Exemplo n.º 1
0
    def _create_order(self, request):
        """
        Create new order.
        """
        # determine form class
        order_model = get_order_model()
        formclass = order_model.get_form()

        # create form
        if request.method == 'POST':
            form = formclass(request.POST)
        else:
            form = formclass()

        form.configure(request, None, False)

        # validate form
        if request.method == 'POST' and form.is_valid():
            d = form.cleaned_data

            # create new order
            order = order_model.create_empty_customer_not_present(request)

            # redirect to edit page
            return self._redirect(request, 'edit', order)

        return {'form': form, 'edit': False}
Exemplo n.º 2
0
    def generate_order_id(self, order):
        """
        Generate a unique order id.
        """
        order_model = get_order_model()
        found = False
        i = 0
        while not found:
            # generate random ref. number for the given order
            if self._request.settings.order_id == 'numeric':
                order_id = self.generate_numeric_order_id(order)
            elif self._request.settings.order_id == 'seq':
                order_id = self.generate_seq_order_id(order)
            else:
                order_id = self.generate_alpha_order_id(order)

            # add prefix/suffix
            if self._request.settings.order_id_prefix:
                order_id = '%s%s' % (self._request.settings.order_id_prefix,
                                     order_id)
            if self._request.settings.order_id_suffix:
                order_id = '%s%s' % (order_id,
                                     self._request.settings.order_id_suffix)

            # make sure it is unqiue
            found = (order_model.objects.filter(
                order_id=order_id).count() == 0)

            i += 1
            if i > 100:
                raise UserWarning(
                    'Fatal: Unable to find another unique order id after %d iterations!'
                    % i)
        return order_id
Exemplo n.º 3
0
def shipping_notes(request, secret_id):
    """
    Display for PDF creation of the shipping note/status
    """
    basket = Basket(request)
    order = get_object_or_404(get_order_model(), secret_id=secret_id)

    return {'order': order}
Exemplo n.º 4
0
 def generate_seq_order_id(self, order):
     """
     Generate unique order id based on what looks like a sequential number.
     """
     rnd = self.get_random()
     n = get_order_model().objects.all().count()
     oid = rnd.randint(1234, n + (2 * 1234))
     return '%d' % oid
Exemplo n.º 5
0
    def cancel(self, request):
        order_id = request.GET.get('pk')
        edit_order = request.GET.get('edit_order', 'false') == 'true'
        order = get_object_or_404(get_order_model(), pk=order_id)

        def _do_redirect():
            if edit_order:
                return self._redirect(request, 'edit', order)
            else:
                return self._redirect(request, 'index')

        # cannot cancel if we are awaiting payment approval/rejection
        if order.approval_status == OrderBase.APPROVAL_STATUS_WAITING:
            messages.add_message(
                request, messages.ERROR,
                'Order <em>%s</em> is awaiting approval. Please accept or reject this order.'
                % order.order_id)
            return _do_redirect()

        # cannot cancel if the order has already been cancelled
        if order.cancelled:
            messages.add_message(
                request, messages.ERROR,
                'Order <em>%s</em> has already been cancelled.' %
                order.order_id)
            return _do_redirect()

        # process cancellation form
        if request.method == 'POST':
            form = CancelOrderForm(request.POST)
        else:
            form = CancelOrderForm()

        if request.method == 'POST':
            if request.POST.get('cubane_form_cancel', '0') == '1':
                _do_redirect()

            if form.is_valid():
                (success,
                 msg) = order.cancel(request,
                                     form.cleaned_data.get('cancel_msg'))
                if success:
                    messages.add_message(
                        request, messages.SUCCESS,
                        'Order <em>%s</em> has been cancelled.' %
                        order.order_id)
                else:
                    messages.add_message(
                        request, messages.ERROR,
                        'We were unable to cancel the order <em>%s</em>: %s' %
                        (order.order_id, msg))

                _do_redirect()

        return {'order': order, 'form': form}
Exemplo n.º 6
0
    def account_orders(self, request, status):
        order_model = get_order_model()

        if status == 'processing':
            orders = order_model.objects.get_processing_orders(user=request.user)
        else:
            orders = order_model.objects.get_complete_orders(user=request.user)

        return {
            'account_section': True,
            'orders': orders,
            'status': status,
        }
Exemplo n.º 7
0
    def account_index(self, request):
        profile = get_customer_model().objects.get(user=request.user)
        orders = get_order_model().objects.get_processing_orders(user=request.user)[:3]
        try:
            address = request.user.delivery_addresses.all()[0]
        except IndexError:
            address = None

        return {
            'account_section': True,
            'profile': profile,
            'orders': orders,
            'address': address
        }
Exemplo n.º 8
0
def status(request, secret_id):
    """
    View current status of the given order. This page is publicly available
    on the internet without any user authentification.
    """
    order = get_object_or_404(get_order_model(), secret_id=secret_id)

    if order.is_placed() and not order.ga_sent:
        order.ga_sent = True
        order.save()

        # convince the template that ga has not been notified yet
        order.ga_sent = False

    return {'order': order, 'basket': order.basket, 'order_status_page': True}
