예제 #1
0
def cart_session_to_invoice(request, date=None):
    """
    Create an invoice from cart session data
    If date is none, its a proforma invoice
    """

    if date:
        proforma = False
        number = Invoice.next_number()
    else:
        date = now()
        proforma = True
        number = 0
    invoice = Invoice(date=date, proforma=proforma, number=number)
    invoice.buyer = cart_get_buyer(request)
    invoice.address = invoice.buyer.main_address
    invoice.save()
    total = Decimal(0)
    for item in cart_items(request):
        total += item.agreed_price
        item.sale_price = item.agreed_price
        item.state = Item.State.SOLD
        item.invoice = invoice
        item.archive = True
        item.save()
    for charge in cart_charges(request):
        total += charge.amount
        charge.invoice = invoice
        charge.save()
    invoice.total = total
    invoice.save()
    cart_clear(request)
    return invoice
def report_on_site_payments():
    one_month_ago = datetime.datetime.today() - relativedelta(months=1)
    min_date = int(time.mktime(one_month_ago.timetuple()))

    invoices = Invoice.all().filter('payment_type',
                                    Invoice.PAYMENT_ON_SITE).filter(
                                        'date >=', min_date)
    charges = Charge.get((i.charge_key for i in invoices))
    customers = Customer.get((i.order_key.parent() for i in invoices))

    l = [
        '[%(date_str)s][%(customer)s][%(manager)s][%(amount).02f][%(charge_number)s]'
        % dict(customer=c.name,
               manager=i.operator,
               amount=i.amount / 100.0,
               date=i.date,
               date_str=time.ctime(i.date),
               charge_number=charge.charge_number)
        for (i, charge, c) in sorted(zip(invoices, charges, customers),
                                     key=lambda t: t[0].date)
    ]
    body = "\n".join(l) or u"There were no on site payments for the last month"
    logging.info(body)

    server_settings = get_server_settings()
    solution_server_settings = get_solution_server_settings()
    subject = u'On site payments for the last month'
    send_mail(server_settings.dashboardEmail,
              solution_server_settings.shop_payment_admin_emails, subject,
              body)
예제 #3
0
def verify(request):

    # GET request containing pass code as a param
    url_key = request.GET.get('key')
    pass_key_object = PassKey.objects.get(url_key=url_key)
    user_id = pass_key_object.user_id

    # Do a check if there are any previously generated pass_key_objects associated with this user
    previous_pass_keys = PassKey.objects.exclude(
        url_key=pass_key_object.url_key).filter(user_id=user_id)

    # If there are any, delete them one by one
    if len(previous_pass_keys) > 0:
        for i in range(0, len(previous_pass_keys)):
            previous_pass_keys[i].delete()

    # Query for the user's verified field on userAdditionalInfo table
    user_additional_info = UserAdditionalInfo.objects.get(
        user_id=pass_key_object.user_id)

    # Change the verified status to True and save
    user_additional_info.verified = 1
    user_additional_info.save()

    # get rid of url_key_object
    pass_key_object.delete()

    # Creating cart only after the user has been verified
    # Query for the id of the just created user's id number
    new_user = User.objects.filter(id=pass_key_object.user_id)[0]
    new_user_id = new_user.id
    new_user_registered_time = new_user.date_joined

    new_cart_status = InvoiceStatus.objects.get(id=1)

    # Use that id number to create new invoice(cart)
    new_cart = Invoice(user=new_user,
                       status=new_cart_status,
                       date=new_user_registered_time)

    new_cart.save()

    return HttpResponse('User\'s email has been verified',
                        content_type='text/plain')
def _get_invoice_number(charge):
    invoices = list(Invoice.all(keys_only=True).ancestor(charge))
    if len(invoices) == 1:
        return invoices[0].name()
    elif len(invoices) == 0:
        return ""
    else:
        from shop.bizz import PaymentFailedException
        raise PaymentFailedException("Found multiple invoices for charge %r!" %
                                     charge.key())
def _job():
    order_numbers = list(OrderNumber.all())
    charge_numbers = list(ChargeNumber.all())
    invoice_numbers = list(InvoiceNumber.all())
    # Change parent from some OrderNumbers from RegioMangerTeam to LegalEntity.
    # Increase last_number for that legal entity when the parent was a team.
    to_delete = list()
    for ordernumber in order_numbers:
        if ordernumber.parent_key().kind() == RegioManagerTeam.kind():
            # Delete OrderNumber with parent RegioManagerTeam
            logging.warn(
                "Deleting OrderNumber Year %s Original last number: %s" %
                (ordernumber.key().name(), ordernumber.last_number))
            to_delete.append(ordernumber)

    for chargenumber in charge_numbers:
        if chargenumber.parent_key().kind() == RegioManagerTeam.kind():
            logging.warn(
                "Deleting ChargeNumber Year %s Original last number: %s" %
                (chargenumber.key().name(), chargenumber.last_number))
            to_delete.append(chargenumber)

    for invoicenumber in invoice_numbers:
        if invoicenumber.parent_key().kind() == RegioManagerTeam.kind():
            logging.warn(
                "Deleting InvoiceNumber Year %s Original last number: %s" %
                (invoicenumber.key().name(), invoicenumber.last_number))
            # Delete InvoiceNumber with parent RegioManagerTeam
            to_delete.append(invoicenumber)
    db.delete(to_delete)

    for invoice in Invoice.all().filter(
            'date >', 1460635200
            if not DEBUG else 1459870047):  # Thu, 14 Apr 2016 12:00:00 GMT

        def trans():
            new_invoice = Invoice(key_name=InvoiceNumber.next(
                LegalEntity.create_key(invoice.legal_entity_id)),
                                  parent=invoice.parent_key())
            logging.warn("Creating new Invoice %s" % new_invoice.key().name())
            new_invoice.date = invoice.date
            new_invoice.pdf = invoice.pdf
            new_invoice.amount = invoice.amount
            new_invoice.vat_pct = invoice.vat_pct
            new_invoice.total_amount = invoice.total_amount
            new_invoice.paid = invoice.paid
            new_invoice.paid_timestamp = invoice.paid_timestamp
            new_invoice.payment_type = invoice.payment_type
            new_invoice.operator = invoice.operator
            new_invoice.legal_entity_id = invoice.legal_entity_id
            new_invoice.put()
            invoice.deleted = True
            invoice.put()

        run_in_xg_transaction(trans)