Exemplo n.º 9
0
    def reject(self, request):
        order_id = request.GET.get('pk')
        edit_order = request.GET.get('edit_order', 'false') == 'true'
        order = get_object_or_404(get_order_model(), pk=order_id)

        if request.method == 'POST':
            form = RejectOrderForm(request.POST)
        else:
            form = RejectOrderForm()

        if request.method == 'POST':
            if request.POST.get('cubane_form_cancel', '0') == '1':
                if edit_order:
                    return self._redirect(request, 'edit', order)
                else:
                    return self._redirect(request, 'index')

            if form.is_valid():
                (success,
                 msg) = order.reject(request,
                                     form.cleaned_data.get('reject_msg'))

                if success and order.approval_status == OrderBase.APPROVAL_STATUS_REJECTED:
                    messages.add_message(
                        request, messages.SUCCESS,
                        'Order <em>%s</em> has been rejected.' %
                        order.order_id)
                else:
                    messages.add_message(
                        request, messages.ERROR,
                        'We were unable to reject the order <em>%s</em>: %s' %
                        (order.order_id, msg))

                if edit_order:
                    return self._redirect(request, 'edit', order)
                else:
                    return self._redirect(request, 'index')

        return {'order': order, 'form': form}
Exemplo n.º 10
0
def test_payment(request, secret_id):
    """
    If the payment gateway is configured to use the innershed test
    payment gateway, the user will ultimatly redirected to this page, where a
    test payment can be confimed or declined.
    """
    # get order
    order = get_object_or_404(get_order_model(), secret_id=secret_id)

    # get payment gateway
    gateway = order.get_payment_gateway()

    # make sure that the payment gateway is the testing gateway
    if not isinstance(gateway, TestPaymentGateway):
        raise Http404(
            'The system is not configured to use the test payment gateway.')

    return {
        'order': order,
        'details': order.payment_details,
        'post_url': gateway.get_response_url(request)
    }
Exemplo n.º 11
0
    def view(self, request):
        """
        View existing order and make some minor amendments to it (previous order screen).
        """
        pk = request.GET.get('pk')
        order = get_object_or_404(get_order_model(), pk=pk)

        if request.method == 'POST':
            form = ChangeOrderStatusForm(request.POST)
        else:
            form = ChangeOrderStatusForm(
                initial={
                    'status': order.status,
                    'tracking_provider': order.tracking_provider,
                    'tracking_code': order.tracking_code,
                    'delivery_type': order.delivery_type,
                    'delivery_name': order.delivery_name,
                    'delivery_company': order.delivery_company,
                    'delivery_address1': order.delivery_address1,
                    'delivery_address2': order.delivery_address2,
                    'delivery_address3': order.delivery_address3,
                    'delivery_city': order.delivery_city,
                    'delivery_county': order.delivery_county,
                    'delivery_postcode': order.delivery_postcode,
                    'delivery_country': order.delivery_country,
                    'special_requirements': order.special_requirements,
                })

        form.configure(request, order)

        if request.method == 'POST':
            # from cancellation
            if request.POST.get('cubane_form_cancel', '0') == '1':
                return self._redirect(request, 'index')

            # valid?
            if form.is_valid():
                d = form.cleaned_data

                # update status
                new_status = int(d.get('status'))
                status_changed = order.status != new_status
                order.status = new_status

                order.special_requirements = d.get('special_requirements')

                # update tracking code
                tracking_changed = (
                    order.tracking_provider != d.get('tracking_provider') or \
                    order.tracking_code != d.get('tracking_code')
                )
                order.tracking_provider = d.get('tracking_provider')
                order.tracking_code = d.get('tracking_code')

                # update delivery type
                new_delivery_type = int(d.get('delivery_type'))
                delivery_type_changed = order.delivery_type != new_delivery_type
                order.delivery_type = new_delivery_type

                # update delivery address, if this is a delivery order
                delivery_address_changed = False
                if not order.is_click_and_collect:
                    delivery_address_changed = (
                        order.delivery_name      != d.get('delivery_name') or \
                        order.delivery_company  != d.get('delivery_company') or \
                        order.delivery_address1 != d.get('delivery_address1') or \
                        order.delivery_address2 != d.get('delivery_address2') or \
                        order.delivery_address3 != d.get('delivery_address3') or \
                        order.delivery_city     != d.get('delivery_city') or \
                        order.delivery_county   != d.get('delivery_county') or \
                        order.delivery_postcode != d.get('delivery_postcode') or \
                        order.delivery_country  != d.get('delivery_country')
                    )
                    order.delivery_name = d.get('delivery_name')
                    order.delivery_company = d.get('delivery_company')
                    order.delivery_address1 = d.get('delivery_address1')
                    order.delivery_address2 = d.get('delivery_address2')
                    order.delivery_address3 = d.get('delivery_address3')
                    order.delivery_city = d.get('delivery_city')
                    order.delivery_county = d.get('delivery_county')
                    order.delivery_postcode = d.get('delivery_postcode')
                    order.delivery_country = d.get('delivery_country')

                # update processing state for all line items
                order.reset_processed_state()
                indexes = request_int_list(request.POST, 'processed')
                for index in indexes:
                    order.mark_item_as_processed(index, True)

                # update shipped state for all line items
                order.reset_shipped_state()
                indexes = request_int_list(request.POST, 'shipped')
                for index in indexes:
                    order.mark_item_as_shipped(index, True)

                # save order
                order.save()

                # fulfillment
                if order.status in OrderBase.FULFILLED_STATUS and not order.fulfilled:
                    (success, msg) = order.fulfill(request)
                    if success:
                        messages.add_message(
                            request, messages.SUCCESS,
                            'Order <em>%s</em> has been fulfilled successfully.'
                            % order.order_id)
                    else:
                        messages.add_message(
                            request, messages.ERROR,
                            'Error while fulfilling order <em>%s</em>: %s' %
                            (order.order_id, msg))

                # send email if something of importance changed
                if status_changed or tracking_changed or delivery_type_changed or delivery_address_changed:
                    if int(order.status) in [
                            OrderBase.STATUS_PARTIALLY_SHIPPED,
                            OrderBase.STATUS_SHIPPED,
                            OrderBase.STATUS_READY_TO_COLLECT,
                            OrderBase.STATUS_COLLECTED
                    ]:
                        if mail_customer_order_status(request, order):
                            messages.add_message(
                                request, messages.SUCCESS,
                                'Email sent to customer: %s' % order.email)
                    messages.add_message(
                        request, messages.SUCCESS,
                        'Order <em>%s</em> has been updated.' % order.order_id)

                active_tab = request.POST.get('cubane_save_and_continue', '0')
                if not active_tab == '0':
                    return HttpResponseRedirect(
                        reverse('cubane.ishop.orders.edit') +
                        '?pk=%d' % order.pk)
                else:
                    return self._redirect(request, 'index')

        return {'order': order, 'form': form, 'edit': True}