def put_invoices():
    all_invoices = list(Invoice.all())
    mobicage_legal_entity_id = get_mobicage_legal_entity()
    for invoices in chunks(all_invoices, 200):
        to_put = list()
        for i in invoices:
            manager = i.operator and RegioManager.get(RegioManager.create_key(i.operator.email()))
            i.legal_entity_id = manager and manager.team.legal_entity_id or mobicage_legal_entity_id.id
            if i.paid and i.paid_timestamp is None:
                i.paid_timestamp = 0 if i.legal_entity_id == mobicage_legal_entity_id.id else now()
            to_put.append(i)
        db.put(invoices)
예제 #7
0
class InvoicePdfHandler(webapp.RequestHandler):
    def get(self):
        from shop.models import Customer, Invoice
        service_user = users.get_current_user()

        customer_id = long(self.request.get("customer_id"))
        order_number = self.request.get("order_number")
        charge_id = long(self.request.get("charge_id"))
        invoice_number = self.request.get("invoice_number")
        download = self.request.get("download", "false") == "true"

        self.response.headers['Content-Type'] = 'application/pdf'
        self.response.headers['Content-Disposition'] = str(
            '%s; filename=invoice_%s.pdf' %
            ("attachment" if download else "inline", invoice_number))

        try:
            customer = Customer.get_by_id(customer_id)
        except CustomerNotFoundException, exception:
            logging.exception(exception)
            self.abort(500)
            return
        if customer.service_email != service_user.email():
            logging.error("%s attempted to download invoice of %s",
                          service_user, customer.service_email)
            self.error(500)
            return

        invoice = db.get(
            Invoice.create_key(customer_id, order_number, charge_id,
                               invoice_number))

        if not invoice or not invoice.pdf:
            logging.error(
                "%s attempted to download invoice %s which does not exist or does not have a pdf generated",
                service_user, invoice_number)
            self.error(500)
            return
        self.response.out.write(invoice.pdf)