Exemplo n.º 12
0
    def payment_update(self, request):
        cr_id = request.POST.get('CreditRequestID', None)
        status = request.POST.get('Status', None)
        api_key = request.POST.get('Identification[api_key]', None)
        ref = request.POST.get('Identification[RetailerUniqueRef]', None)

        is_valid_request = True
        # check if api key is matching our api KEY
        if api_key != self._get_api_key():
            is_valid_request = False

        if status:
            status = status.lower()
        else:
            is_valid_request = False

        # credit id should be provided
        if not cr_id:
            is_valid_request = False

        # some requests are with [] some without
        if ref:
            ref = ref.split('[')[0]

        # get order by ref
        order = get_order_model().objects.filter(secret_id=ref)

        if order.count() != 1:
            is_valid_request = False

        if is_valid_request:
            order = order[0]
            if status == 'initialise':
                order.loan_status = OrderBase.LOAN_STATUS_NONE
            elif status == 'predecline':
                order.loan_status = OrderBase.LOAN_STATUS_PREDECLINE
            elif status == 'accept':
                order.loan_status = OrderBase.LOAN_STATUS_ACCEPT
            elif status == 'decline':
                order.loan_status = OrderBase.LOAN_STATUS_DECLINE
                order.status = OrderBase.STATUS_PAYMENT_DECLINED
            elif status == 'refer':
                order.loan_status = OrderBase.LOAN_STATUS_REFER
            elif status == 'verified':
                order.loan_status = OrderBase.LOAN_STATUS_VERIFIED
                order.status = OrderBase.STATUS_PAYMENT_CONFIRMED
                order.payment_confirmed_at = datetime.datetime.now()
                generate_emails_and_notes(request, order)
            elif status == 'amended':
                order.loan_status = OrderBase.LOAN_STATUS_AMENDED
            elif status == 'fulfilled':
                order.loan_status = OrderBase.LOAN_STATUS_FULFILLED
            elif status == 'complete':
                order.loan_status = OrderBase.LOAN_STATUS_COMPLETE
            elif status == 'cancelled':
                order.loan_status = OrderBase.LOAN_STATUS_CANCELLED
                order.status = OrderBase.STATUS_PAYMENT_DECLINED
            elif status == 'info needed':
                order.loan_status = OrderBase.LOAN_STATUS_INFO_NEEDED
            elif status == 'action customer':
                order.loan_status = OrderBase.LOAN_STATUS_ACTION_CUSTOMER
            elif status == 'action retailer':
                order.loan_status = OrderBase.LOAN_STATUS_ACTION_RETAILER
            else:
                order.loan_status = OrderBase.LOAN_STATUS_NONE

            order.transaction_id = cr_id
            order.save()

            # Omni didn't define what kind of response they are expecting. Assuming 200...
            return HttpResponse('Status: OK')
        else:
            raise Exception(
                '[Omni]: Payment Update couldn\'t update given order.')
Exemplo n.º 13
0
 class Meta:
     model = get_order_model()
     fields = '__all__'
Exemplo n.º 14
0
    class Meta:
        model = get_order_model()
        fields = [
            # status
            'status',

            # tracking
            'tracking_provider',
            'tracking_code',

            # customer
            'customer',
            'email',
            'telephone',

            # details
            'special_requirements',

            # billing
            'billing_postcode_lookup',
            'full_name',
            'billing_company',
            'billing_address1',
            'billing_address2',
            'billing_address3',
            'billing_city',
            'billing_county',
            'billing_postcode',
            'billing_country',

            # delivery
            'delivery_postcode_lookup',
            'delivery_name',
            'delivery_company',
            'delivery_address1',
            'delivery_address2',
            'delivery_address3',
            'delivery_city',
            'delivery_county',
            'delivery_postcode',
            'delivery_country'
        ]
        tabs = [
            {
                'title': 'Line Items',
                'fields': ['_basket']
            },
            {
                'title':
                'Status and Tracking',
                'fields': [
                    # status
                    'status',

                    # tracking
                    'tracking_provider',
                    'tracking_code'
                ]
            },
            {
                'title':
                'Details',
                'fields': [
                    # customer
                    'customer',
                    'email',
                    'telephone',

                    # details
                    'special_requirements',

                    # billing
                    'billing_postcode_lookup',
                    'full_name',
                    'billing_company',
                    'billing_address1',
                    'billing_address2',
                    'billing_address3',
                    'billing_city',
                    'billing_county',
                    'billing_postcode',
                    'billing_country',

                    # delivery
                    'delivery_postcode_lookup',
                    'delivery_name',
                    'delivery_company',
                    'delivery_address1',
                    'delivery_address2',
                    'delivery_address3',
                    'delivery_city',
                    'delivery_county',
                    'delivery_postcode',
                    'delivery_country'
                ]
            }
        ]
        sections = {
            'status': 'Order Status',
            'tracking_provider': 'Order Delivery Tracking',
            'customer': 'Customer Information',
            'special_requirements': 'Customer Details',
            'billing_postcode_lookup': 'Billing Address',
            'delivery_postcode_lookup': 'Delivery Address',
        }