예제 #8
0
def create_reseller_invoice_for_legal_entity(legal_entity,
                                             start_date,
                                             end_date,
                                             do_send_email=True):
    """
    Args:
        legal_entity (LegalEntity) 
        start_date (long)
        end_date (long)
        do_send_email (bool)
    """
    if legal_entity.is_mobicage:
        # To avoid a composite index we don't filter on is_mobicage
        return
    solution_server_settings = get_solution_server_settings()
    from_email = solution_server_settings.shop_no_reply_email
    to_emails = solution_server_settings.shop_payment_admin_emails
    mobicage_legal_entity = get_mobicage_legal_entity()
    logging.info(
        'Exporting reseller invoices for legal entity %s(id %d) from %s(%s) to %s(%s)',
        legal_entity.name, legal_entity.id, start_date, time.ctime(start_date),
        end_date, time.ctime(end_date))
    invoices = list(Invoice.all().filter(
        'legal_entity_id',
        legal_entity.id).filter('paid_timestamp >', start_date).filter(
            'paid_timestamp <', end_date).filter('paid', True).filter(
                'payment_type IN',
                (Invoice.PAYMENT_MANUAL, Invoice.PAYMENT_MANUAL_AFTER)))
    start_time = time.strftime('%m/%d/%Y', time.gmtime(int(start_date)))
    end_time = time.strftime('%m/%d/%Y', time.gmtime(int(end_date)))
    if not invoices:
        message = 'No new invoices for reseller %s for period %s - %s' % (
            legal_entity.name, start_time, end_time)
        logging.info(message)
        if do_send_email:
            send_mail(from_email, to_emails, message, message)
        return
    items_per_customer = {}
    customers_to_get = set()
    products = {
        p.code: p
        for p in Product.list_by_legal_entity(legal_entity.id)
    }
    for invoice in invoices:
        # get all subscription order items
        order_items = list(OrderItem.list_by_order(invoice.order_key))
        for item in reversed(order_items):
            product = products[item.product_code]
            # We're only interested in subscription items
            if product.is_subscription or product.is_subscription_extension or product.is_subscription_discount:
                if invoice.customer_id not in items_per_customer:
                    items_per_customer[invoice.customer_id] = []
                    customers_to_get.add(
                        Customer.create_key(invoice.customer_id))
                items_per_customer[invoice.customer_id].append(item)
            else:
                order_items.remove(item)
    if not customers_to_get:
        message = 'No new invoices containing subscriptions for reseller %s for period %s - %s' % (
            legal_entity.name, start_time, end_time)
        logging.info(message)
        if do_send_email:
            send_mail(from_email, to_emails, message, message)
        return
    customers = {c.id: c for c in db.get(customers_to_get)}
    product_totals = {}
    for customer_id in items_per_customer:
        items = items_per_customer[customer_id]
        for item in items:
            if item.product_code not in product_totals:
                product_totals[item.product_code] = {
                    'count': 0,
                    'price': int(item.price * legal_entity.revenue_percent)
                }
            product_totals[item.product_code]['count'] += item.count
    total_amount = 0
    for product in product_totals:
        p = product_totals[product]
        price = p['count'] * p['price']
        p['total_price'] = format_currency(
            price / 100.,
            legal_entity.currency_code,
            locale=mobicage_legal_entity.country_code)
        total_amount += price
    total_amount_formatted = format_currency(
        total_amount / 100.,
        legal_entity.currency_code,
        locale=mobicage_legal_entity.country_code)
    vat_amount = total_amount / mobicage_legal_entity.vat_percent if mobicage_legal_entity.country_code == legal_entity.country_code else 0
    vat_amount_formatted = format_currency(
        vat_amount / 100.,
        legal_entity.currency_code,
        locale=mobicage_legal_entity.country_code)
    from_date = format_datetime(datetime.utcfromtimestamp(start_date),
                                locale=SHOP_DEFAULT_LANGUAGE,
                                format='dd/MM/yyyy HH:mm')
    until_date = format_datetime(datetime.utcfromtimestamp(end_date),
                                 locale=SHOP_DEFAULT_LANGUAGE,
                                 format='dd/MM/yyyy HH:mm')

    solution_server_settings = get_solution_server_settings()
    template_variables = {
        'products':
        products,
        'customers':
        customers,
        'invoices':
        invoices,
        'items_per_customer':
        items_per_customer,
        'product_totals':
        product_totals.items(),
        'mobicage_legal_entity':
        mobicage_legal_entity,
        'legal_entity':
        legal_entity,
        'language':
        SHOP_DEFAULT_LANGUAGE,
        'from_date':
        from_date,
        'until_date':
        until_date,
        'revenue_percent':
        legal_entity.revenue_percent,
        'vat_amount_formatted':
        vat_amount_formatted,
        'total_amount_formatted':
        total_amount_formatted,
        'logo_path':
        '../html/img/osa_white_en_250.jpg',
        'tos_link':
        '<a href="%s">%s</a>' %
        (solution_server_settings.shop_privacy_policy_url,
         solution_server_settings.shop_privacy_policy_url)
    }
    source_html = SHOP_JINJA_ENVIRONMENT.get_template(
        'invoice/reseller_invoice.html').render(template_variables)
    output_stream = StringIO()
    pisa.CreatePDF(src=source_html,
                   dest=output_stream,
                   path='%s/invoice' % SHOP_TEMPLATES_FOLDER)
    invoice_pdf_contents = output_stream.getvalue()
    output_stream.close()
    # Create an order, order items, charge and invoice.
    _now = now()
    customer = legal_entity.get_or_create_customer()
    mobicage_team = RegioManagerTeam.get_mobicage()

    def trans():
        to_put = list()
        order_number = OrderNumber.next(mobicage_legal_entity)
        order_key = db.Key.from_path(Order.kind(),
                                     order_number,
                                     parent=customer.key())
        order = Order(key=order_key)
        order.contact_id = legal_entity.contact_id
        order.date = _now
        order.vat_pct = mobicage_legal_entity.vat_percent if legal_entity.country_code == mobicage_legal_entity.country_code else 0
        order.amount = int(round(total_amount))
        order.vat = int(round(vat_amount))
        order.total_amount = int(round(total_amount + vat_amount))
        order.is_subscription_order = False
        order.is_subscription_extension_order = False
        order.team_id = mobicage_team.id
        order.manager = customer.manager
        order.status = Order.STATUS_SIGNED
        to_put.append(order)

        for i, (product_code, item) in enumerate(product_totals.iteritems()):
            order_item = OrderItem(parent=order_key)
            order_item.number = i + 1
            order_item.comment = products[product_code].default_comment(
                SHOP_DEFAULT_LANGUAGE)
            order_item.product_code = product_code
            order_item.count = item['count']
            order_item.price = item['price']
            to_put.append(order_item)

        charge_key = Charge.create_key(allocate_id(Charge), order_number,
                                       customer.id)
        charge = Charge(key=charge_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.charge_number = ChargeNumber.next(mobicage_legal_entity)
        charge.currency_code = legal_entity.currency_code
        to_put.append(charge)

        invoice_number = InvoiceNumber.next(mobicage_legal_entity)
        invoice = Invoice(key_name=invoice_number,
                          parent=charge,
                          amount=charge.amount,
                          vat_pct=charge.vat_pct,
                          vat=charge.vat,
                          total_amount=charge.total_amount,
                          currency_code=legal_entity.currency_code,
                          date=_now,
                          payment_type=Invoice.PAYMENT_MANUAL_AFTER,
                          operator=charge.manager,
                          paid=False,
                          legal_entity_id=mobicage_legal_entity.id,
                          pdf=invoice_pdf_contents)
        charge.invoice_number = invoice_number
        to_put.append(invoice)
        put_and_invalidate_cache(*to_put)
        return order, charge, invoice

    order, charge, invoice = run_in_xg_transaction(trans)

    if do_send_email:
        serving_url = '%s/internal/shop/invoice/pdf?customer_id=%d&order_number=%s&charge_id=%d&invoice_number=%s' % (
            get_server_settings().baseUrl, customer.id, order.order_number,
            charge.id, invoice.invoice_number)
        subject = 'New reseller invoice for %s, %s - %s' % (
            legal_entity.name, start_time, end_time)
        body_text = 'A new invoice is available for reseller %s for period %s to %s here: %s' % (
            legal_entity.name, start_time, end_time, serving_url)

        send_mail(from_email, to_emails, subject, body_text)
예제 #9
0
    def trans():
        to_put = list()
        order_number = OrderNumber.next(mobicage_legal_entity)
        order_key = db.Key.from_path(Order.kind(),
                                     order_number,
                                     parent=customer.key())
        order = Order(key=order_key)
        order.contact_id = legal_entity.contact_id
        order.date = _now
        order.vat_pct = mobicage_legal_entity.vat_percent if legal_entity.country_code == mobicage_legal_entity.country_code else 0
        order.amount = int(round(total_amount))
        order.vat = int(round(vat_amount))
        order.total_amount = int(round(total_amount + vat_amount))
        order.is_subscription_order = False
        order.is_subscription_extension_order = False
        order.team_id = mobicage_team.id
        order.manager = customer.manager
        order.status = Order.STATUS_SIGNED
        to_put.append(order)

        for i, (product_code, item) in enumerate(product_totals.iteritems()):
            order_item = OrderItem(parent=order_key)
            order_item.number = i + 1
            order_item.comment = products[product_code].default_comment(
                SHOP_DEFAULT_LANGUAGE)
            order_item.product_code = product_code
            order_item.count = item['count']
            order_item.price = item['price']
            to_put.append(order_item)

        charge_key = Charge.create_key(allocate_id(Charge), order_number,
                                       customer.id)
        charge = Charge(key=charge_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.charge_number = ChargeNumber.next(mobicage_legal_entity)
        charge.currency_code = legal_entity.currency_code
        to_put.append(charge)

        invoice_number = InvoiceNumber.next(mobicage_legal_entity)
        invoice = Invoice(key_name=invoice_number,
                          parent=charge,
                          amount=charge.amount,
                          vat_pct=charge.vat_pct,
                          vat=charge.vat,
                          total_amount=charge.total_amount,
                          currency_code=legal_entity.currency_code,
                          date=_now,
                          payment_type=Invoice.PAYMENT_MANUAL_AFTER,
                          operator=charge.manager,
                          paid=False,
                          legal_entity_id=mobicage_legal_entity.id,
                          pdf=invoice_pdf_contents)
        charge.invoice_number = invoice_number
        to_put.append(invoice)
        put_and_invalidate_cache(*to_put)
        return order, charge, invoice
예제 #10
0
def checkout(request):

    # if cart is empty redirect back to cart page- don't go to checkout
    if request.cart.is_empty():
        return HttpResponseRedirect('/cart/')

    checkout_step = request.session.get('checkout_step', 1)

    if request.method == 'POST':
        action = request.POST.get('action')

        if action == 'back':
            if checkout_step == 1:

                if 'checkout_step' in request.session:
                    del request.session['checkout_step']

                if 'token' in request.session:
                    del request.session['token']

                if 'invoice' in request.session:
                    del request.session['invoice']

                return HttpResponseRedirect('/cart/')

            if checkout_step > 1:
                request.session['checkout_step'] = checkout_step - 1
                return HttpResponseRedirect('/cart/checkout/')

    if checkout_step == 1:

        if request.method == "POST":
            form = CheckoutForm(data=request.POST)

            if form.is_valid():
                # if the form was valid, proceed to checkout step two.
                # make sure to save stripe token and order information somewhere!

                token = stripe.Token.retrieve(request.POST.get('stripe_token'))

                request.session['token'] = token

                invoice = Invoice()
                invoice.name_first = form.cleaned_data['first_name']
                invoice.name_last = form.cleaned_data['last_name']
                invoice.street_1 = form.cleaned_data['address_1']
                invoice.street_2 = form.cleaned_data['address_2']
                invoice.city = form.cleaned_data['city']
                invoice.country = form.cleaned_data['country']
                invoice.province = form.cleaned_data['province']
                invoice.postal_code = form.cleaned_data['postal_code']
                invoice.phone = form.cleaned_data['phone_number']
                invoice.email = form.cleaned_data['email']
                invoice.stripe_token = request.POST.get('stripe_token')
                invoice.card_last4 = token['card']['last4']
                invoice.card_brand = token['card']['brand']

                # convert the Invoice into a dictionary for serialization into session (we'll change it back later)
                request.session['invoice'] = model_to_dict(invoice)

                request.session['checkout_step'] = 2
                return HttpResponseRedirect("/cart/checkout/")

        else:

            invoice_dict = request.session.get('invoice')

            initial = {}
            if invoice_dict:
                invoice = Invoice(**invoice_dict)
                initial['first_name'] = invoice.name_first
                initial['last_name'] = invoice.name_last
                initial['address_1'] = invoice.street_1
                initial['address_2'] = invoice.street_2
                initial['city'] = invoice.city
                initial['country'] = invoice.country
                initial['province'] = invoice.province
                initial['postal_code'] = invoice.postal_code
                initial['phone_number'] = invoice.phone
                initial['email'] = invoice.email

            form = CheckoutForm(initial=initial)

        context = {'form': form}

        return render(request, 'shop/checkout_step_1.html', context)

    # process checkout step 2
    elif checkout_step == 2:

        invoice_dict = request.session['invoice']
        invoice = Invoice(**invoice_dict)

        # handle confirm page submitted
        if request.method == 'POST':

            with transaction.atomic():
                # set the calculated fields and save
                invoice.shipping = Decimal("10.00")
                invoice.tax = request.cart.tax()
                invoice.subtotal = request.cart.subtotal()
                invoice.total = request.cart.total() + invoice.shipping
                invoice.save()

                invoice.create_items(cart=request.cart)

                request.cart.adjust_stock()

                total_cents = int(invoice.total * 100)
                stripe.Charge.create(amount=total_cents,
                                     currency='cad',
                                     source=invoice.stripe_token,
                                     description='Test Charge from checkout')

                del request.session['checkout_step']
                del request.session['invoice']
                del request.session['token']
                request.cart.delete()

                # create invoice,
                # charge stripe token for cart total amount in cents
                # remove stock from inventory
                # clear checkout step from session
                # clear invoice from session

                invoice.send_email()

            messages.success(request, "Invoice Successfully sent.")
            return HttpResponseRedirect('/invoices/%s/' % invoice.id)

        else:
            # use some dictionary unpacking magic to turn our invoice_dict back into an Invoice
            context = {'invoice': invoice, 'token': request.session['token']}
            return render(request, 'shop/checkout_step_2.html', context)
예제 #11
0
def export_invoices(year, month):
    start_date = datetime.date(year, month, 1)
    end_date = start_date + relativedelta(months=1)

    qry = Invoice.all() \
        .filter('date >=', get_epoch_from_datetime(start_date)) \
        .filter('date <', get_epoch_from_datetime(end_date))

    invoices = list()
    order_keys = set()
    all_products = dict(((p.code, p) for p in Product.all()))
    for invoice_model in qry:
        i = model_to_dict(invoice_model)
        order_key = invoice_model.parent_key().parent()
        i['invoice_number'] = invoice_model.invoice_number
        i['order_items'] = map(model_to_dict,
                               OrderItem.all().ancestor(order_key))
        if invoice_model.charge.is_recurrent:
            # only apply recurrent charges
            for order_item in reversed(i['order_items']):
                order_item[
                    'count'] = invoice_model.charge.subscription_extension_length or 1
                product = all_products[order_item['product_code']]
                if not (product.is_subscription_discount
                        or product.is_subscription
                        or product.is_subscription_extension):
                    i['order_items'].remove(order_item)

            # add the subscription extensions like XCTY
            if invoice_model.charge.subscription_extension_order_item_keys:
                known_extension_item_keys = [
                    item['_key'] for item in i['order_items']
                ]

                extension_order_items = db.get(
                    invoice_model.charge.subscription_extension_order_item_keys
                )
                for item in extension_order_items:
                    item.count = 1
                    if str(item.key()) not in known_extension_item_keys:
                        i['order_items'].append(model_to_dict(item))

        i['order_key'] = order_key
        i['currency'] = invoice_model.currency_code
        order_keys.add(order_key)
        invoices.append(i)

    orders = {o.key(): o for o in db.get(order_keys)}

    contact_keys = set()
    customer_keys = set()
    for i in invoices:
        order_model = orders[i['order_key']]
        del i['order_key']
        i['customer_key'] = order_model.customer_key
        i['contact_key'] = order_model.contact_key
        i['manager'] = None if not order_model.manager else order_model.manager.email(
        )
        customer_keys.add(order_model.customer_key)
        contact_keys.add(order_model.contact_key)

    del orders

    customer_and_contact_models = {
        m.key(): m
        for m in db.get(customer_keys.union(contact_keys))
    }

    # filter invoices for customers of resellers
    reseller_ids = [
        k.id() for k in LegalEntity.list_non_mobicage(keys_only=True)
    ]
    reseller_team_ids = [
        t.id for t in RegioManagerTeam.all().filter('legal_entity_id IN',
                                                    reseller_ids)
    ]

    for i in reversed(invoices):
        customer_model = customer_and_contact_models[i['customer_key']]
        if customer_model.team_id in reseller_team_ids:
            invoices.remove(i)
            continue
        del i['customer_key']
        i['customer'] = model_to_dict(customer_model)
        contact_model = customer_and_contact_models[i['contact_key']]
        del i['contact_key']
        i['contact'] = model_to_dict(contact_model)

    del customer_and_contact_models

    return sorted(invoices,
                  key=lambda i: int(i['invoice_number'].split('.')[-1]))
예제 #12
0
def getPostCart(request):

    # User needs to be logged in, or exits the method and returns -1
    if not request.user.is_authenticated:

        return HttpResponse('{"status_code": -1, "message": "Login required"}',
                            content_type='application/json')

    if request.method == 'GET':

        try:

            # Query for the 'cart' status invoice. If there isn't one, create one
            cart_list = Invoice.objects.filter(status_id=1,
                                               user_id=request.user.id)

            if len(cart_list) == 0:
                cart = Invoice(date=datetime.now(),
                               user_id=request.user.id,
                               status_id=1)
            # If there is an existing cart, use that
            else:
                cart = cart_list[0]

            # Query for every item existing in the cart
            lineItems = LineItem.objects.filter(invoice_id=cart.invoice_id)

            # Create an empty array with the length equivalent to existing line items in cart
            data = [None] * len(lineItems)

            # Create dict of line items in cart and append them to the empty array created above
            for i in range(0, len(lineItems)):

                # Per one item, query for its item name and item image
                item = Item.objects.get(item_id=lineItems[i].item_id)
                item_name = item.name
                item_image = item.image

                data[i] = {
                    'line_item_id': lineItems[i].line_item,
                    'invoice_id': lineItems[i].invoice_id,
                    'item_id': lineItems[i].item_id,
                    'item_name': item_name,
                    'item_image': str(item_image),
                    'line_item_price': float(lineItems[i].line_item_price),
                    'quantity': lineItems[i].quantity,
                    'status': lineItems[i].status_id
                }

            # Convert the array into transferable json data
            data = json.dumps(data)

            print('Successfully fetched line items from current cart')

            # Return the json data
            return HttpResponse(data, content_type='application/json')

        except (KeyError):

            return HttpResponse('{"status_code": -6, "message": "Key error"}',
                                content_type='application/json')

    elif request.method == 'POST':

        try:

            # Retrieve data from user request
            data = json.loads(request.body)

            # Cart
            current_cart = queryCart(request)

            # Check if the picked item belongs to the current logged in user. If so, terminate process and throw an error code
            item_id = data['item_id']
            item_owner_id = Item.objects.get(item_id=item_id).user_id
            current_user_id = request.user.id

            if item_owner_id == current_user_id:
                return HttpResponse(
                    '{"status_code": -10, "message": "Attempted to add own item into cart"}',
                    content_type='application/json')

            # Check if item_id input is of the right data type: int

            # try:
            #     int(data['item_id'])
            # except:
            #     return HttpResponse('-7', content_type='application/json')

            if not type(data['item_id']) == int:

                return HttpResponse(
                    '{"status_code": -7, "message": "Wrong data type input"}',
                    content_type='application/json')

            # Check if there is already an entry with  line_item_id of the data sent by the user
            original_entry_list = LineItem.objects.filter(
                item_id=data['item_id'], invoice_id=current_cart.invoice_id)

            # If there is already a same lineitem existing in cart, this is an update to quantity
            # Update
            if len(original_entry_list) > 0:

                original_entry = original_entry_list[0]

                if 'quantity' in data.keys():

                    # Check if quantity input is of right data type: int
                    if not type(data['quantity']) == int:

                        return HttpResponse(
                            '{"status_code": -7, "message": "Wrong data type input"}',
                            content_type='application/json')

                    original_entry.quantity = data['quantity']

                original_entry.line_item_price = updateLineItemPrice(
                    original_entry.quantity, original_entry.item_id)

                original_entry.save()

            # If there is no line_item with the same line_item_id in cart, it's a post

            # Post(Putting items into your cart)
            else:

                # Query for this user's cart
                cart = Invoice.objects.get(status_id=1,
                                           user_id=request.user.id)

                invoice_id = cart.invoice_id
                item_id = data['item_id']
                quantity = data['quantity']

                # Check if both of the passed in data are of the right type: int
                if not type(item_id) == int or not type(quantity) == int:

                    return HttpResponse(
                        '{"status_code": -7, "message": "Wrong data type input"}',
                        content_type='application/json')

                # Calculate the total line_item_price
                line_item_price = updateLineItemPrice(quantity, item_id)

                # Create and save new lineitem data
                new_line_item = LineItem(status_id=1,
                                         invoice_id=invoice_id,
                                         item_id=item_id,
                                         line_item_price=line_item_price,
                                         quantity=quantity)

                new_line_item.save()

            print('The lineItem has been added to the cart successfully')

            return HttpResponse('{"status_code": 0, "message": "Success"}',
                                content_type='application/json')

        except (KeyError):

            print("There was a key error")

            return HttpResponse('{"status_code": -6, "message": "Key error"}',
                                content_type='application/json')
def delete_deleted_invoices():
    db.delete(Invoice.all(keys_only=True).filter('deleted', True))
    logging.error("Please remove the Invoice.deleted property")
 def trans():
     new_invoice = Invoice(key_name=InvoiceNumber.next(
         LegalEntity.create_key(invoice.legal_entity_id)),
                           parent=invoice.parent_key())
     logging.warn("Creating new Invoice %s" % new_invoice.key().name())
     new_invoice.date = invoice.date
     new_invoice.pdf = invoice.pdf
     new_invoice.amount = invoice.amount
     new_invoice.vat_pct = invoice.vat_pct
     new_invoice.total_amount = invoice.total_amount
     new_invoice.paid = invoice.paid
     new_invoice.paid_timestamp = invoice.paid_timestamp
     new_invoice.payment_type = invoice.payment_type
     new_invoice.operator = invoice.operator
     new_invoice.legal_entity_id = invoice.legal_entity_id
     new_invoice.put()
     invoice.deleted = True
     invoice.put()
예제 #15
0
파일: views.py 프로젝트: Comp199/cartotron
def checkout(request):

    # if cart is empty redirect back to cart page- don't go to checkout
    if request.cart.is_empty():
        return HttpResponseRedirect('/cart/')

    checkout_step = request.session.get('checkout_step', 1)

    if request.method == 'POST':
        action = request.POST.get('action')

        if action == 'back':
            if checkout_step == 1:

                if 'checkout_step' in request.session:
                    del request.session['checkout_step']

                if 'token' in request.session:
                    del request.session['token']

                if 'invoice' in request.session:
                    del request.session['invoice']

                return HttpResponseRedirect('/cart/')

            if checkout_step > 1:
                request.session['checkout_step'] = checkout_step - 1
                return HttpResponseRedirect('/cart/checkout/')

    if checkout_step == 1:

        if request.method == "POST":
            form = CheckoutForm(data=request.POST)

            if form.is_valid():
                # if the form was valid, proceed to checkout step two.
                # make sure to save stripe token and order information somewhere!

                token = stripe.Token.retrieve(request.POST.get('stripe_token'))

                request.session['token'] = token

                invoice = Invoice()
                invoice.name_first = form.cleaned_data['first_name']
                invoice.name_last = form.cleaned_data['last_name']
                invoice.street_1 = form.cleaned_data['address_1']
                invoice.street_2 = form.cleaned_data['address_2']
                invoice.city = form.cleaned_data['city']
                invoice.country = form.cleaned_data['country']
                invoice.province = form.cleaned_data['province']
                invoice.postal_code = form.cleaned_data['postal_code']
                invoice.phone = form.cleaned_data['phone_number']
                invoice.email = form.cleaned_data['email']
                invoice.stripe_token = request.POST.get('stripe_token')
                invoice.card_last4 = token['card']['last4']
                invoice.card_brand = token['card']['brand']

                # convert the Invoice into a dictionary for serialization into session (we'll change it back later)
                request.session['invoice'] = model_to_dict(invoice)

                request.session['checkout_step'] = 2
                return HttpResponseRedirect("/cart/checkout/")

        else:

            invoice_dict = request.session.get('invoice')

            initial = {}
            if invoice_dict:
                invoice = Invoice(**invoice_dict)
                initial['first_name'] = invoice.name_first
                initial['last_name'] = invoice.name_last
                initial['address_1'] = invoice.street_1
                initial['address_2'] = invoice.street_2
                initial['city'] = invoice.city
                initial['country'] = invoice.country
                initial['province'] = invoice.province
                initial['postal_code'] = invoice.postal_code
                initial['phone_number'] = invoice.phone
                initial['email'] = invoice.email

            form = CheckoutForm(initial=initial)

        context = {'form': form}

        return render(request, 'shop/checkout_step_1.html', context)

    # process checkout step 2
    elif checkout_step == 2:

        invoice_dict = request.session['invoice']
        invoice = Invoice(**invoice_dict)

        # handle confirm page submitted
        if request.method == 'POST':

            with transaction.atomic():
                # set the calculated fields and save
                invoice.shipping = Decimal("10.00")
                invoice.tax = request.cart.tax()
                invoice.subtotal = request.cart.subtotal()
                invoice.total = request.cart.total() + invoice.shipping
                invoice.save()

                invoice.create_items(cart=request.cart)

                request.cart.adjust_stock()

                total_cents = int(invoice.total*100)
                stripe.Charge.create(
                    amount=total_cents,
                    currency='cad',
                    source=invoice.stripe_token,
                    description='Test Charge from checkout'
                )

                del request.session['checkout_step']
                del request.session['invoice']
                del request.session['token']
                request.cart.delete()

                # create invoice,
                # charge stripe token for cart total amount in cents
                # remove stock from inventory
                # clear checkout step from session
                # clear invoice from session

                invoice.send_email()

            messages.success(request, "Invoice Successfully sent.")
            return HttpResponseRedirect('/invoices/%s/' % invoice.id)

        else:
            # use some dictionary unpacking magic to turn our invoice_dict back into an Invoice
            context = {
                'invoice': invoice,
                'token': request.session['token']
            }
            return render(request, 'shop/checkout_step_2.html', context)
예제 #16
0
    def import_stock(self, ws):
        """ Read stock sheet, create missing items, update purchases and invoices """
        self.stdout.write(">> Start import stock")
        # Item.objects.filter(category__isnull=True).delete()
        # Purchase.objects.all().delete()
        rowgen = ws.rows
        cols = [c.value for c in next(rowgen)]
        try:
            col_pdate = cols.index("Pdate")
            col_vendor = cols.index("Vendor")
            col_vat = cols.index("VAT")
            col_lot = cols.index("Lot No.")
            col_prem = cols.index("Prem")
            col_cost_lot = cols.index("CostLot")
            col_cost_item = cols.index("CostItem")
            col_cost_rest = cols.index("Cost Rest")
            col_stock_no = cols.index("Stock no.")
            col_description = cols.index("Description")
            col_price = cols.index("Price")
            col_sale_date = cols.index("SaleDate")
            col_inv_no = cols.index("InvNo")
            col_purchaser = cols.index("Purchaser")
            col_section = cols.index("Section Text")
        except ValueError as e:
            self.stdout.write(f"Header error in sheet {ws.title}:\n{str(e)}")
            raise
        exists = 0
        created = 0
        vendors_created = 0
        inv_created = 0
        last_vendor = None
        last_pdate = None
        try:
            for row in rowgen:
                row_number = row[0].row
                ref = str(row[col_stock_no].value)
                if ref[0].isdigit():
                    ref = "#" + ref
                description = row[col_description].value
                price, text = parse_decimal(row[col_price].value)
                if text:
                    self.stdout.write(
                        f"Ignoring row: {row[0].row} Price = {text}")
                    continue
                inv_no = row[col_inv_no].value
                sale_date = row[col_sale_date].value
                archive = False
                if inv_no and sale_date:
                    archive = True
                    sale_date = parse_date(sale_date)
                vat, _ = parse_decimal(row[col_vat].value)
                margin_scheme = not vat
                lot_number = row[col_lot].value
                cost_item, _ = parse_decimal(row[col_cost_item].value)
                cost_lot, _ = parse_decimal(row[col_cost_lot].value)
                cost_rest, _ = parse_decimal(row[col_cost_rest].value)
                premium, _ = parse_decimal(row[col_prem].value)
                pdate = parse_date(row[col_pdate].value)
                vendor_name = parse_special(row[col_vendor].value)
                # Find or create a vendor
                vendor = None
                if vendor_name:
                    key = vendor_key(vendor_name)
                    vendors = Contact.objects.filter(notes=key)
                    l = len(vendors)
                    if l == 0:
                        name, address = parse_name_address(vendor_name,
                                                           vendor=True)
                        vendor = Contact.objects.create(company=name,
                                                        notes=key,
                                                        vendor=True)
                        address = Address.objects.create(address=address,
                                                         contact=vendor)
                        vendor.main_address = address
                        vendor.save()
                        vendors_created += 1
                    elif l == 1:
                        vendor = vendors[0]
                    else:
                        self.stdout.write(
                            f"Info row: {row_number} Multiple vendors {l}: {vendor}"
                        )
                else:
                    # Missing vendor uses previous vendor if same purchase date
                    vendor = last_vendor
                    # if last_pdate == pdate:
                    # self.stdout.write(
                    #     f"Info row: {row_number} {vendor.name} different date"
                    # )

                # Find or create an item and add costs
                item = None
                try:
                    item = Item.objects.get(ref=ref)
                    if not item.sale_price:
                        item.sale_price = 0
                    if item.sale_price != price:
                        if not item.archive:
                            self.stdout.write(
                                f"Info row: {row_number} Web price: {item.sale_price} Excel price: {price}"
                            )
                    exists += 1
                except Item.DoesNotExist:
                    self.stdout.write(f"Item {ref} {description} not found")
                    item = Item.objects.create(
                        name=truncate(description),
                        ref=ref,
                        description=description,
                        sale_price=Decimal(price),
                        category=None,
                        image=None,
                        archive=archive,
                        visible=False,
                    )
                    created += 1
                if item:
                    item.cost_price = cost_item
                    item.restoration_cost = cost_rest

                    # Create a purchase record and link item to it
                    try:
                        purchase = Purchase.objects.get(vendor=vendor,
                                                        date=pdate)
                    except Purchase.DoesNotExist:
                        purchase = Purchase.objects.create(
                            date=pdate,
                            invoice_number=0,
                            invoice_total=0,
                            buyers_premium=premium,
                            vendor=vendor,
                            margin_scheme=margin_scheme,
                            vat=vat,
                        )
                    # Find or create a lot
                    try:
                        lot = Lot.objects.get(purchase=purchase,
                                              number=lot_number)
                    except Lot.DoesNotExist:
                        lot = Lot.objects.create(purchase=purchase,
                                                 number=lot_number,
                                                 cost=cost_lot)
                    item.lot = lot
                    # if sold, update invoice with item
                    if inv_no:
                        try:
                            invoice = Invoice.objects.get(number=inv_no)
                            item.invoice = invoice
                        except Invoice.DoesNotExist:
                            invoice = Invoice(
                                date=pdate,
                                number=inv_no,
                                buyer=None,
                                total=0,
                                paid=True,
                            )
                            inv_created += 1
                        item.invoice = invoice
                        print(invoice.total, item.sale_price)
                        invoice.total += item.sale_price
                        invoice.save()
                    item.save()
                    last_pdate = pdate
                    last_vendor = vendor

        except Exception as e:
            self.stdout.write(
                f"Exception in {ws.title} row {row_number}\n{str(e)}")
            raise
        # Calculate the invoice total for every purchase
        for purchase in Purchase.objects.all():
            total = purchase.buyers_premium
            for lot in purchase.lot_set.all():
                total += lot.cost
            purchase.invoice_total = total
            purchase.save()

        self.stdout.write(
            f"Items exists: {exists} Created: {created} Vendors created {vendors_created} Invoices created: {inv_created}"
        )
예제 #17
0
def submitCart(request):

    # Check if a user is logged in
    if not request.user.is_authenticated:

        return HttpResponse('{"status_code": -1, "message": "Login required"}', content_type='application/json')

    # Query and check if there are more item stocks than requested quantity of the line item

    # Query and change the status for every line item that was in the cart to 2

    # Get the id of current cart
    current_cart_id = Invoice.objects.get(
        status_id=1, user_id=request.user.id).invoice_id

    line_items_in_cart = LineItem.objects.filter(
        invoice=current_cart_id)

    # Query for line items that has a status of 2(not saved)
    line_items_in_cart_not_saved = LineItem.objects.filter(
        invoice=current_cart_id, status_id=1)

    # If there are no items ready for purchase in the cart, abort submitting
    if len(line_items_in_cart_not_saved) == 0:

        return HttpResponse('{"status_code": -11, "message": "No line item with status 1 to submit"}', content_type='application/json')

    # Do stock check first here and return -1 error if stock is less than quantity
    for line_item in line_items_in_cart:

        item_id = line_item.item_id
        quantity = line_item.quantity

        item_stock = Item.objects.get(item_id=item_id).stock

        if item_stock < quantity:

            # Create and save notification item for this user

            new_notification = Notification(
                notification_body="There are not enough stocks of this item.", user=request.user, line_item_id=line_item.line_item)

            new_notification.save()

            return HttpResponse('{"status_code": -2, "message": "Not enough stock"}', content_type='application/json')

    # Create a new cart under this user's user_id

    new_cart = Invoice(user=request.user, status_id=1,
                       date=datetime.now())

    new_cart.save()

    # Change status for lineitem and stocks for item
    for line_item in line_items_in_cart:

        # Query for the item of the line_item
        item_id = line_item.item_id
        quantity = line_item.quantity
        status = line_item.status_id

        item = Item.objects.get(item_id=item_id)
        seller_id = item.user_id

        # If there are more stocks than requested quantity,
        # and the status of the item is 1,
        # go through with changing the status and calculating the item stocks
        if status == 1:
            line_item.status_id = 2

            # Create a notification and send it to the seller of the item
            seller_notification = Notification(
                user_id=seller_id, notification_body="A buyer would like to purchase this item.", line_item_id=line_item.line_item)

            seller_notification.save()

            line_item.save()

            # update the stock of the item and save the item
            item.stock = item.stock - quantity
            item.save()

        # Change invoice_id of the line_item with a status of 6 to the one of the new cart
        elif status == 5:

            # Newly created cart
            new_cart = Invoice.objects.filter(
                user_id=request.user.id, status_id=1).order_by('-invoice_id')[0]
            line_item.invoice_id = new_cart.invoice_id
            line_item.save()

    # Query for the invoice with status of cart(1) and switch the status to paid(2)
    # Don't exactly now why this query gets more than 1? Maybe it didn't?
    cart = Invoice.objects.get(
        status_id=1, user_id=request.user.id, invoice_id=current_cart_id)

    cart.status_id = 2

    cart.save()

    return HttpResponse('{"status_code": 0, "message": "Success"}', content_type='application/json')