Exemplo n.º 15
0
class OrderView(ModelView):
    template_path = 'cubane/ishop/merchant/orders/'
    model = get_order_model()
    namespace = 'cubane.ishop.orders'

    def __init__(self, *args, **kwargs):
        self.patterns = []
        self.listing_actions = []
        self.shortcut_actions = []

        # view order (previous order screen)
        self.patterns.append(view_url(r'view/$', 'view', name='view'))
        self.listing_actions.append(('View', 'view', 'single'))
        self.shortcut_actions.append('view')

        # support for pre-auth payments (approval)
        if settings.SHOP_PREAUTH:
            self.patterns.extend([
                view_url(r'approve/$', 'approve', name='approve'),
                view_url(r'reject/$', 'reject', name='reject'),
                view_url(r'cancel/$', 'cancel', name='cancel')
            ])
            self.listing_actions.extend([('[Approve]', 'approve', 'single'),
                                         ('[Reject]', 'reject', 'single'),
                                         ('[Cancel]', 'cancel', 'single')])
            self.shortcut_actions.extend([
                'approve',
                'reject',
                'cancel',
            ])
        else:
            self.exclude_columns = ['approval_status']

        self.patterns.extend([
            view_url(r'basket-editor/', 'basket_editor', name='basket_editor'),
            view_url(r'basket-editor-search/',
                     'basket_editor_search',
                     name='basket_editor_search'),
            view_url(r'basket-editor-add-to-basket/',
                     'basket_editor_add_to_basket',
                     name='basket_editor_add_to_basket'),
        ])

        super(OrderView, self).__init__(*args, **kwargs)

    def _get_objects(self, request):
        return self.model.objects.select_related('customer', 'voucher').all()

    def _get_objects_or_404(self, request):
        return self.model.objects.select_related('customer', 'voucher').all()

    def before_save(self, request, cleaned_data, instance, edit):
        # default values
        if not edit:
            from cubane.ishop.views import get_shop
            shop = get_shop()
            instance.customer_not_present = True
            instance.payment_gateway = shop.get_default_payment_gateway()

        # save basket.
        basket = Basket(request, prefix=instance.backend_basket_prefix)
        if not basket.is_empty():
            instance.save_basket(basket)

        # change status
        if request.POST.get('next-status'):
            cleaned_data['status'] = int(request.POST.get('next-status'))

    def after_save(self, request, cleaned_data, instance, edit):
        # generate identifiers
        if not edit:
            instance.generate_identifiers(request)

    def after_save_changes(self, request, cleaned_data, instance, changes,
                           edit):
        """
        Called after the given model instance is saved.
        """
        # determine changes
        status_changed = 'status' in changes
        tracking_changed = 'tracking_provider' in changes or 'tracking_code' in changes
        click_and_collect_changed = 'click_and_collect' in changes
        delivery_option_changed = ('delivery_option_id' in changes
                                   or 'delivery_quote' in changes)
        delivery_address_changed = ('delivery_name' in changes
                                    or 'delivery_company' in changes
                                    or 'delivery_address1' in changes
                                    or 'delivery_address2' in changes
                                    or 'delivery_address3' in changes
                                    or 'delivery_city' in changes
                                    or 'delivery_county' in changes
                                    or 'delivery_postcode' in changes
                                    or 'delivery_country_id' in changes)
        changed = (status_changed or tracking_changed
                   or click_and_collect_changed or delivery_option_changed
                   or delivery_address_changed)

        # fulfillment
        if instance.status in OrderBase.FULFILLED_STATUS and not instance.fulfilled:
            (success, msg) = instance.fulfill(request)
            if success:
                messages.add_message(
                    request, messages.SUCCESS,
                    'Order <em>%s</em> has been fulfilled successfully.' %
                    instance.order_id)
            else:
                messages.add_message(
                    request, messages.ERROR,
                    'Error while fulfilling order <em>%s</em>: %s' %
                    (instance.order_id, msg))

        # send email if something of importance changed
        if changed:
            if int(instance.status) in [
                    OrderBase.STATUS_PARTIALLY_SHIPPED,
                    OrderBase.STATUS_SHIPPED,
                    OrderBase.STATUS_READY_TO_COLLECT,
                    OrderBase.STATUS_COLLECTED
            ]:
                if mail_customer_order_status(request, instance):
                    messages.add_message(
                        request, messages.SUCCESS,
                        'Email sent to customer: %s' % instance.email)

        # redirect to payment
        if request.POST.get('autosubmit'):
            return HttpResponseRedirect(
                '%s%s' % (instance.get_absolute_url(), '?autosubmit=true'))

    def _create_edit(self, request, pk=None, edit=False, duplicate=False):
        context = super(OrderView, self)._create_edit(request, pk, edit,
                                                      duplicate)
        if edit:
            context['order'] = context.get('object')
        return context

    def view(self, request):
        """
        View existing order and make some minor amendments to it (previous order screen).
        """
        pk = request.GET.get('pk')
        order = get_object_or_404(get_order_model(), pk=pk)

        if request.method == 'POST':
            form = ChangeOrderStatusForm(request.POST)
        else:
            form = ChangeOrderStatusForm(
                initial={
                    'status': order.status,
                    'tracking_provider': order.tracking_provider,
                    'tracking_code': order.tracking_code,
                    'delivery_type': order.delivery_type,
                    'delivery_name': order.delivery_name,
                    'delivery_company': order.delivery_company,
                    'delivery_address1': order.delivery_address1,
                    'delivery_address2': order.delivery_address2,
                    'delivery_address3': order.delivery_address3,
                    'delivery_city': order.delivery_city,
                    'delivery_county': order.delivery_county,
                    'delivery_postcode': order.delivery_postcode,
                    'delivery_country': order.delivery_country,
                    'special_requirements': order.special_requirements,
                })

        form.configure(request, order)

        if request.method == 'POST':
            # from cancellation
            if request.POST.get('cubane_form_cancel', '0') == '1':
                return self._redirect(request, 'index')

            # valid?
            if form.is_valid():
                d = form.cleaned_data

                # update status
                new_status = int(d.get('status'))
                status_changed = order.status != new_status
                order.status = new_status

                order.special_requirements = d.get('special_requirements')

                # update tracking code
                tracking_changed = (
                    order.tracking_provider != d.get('tracking_provider') or \
                    order.tracking_code != d.get('tracking_code')
                )
                order.tracking_provider = d.get('tracking_provider')
                order.tracking_code = d.get('tracking_code')

                # update delivery type
                new_delivery_type = int(d.get('delivery_type'))
                delivery_type_changed = order.delivery_type != new_delivery_type
                order.delivery_type = new_delivery_type

                # update delivery address, if this is a delivery order
                delivery_address_changed = False
                if not order.is_click_and_collect:
                    delivery_address_changed = (
                        order.delivery_name      != d.get('delivery_name') or \
                        order.delivery_company  != d.get('delivery_company') or \
                        order.delivery_address1 != d.get('delivery_address1') or \
                        order.delivery_address2 != d.get('delivery_address2') or \
                        order.delivery_address3 != d.get('delivery_address3') or \
                        order.delivery_city     != d.get('delivery_city') or \
                        order.delivery_county   != d.get('delivery_county') or \
                        order.delivery_postcode != d.get('delivery_postcode') or \
                        order.delivery_country  != d.get('delivery_country')
                    )
                    order.delivery_name = d.get('delivery_name')
                    order.delivery_company = d.get('delivery_company')
                    order.delivery_address1 = d.get('delivery_address1')
                    order.delivery_address2 = d.get('delivery_address2')
                    order.delivery_address3 = d.get('delivery_address3')
                    order.delivery_city = d.get('delivery_city')
                    order.delivery_county = d.get('delivery_county')
                    order.delivery_postcode = d.get('delivery_postcode')
                    order.delivery_country = d.get('delivery_country')

                # update processing state for all line items
                order.reset_processed_state()
                indexes = request_int_list(request.POST, 'processed')
                for index in indexes:
                    order.mark_item_as_processed(index, True)

                # update shipped state for all line items
                order.reset_shipped_state()
                indexes = request_int_list(request.POST, 'shipped')
                for index in indexes:
                    order.mark_item_as_shipped(index, True)

                # save order
                order.save()

                # fulfillment
                if order.status in OrderBase.FULFILLED_STATUS and not order.fulfilled:
                    (success, msg) = order.fulfill(request)
                    if success:
                        messages.add_message(
                            request, messages.SUCCESS,
                            'Order <em>%s</em> has been fulfilled successfully.'
                            % order.order_id)
                    else:
                        messages.add_message(
                            request, messages.ERROR,
                            'Error while fulfilling order <em>%s</em>: %s' %
                            (order.order_id, msg))

                # send email if something of importance changed
                if status_changed or tracking_changed or delivery_type_changed or delivery_address_changed:
                    if int(order.status) in [
                            OrderBase.STATUS_PARTIALLY_SHIPPED,
                            OrderBase.STATUS_SHIPPED,
                            OrderBase.STATUS_READY_TO_COLLECT,
                            OrderBase.STATUS_COLLECTED
                    ]:
                        if mail_customer_order_status(request, order):
                            messages.add_message(
                                request, messages.SUCCESS,
                                'Email sent to customer: %s' % order.email)
                    messages.add_message(
                        request, messages.SUCCESS,
                        'Order <em>%s</em> has been updated.' % order.order_id)

                active_tab = request.POST.get('cubane_save_and_continue', '0')
                if not active_tab == '0':
                    return HttpResponseRedirect(
                        reverse('cubane.ishop.orders.edit') +
                        '?pk=%d' % order.pk)
                else:
                    return self._redirect(request, 'index')

        return {'order': order, 'form': form, 'edit': True}

    def _create_order(self, request):
        """
        Create new order.
        """
        # determine form class
        order_model = get_order_model()
        formclass = order_model.get_form()

        # create form
        if request.method == 'POST':
            form = formclass(request.POST)
        else:
            form = formclass()

        form.configure(request, None, False)

        # validate form
        if request.method == 'POST' and form.is_valid():
            d = form.cleaned_data

            # create new order
            order = order_model.create_empty_customer_not_present(request)

            # redirect to edit page
            return self._redirect(request, 'edit', order)

        return {'form': form, 'edit': False}

    def approve(self, request):
        order_id = request.GET.get('pk')
        edit_order = request.GET.get('edit_order', 'false') == 'true'
        order = get_object_or_404(get_order_model(), pk=order_id)

        if request.method == 'POST':
            form = ApproveOrderForm(request.POST)
        else:
            form = ApproveOrderForm()

        if request.method == 'POST':
            if request.POST.get('cubane_form_cancel', '0') == '1':
                if edit_order:
                    return self._redirect(request, 'edit', order)
                else:
                    return self._redirect(request, 'index')

            if form.is_valid():
                (success, msg) = order.approve(request)

                if success and order.approval_status == OrderBase.APPROVAL_STATUS_APPROVED:
                    messages.add_message(
                        request, messages.SUCCESS,
                        'Order <em>%s</em> has been approved.' %
                        order.order_id)
                else:
                    messages.add_message(
                        request, messages.ERROR,
                        'We were unable to approve the order <em>%s</em>: %s' %
                        (order.order_id, msg))

                if edit_order:
                    return self._redirect(request, 'edit', order)
                else:
                    return self._redirect(request, 'index')

        return {'order': order, 'form': form}

    def reject(self, request):
        order_id = request.GET.get('pk')
        edit_order = request.GET.get('edit_order', 'false') == 'true'
        order = get_object_or_404(get_order_model(), pk=order_id)

        if request.method == 'POST':
            form = RejectOrderForm(request.POST)
        else:
            form = RejectOrderForm()

        if request.method == 'POST':
            if request.POST.get('cubane_form_cancel', '0') == '1':
                if edit_order:
                    return self._redirect(request, 'edit', order)
                else:
                    return self._redirect(request, 'index')

            if form.is_valid():
                (success,
                 msg) = order.reject(request,
                                     form.cleaned_data.get('reject_msg'))

                if success and order.approval_status == OrderBase.APPROVAL_STATUS_REJECTED:
                    messages.add_message(
                        request, messages.SUCCESS,
                        'Order <em>%s</em> has been rejected.' %
                        order.order_id)
                else:
                    messages.add_message(
                        request, messages.ERROR,
                        'We were unable to reject the order <em>%s</em>: %s' %
                        (order.order_id, msg))

                if edit_order:
                    return self._redirect(request, 'edit', order)
                else:
                    return self._redirect(request, 'index')

        return {'order': order, 'form': form}

    def cancel(self, request):
        order_id = request.GET.get('pk')
        edit_order = request.GET.get('edit_order', 'false') == 'true'
        order = get_object_or_404(get_order_model(), pk=order_id)

        def _do_redirect():
            if edit_order:
                return self._redirect(request, 'edit', order)
            else:
                return self._redirect(request, 'index')

        # cannot cancel if we are awaiting payment approval/rejection
        if order.approval_status == OrderBase.APPROVAL_STATUS_WAITING:
            messages.add_message(
                request, messages.ERROR,
                'Order <em>%s</em> is awaiting approval. Please accept or reject this order.'
                % order.order_id)
            return _do_redirect()

        # cannot cancel if the order has already been cancelled
        if order.cancelled:
            messages.add_message(
                request, messages.ERROR,
                'Order <em>%s</em> has already been cancelled.' %
                order.order_id)
            return _do_redirect()

        # process cancellation form
        if request.method == 'POST':
            form = CancelOrderForm(request.POST)
        else:
            form = CancelOrderForm()

        if request.method == 'POST':
            if request.POST.get('cubane_form_cancel', '0') == '1':
                _do_redirect()

            if form.is_valid():
                (success,
                 msg) = order.cancel(request,
                                     form.cleaned_data.get('cancel_msg'))
                if success:
                    messages.add_message(
                        request, messages.SUCCESS,
                        'Order <em>%s</em> has been cancelled.' %
                        order.order_id)
                else:
                    messages.add_message(
                        request, messages.ERROR,
                        'We were unable to cancel the order <em>%s</em>: %s' %
                        (order.order_id, msg))

                _do_redirect()

        return {'order': order, 'form': form}

    def basket_editor(self, request):
        prefix = request.GET.get('prefix')
        basket = Basket(request, prefix=prefix)

        return {'basket': basket}

    def basket_editor_search(self, request):
        from cubane.ishop.views import get_shop

        q = request.POST.get('q')
        shop = get_shop()
        products = shop.get_products().filter(
            Q(title__icontains=q) | Q(barcode__startswith=q)
            | Q(part_number__startswith=q)
            | Q(sku_enabled=True, sku__startswith=q),
            draft=False)

        return {'products': products[:100]}

    def basket_editor_add_to_basket(self, request):
        from cubane.ishop.views import get_shop

        pk = request.POST.get('pk')
        prefix = request.POST.get('prefix')
        shop = get_shop()
        product = shop.get_products().get(pk=pk)

        return {'product': product, 'prefix': prefix, 'settings': settings}
Exemplo n.º 16
0
def process_payment(request, gateway, transaction_id):
    """
    Process payment information for the order with the given transaction id.
    """
    # if the payment gateway returns no transaction id,
    # we consider this as an error.
    if transaction_id == None:
        mail_error(
            'Payment gateway %s was unable to identify transaction id based on the payment response %s.'
            % (gateway, request))
        return gateway.payment_response(request, PaymentGateway.RESPONSE_ERROR,
                                        None, None)

    # get order based on transaction id
    order_model = get_order_model()
    try:
        order = order_model.objects.get(transaction_id=transaction_id)
        registration_context = RegistrationContext(order.transaction_id,
                                                   order.payment_details)
    except order_model.DoesNotExist:
        # unable to identify correct order.
        return HttpResponse('', content_type='text/plain')

    # let the payment gateway determine the success of the payment
    # based on the response...
    payment_status = gateway.payment_accept(request, order,
                                            registration_context)

    # translate payment gateway payment status to system state
    if payment_status == PaymentGateway.STATUS_PAYMENT_CONFIRMED:
        if order.preauth:
            order.approval_status = OrderBase.APPROVAL_STATUS_WAITING
        else:
            order.approval_status = OrderBase.APPROVAL_STATUS_NONE
        order.status = OrderBase.STATUS_PAYMENT_CONFIRMED
        order.payment_confirmed_at = datetime.datetime.now()
        order.save()
    elif payment_status == PaymentGateway.STATUS_PAYMENT_DECLINED:
        order.status = OrderBase.STATUS_PAYMENT_DECLINED
        order.save()
    elif payment_status == PaymentGateway.STATUS_PENDING:
        order.status = OrderBase.STATUS_PENDING
        order.save()
    elif payment_status == PaymentGateway.STATUS_PAYMENT_ERROR:
        order.status = OrderBase.STATUS_PAYMENT_ERROR
        order.save()
        mail_error('Payment error (gateway %s): %s' %
                   (gateway.__class__.__name__, gateway.message))
    else:
        order.status = OrderBase.STATUS_PAYMENT_ERROR
        order.save()
        mail_error(
            'Received unknown payment response for order %s from gateway %s. Gateway message = %s'
            % (order.id, gateway.__class__.__name__, gateway.message))

    # send out emails and order/shipping notes
    generate_emails_and_notes(request, order)

    # send success back to payment gateway (this does not neccessarily
    # mean that the actual payment was successful)...
    if order.is_backend_payment:
        next_url = '%s?pk=%s' % (get_absolute_url('cubane.ishop.orders.edit'),
                                 order.pk)
    else:
        next_url = get_absolute_url('shop.order.status',
                                    args=[order.secret_id])

    return gateway.payment_response(request, PaymentGateway.RESPONSE_SUCCESS,
                                    order, registration_context, next_url)
Exemplo n.º 17
0
def pay(request):
    """
    Start payment based on particular payment provided. At this point in time,
    the basket is destroyed.
    """
    # get order
    secret_id = request.POST.get('secret_id', None)
    if secret_id == None:
        raise Http404('Missing argument: secret_id.')

    if not re.match(r'^[a-fA-F0-9]+$', secret_id):
        raise Http404('Invalid format for argument: secret_id.')

    order = get_object_or_404(get_order_model(), secret_id=secret_id)

    # if the order is via invoice, accept order instantly without going through
    # online payment
    if order.is_invoice:
        # verify that the order can be placed
        if not order.can_be_placed_via_invoice():
            raise Http404(
                'Unable to place the given order because of its status.')

        order.status = OrderBase.STATUS_PLACED_INVOICE
        order.save()

        generate_emails_and_notes(request, order)
        _destroy_basket(request)
        return HttpResponseRedirect(
            reverse('shop.order.status', args=[secret_id]))

    # if the total amount payable is zero, then skip the payment process
    # but the order is not an invoice as such.
    if order.is_zero_amount_checkout:
        order.status = OrderBase.STATUS_PLACED_ZERO_AMOUNT
        order.save()

        generate_emails_and_notes(request, order)
        _destroy_basket(request)
        return HttpResponseRedirect(
            reverse('shop.order.status', args=[secret_id]))

    # get gateway
    gateway = order.get_payment_gateway()

    # if we retry an existing order, clone the order first, which implicitly
    # generates a new order id...
    retry = request.POST.get('retry', '0') == '1'
    if retry == True and order.is_retry():
        order = order.clone(request)

    # verify that the order has not already been confirmed
    if not order.can_be_registered_for_payment():
        raise Http404(
            'Unable to register the given order because of its status.')

    # if order can be moto
    order.is_backend_payment = False
    if order.can_moto and request.user.is_staff:
        order.is_backend_payment = True

    # register a new transaction for payment
    if order.is_backend_payment:
        preauth = False
    else:
        preauth = settings.SHOP_PREAUTH
    registration_context = gateway.register_payment(request,
                                                    order,
                                                    preauth=preauth)

    # if we do not get a valid registration content,
    # consider this payment attempt to be failed
    if registration_context == None:
        mail_error(
            'Payment gateway %s was unable to register payment transaction. Message: %s'
            % (gateway.name, gateway.message))
        order.status = OrderBase.STATUS_PAYMENT_ERROR
        order.save()
        return HttpResponseRedirect(
            reverse('shop.order.status', args=[order.secret_id]))

    # save transcation details within order
    order.transaction_id = registration_context.transaction_id
    order.payment_details = registration_context.payment_details
    order.status = OrderBase.STATUS_PAYMENT_AWAITING

    order.save()

    _destroy_basket(request)

    if gateway.is_redirect():
        # let the payment gateway render the response, which might be a redirect
        # or a custom submit form...
        return gateway.payment_redirect(request, order, registration_context)
    else:
        # handle payment directly
        return process_payment(request, gateway, order.transaction_id)
Exemplo n.º 18
0
def complete(request):
    """
    (3) Final checkout step, where the order is actually created from the basket.
    """
    basket = Basket(request)

    # redirect back to a previous step if we missed anything...
    next = get_next_checkout_step(request, basket, CurrentPage.COMPLETE())
    if next:
        return HttpResponseRedirect(next)

    # state or county
    if 'state' in basket.billing_address:
        county = basket.billing_address.get('state')
    else:
        county = basket.billing_address.get('county')

    # create account if requested
    if basket.signup:
        # create user account
        md5 = hashlib.md5()
        md5.update(basket.signup.get('email'))
        email = basket.signup.get('email')

        if User.objects.filter(email=email).count() > 0:
            messages.warning(
                request,
                'There is already an account with this email: %s.' % email)
            return HttpResponseRedirect(reverse('shop.account.login'))
        user = User.objects.create(username=md5.hexdigest()[:30],
                                   first_name=basket.signup.get('first_name'),
                                   last_name=basket.signup.get('last_name'),
                                   email=email)

        # replace username with user id and set password
        user.username = unicode(user.id)
        user.set_password(basket.signup.get('password'))
        user.save()

        # create profile
        get_customer_model().objects.create(
            user=user,
            first_name=user.first_name,
            last_name=user.last_name,
            email=user.email,
            title=basket.billing_address.get('title'),
            address1=basket.billing_address.get('address1'),
            address2=basket.billing_address.get('address2'),
            address3=basket.billing_address.get('address3'),
            city=basket.billing_address.get('city'),
            county=county,
            postcode=basket.billing_address.get('postcode'),
            country=basket.billing_address.get('country'),
            telephone=basket.billing_address.get('telephone'),
            newsletter=basket.newsletter)

        # log user in
        login_user_without_password(request, user)
        basket.signup = None
    else:
        if request.user.is_anonymous():
            user = None
        else:
            user = request.user

        # if specified, copy relevant information to customer's profile
        if user != None and basket.update_profile:
            user.first_name = basket.billing_address.get('first_name')
            user.last_name = basket.billing_address.get('last_name')
            user.save()

            customer = get_customer_model().objects.get(user=user)
            customer.address1 = basket.billing_address.get('address1')
            customer.address2 = basket.billing_address.get('address2')
            customer.address3 = basket.billing_address.get('address3')
            customer.city = basket.billing_address.get('city')
            customer.county = county
            customer.postcode = basket.billing_address.get('postcode')
            customer.country = basket.billing_address.get('country')
            customer.telephone = basket.billing_address.get('telephone')
            customer.save()

    # create single order
    order = get_order_model().create_from_basket(request, basket, user)

    # mailchimp
    if request.settings.mailchimp_enabled and basket.newsletter:
        email = basket.billing_address.get('email')
        first_name = basket.billing_address.get('first_name')
        last_name = basket.billing_address.get('last_name')
        person_name = (first_name, last_name)
        merge_vars = {'FNAME': " ".join(person_name)}
        ms = MailSnake(request.settings.mailchimp_api)
        try:
            ms.listSubscribe(id=request.settings.mailchimp_list_id,
                             email_address=email,
                             merge_vars=merge_vars)
        except:
            pass

    # redirect to order status page (payment from there...)
    basket.save()
    return HttpResponseRedirect(
        reverse('shop.order.status', args=[order.secret_id]))