Example #1
0
    def summary(self):
        ret = '<table cellpadding="0" cellspacing="10" border="0"><tr><td><u>Product</u></td><td><u>Quantity</u></td><td><u>Unit Price</u></td><td><u>Item Total</u></td></tr>'
        for i in self.active_items:
            try:

                ret += """<tr>
                            <td nowrap><b>{name}</b></td><td>{quant}</td><td>${price}</td><td align="right">${tot}</td>
                          </tr>
                       """.format(
                    name=i.product.name.encode("ascii", "ignore"),
                    price=util.money(i.unit_price),
                    quant=int(i.quantity),
                    tot=util.money(i.total()),
                )
                for attr in i.children:
                    kidstr = """<tr>
                                <td align="right">{klass} : {name}</td><td colspan="3">&nbsp;</td>
                             </tr>
                          """.format(
                        name=attr.product.name, klass=attr.product.attr_class
                    )
                    ret += kidstr

            except Exception as exc:  # pragma: no cover
                log.debug(exc)

        ret += '<tr><td colspan="4"><hr></td></tr>'
        ret += '<tr><td><i>Sub Total</i></td><td colspan="2">&nbsp;</td><td align="right">$%s</td></tr>' % util.money(
            self.total_item_price(), True
        )
        ret += (
            '<tr><td><i>Shipping/Handling</i></td><td colspan="2">&nbsp;</td><td align="right">$%s</td></tr>'
            % util.money((self.total_shipping_price() + self.total_handling_price()), True)
        )
        ret += '<tr><td><i>Tax</i></td><td colspan="2">&nbsp;</td><td align="right">$%s</td></tr>' % util.money(
            self.total_tax(), True
        )
        ret += (
            '<tr><td><i>Total Payments</i></td><td colspan="2">&nbsp;</td><td align="right">$%s</td></tr>'
            % util.money(self.total_payments_applied(), True)
        )
        ret += (
            '<tr><td><i>Total Discounts</i></td><td colspan="2">&nbsp;</td><td align="right">$%s</td></tr>'
            % util.money(self.total_discounts_applied(), True)
        )
        ret += '<tr><td><i>Total Due</i></td><td colspan="2">&nbsp;</td><td align="right">$%s</td></tr>' % util.money(
            self.total_payments_due(), True
        )
        ret += "</table>"
        return ret
Example #2
0
    def inventory_list(self):
        products = Product.find_by_vendor(self.request.ctx.user.vendor) if self.request.ctx.user and self.request.ctx.user.is_vendor_user() else Product.find_all(self.enterprise_id) #pylint: disable-msg=E1120

        campaigns = Campaign.find_all(self.enterprise_id)

        response = {
            'page': 1,
            'total': 1,
            'records': len(products)}

        rows = []

        for prod in products:
            #log.debug('%s %s/%s' % (p.product_id, i+1, len(products)))
            # blank spot at the beginning of the row is to make room for the
            # action buttons.  don't remove it.
            cells = ['', unicode(prod.product_id),
                     util.nvl(prod.name),
                     util.nvl(prod.sku),
                     util.nvl(prod.manufacturer),
                     util.nvl(unicode(prod.inventory)),
                     util.nvl(unicode(prod.inventory_par)),
                     util.nvl(unicode(prod.unit_cost))]
            # the column ordering in the UI is dependant on the order of the
            # campaigns that comes back from Campaign.find_all().  We use the
            # same ordering here so we are fine not adding some campaign ID here.
            for camp in campaigns:
                cells.append(util.nvl(util.money(prod.get_retail_price(camp))))

            rows.append({'id': str(prod.product_id),
                         'cell': cells})

        response['rows'] = rows
        return json.dumps(response)
Example #3
0
 def payment_history(self):
     try:
         journals = Journal.find_all_by_order(self)
         ret = '<table cellpadding="0" cellspacing="10" border="0"><tr><td><u>Date</u></td><td><u>Method</u></td><td><u>Note</u></td><td><u>Amount</u></td></tr>'
         for j in journals:
             ret += """<tr>
                         <td>{dt}</td><td nowrap>{meth}</td><td>{note}</td><td align="right">{amt}</td>
                       </tr>
                    """.format(
                 dt=util.slash_date(j.create_dt), amt=util.money(j.amount), meth=j.method, note=j.note
             )
         ret += '<tr><td colspan="4"><hr></td></tr>'
         ret += (
             '<tr><td><i>Total Payments Applied</i></td><td colspan="2">&nbsp;</td><td align="right">%s</td></tr>'
             % util.money(self.total_payments_applied(), True)
         )
         ret += "</table>"
         return ret
     except Exception as exc:  # pragma: no cover
         log.debug(exc)
Example #4
0
    def _apply_payment(self, customer_id, order_id, pmt_amount=None, pmt_method=None, pmt_note=None):  #pylint: disable-msg=R0913
        """ KB: [2011-03-09]: Check that everything is kosher
        Create a journal entry for the order for the amount and type specified in the UI
        Create a status noting the type and amount of the payment applied.
        """
        customer = Customer.load(customer_id)
        self.forbid_if(not customer or customer.campaign.company.enterprise_id != self.enterprise_id)
        order = customer.get_order(order_id)
        self.forbid_if(not order)
        user = self.request.ctx.user
        current_customer_balance = customer.get_current_balance()
        #prior_payments_applied = order.total_payments_applied()
        prior_total_due = order.total_payments_due()
        balance_amount_to_apply = float(self.request.POST.get('pmt_balance_amount_to_apply', 0.0))
        amt = float(util.nvl(pmt_amount, self.request.POST.get('pmt_amount')))
        method = util.nvl(pmt_method, self.request.POST.get('pmt_method'))
        note = util.nvl(pmt_note, self.request.POST.get('pmt_note'))

        self.forbid_if(round(amt + balance_amount_to_apply, 2) > round(prior_total_due, 2),
                       "amt + balance_amount_to_apply > prior_total_due")
        self.forbid_if(current_customer_balance > 0 and round(balance_amount_to_apply, 2) > round(current_customer_balance, 2),
                       "balance_amount_to_apply > current_customer_balance")

        pmt_type = 'PartialPayment'
        if amt == prior_total_due:
            pmt_type = 'FullPayment'

        Journal.create_new(amt, customer, order, user, pmt_type, method, note)
        status_note = '%s applied: $%s' % (pmt_type, util.money(amt))
        Status.add(customer, order, Status.find_event(self.enterprise_id, order, 'PAYMENT_APPLIED'), status_note)
        self.flash(status_note)
        if balance_amount_to_apply > 0:
            Journal.create_new(balance_amount_to_apply, customer, order, user, 'CreditDecrease')
            status_note = '%s applied: $%s' % ('CreditDecrease', util.money(balance_amount_to_apply))
            Status.add(customer, order, Status.find_event(self.enterprise_id, order, 'PAYMENT_APPLIED'), status_note)
            self.flash(status_note)
        customer.invalidate_caches()
        customer.flush()
        return 'True'
Example #5
0
 def product_price(product, campaign):
     return util.money(product.get_price(campaign))
Example #6
0
    def create_new(cart, customer, enterprise_id, campaign, user_created, order_note=None, incl_tax=True):
        """ KB: [2010-09-09]: Given a cart full of products, create a new order and return it.
        if a given product is a parent, then create an kid order_item of zero cost and attach it to the parent.
        """
        cord = CustomerOrder()
        cord.creator = user_created
        cord.customer = customer
        cord.campaign = campaign
        cord.shipping_total = util.nvl(cart.shipping_total, 0.0)
        cord.shipping_note = cart.shipping_selection_name
        cord.handling_total = util.nvl(cart.handling_total, 0.0)
        cord.shipping_addr1 = cart.shipping_addr1
        cord.shipping_addr2 = cart.shipping_addr2
        cord.shipping_city = cart.shipping_city
        cord.shipping_state = cart.shipping_state
        cord.shipping_zip = cart.shipping_zip
        cord.shipping_country = cart.shipping_country
        cord.shipping_phone = cart.shipping_phone
        cart.calculate_cart_discount_for_order(cord)
        cord.note = order_note
        cord.save()
        cord.flush()
        for cart_item in cart.items:
            prd = Product.load(cart_item["product"].product_id)
            item = OrderItem()
            item.order = cord
            item.product = prd
            item.creator = user_created
            item.start_dt = cart_item["start_dt"]
            item.note = cart_item["note"]
            item.save()
            item.flush()

            attribute_order_items = []
            for attribute_product_id in cart_item["attributes"].keys():
                attribute_order_item = OrderItem()
                attribute_order_item.parent_id = item.order_item_id
                attribute_order_item.order = cord
                ao_prd = Product.load(attribute_product_id)
                attribute_order_item.product = ao_prd
                attribute_order_item.creator = user_created
                attribute_order_item.unit_cost = ao_prd.unit_cost
                attribute_order_item.unit_discount_price = ao_prd.get_discount_price(campaign)
                attribute_order_item.unit_retail_price = ao_prd.get_retail_price(campaign)
                attribute_order_item.quantity = cart_item["attributes"][attribute_product_id]["quantity"]
                attribute_order_item.save()
                attribute_order_items.append(attribute_order_item)

            # KB: [2013-02-24]: Discount is calculated by using the highest price of the discounts for the product and all of its selected attributes
            discount = max(
                [util.nvl(aois.unit_discount_price) for aois in attribute_order_items]
                + [prd.get_discount_price(campaign)]
            )
            # KB: [2013-02-24]: Retail is calculated by using the highest price of the retail prices for the product and all its selected attributes.
            retail = max(
                [util.nvl(aois.unit_retail_price, 0.0) for aois in attribute_order_items]
                + [cart_item["base_price"] if "base_price" in cart_item else prd.get_retail_price(campaign)]
            )

            item.quantity = float(cart_item["quantity"])
            item.unit_price = discount if discount else retail
            if campaign.tax_rate and incl_tax:
                item.tax = (item.unit_price * item.quantity) * campaign.tax_rate
            item.unit_cost = prd.unit_cost
            item.unit_discount_price = discount if discount else None
            item.unit_retail_price = retail
            item.save()
            if prd.track_inventory:
                InventoryJournal.create_new(prd, "Sale", int(item.quantity), item)
            if item.unit_discount_price is not None:
                discount = DiscountProduct.find_by_product(prd)
                Journal.create_new(
                    (item.unit_retail_price - item.unit_discount_price) * int(item.quantity),
                    customer,
                    cord,
                    None,
                    typ="AutomaticDiscount",
                    attachment=discount,
                )
            Status.add(
                customer,
                item,
                Status.find_event(enterprise_id, item, "CREATED"),
                "Item added to order %s @ $%s" % (prd.name, util.money(item.unit_price)),
            )
            if prd.can_have_children():
                item.flush()  # we need this to get the parent ID.
                children = prd.get_children()
                if children and len(children) > 0:
                    for kid in children:
                        child_item = OrderItem()
                        child_item.order = cord
                        child_item.parent_id = item.order_item_id
                        child_item.product = kid.child
                        child_item.creator = user_created
                        child_item.start_dt = cart_item["start_dt"]
                        child_item.unit_price = 0.0
                        child_item.unit_discount_price = None
                        child_item.unit_retail_price = 0.0
                        child_item.unit_cost = prd.unit_cost
                        child_item.quantity = kid.child_quantity
                        if kid.child.track_inventory:
                            InventoryJournal.create_new(kid.child, "Sale", child_item.quantity, child_item)
        Status.add(customer, cord, Status.find_event(enterprise_id, cord, "CREATED"), "Order created ")
        if cord.discount:
            discount_amount = None
            if cord.discount.percent_off:
                item_price = cord.total_item_price()
                discount_amount = item_price - (item_price * cord.discount.percent_off)
            elif cord.discount.shipping_percent_off:
                # (9.0 / (1.0-0.1)) = 10.00
                discount_amount = cart.shipping_discount_total
            if discount_amount and int(discount_amount) > 0:
                Journal.create_new(
                    discount_amount, customer, cord, None, typ="AutomaticDiscount", attachment=cord.discount
                )
        cord.save()
        cord.flush()
        return cord
Example #7
0
    def edit_order(self):   #pylint: disable-msg=R0915,R0912
        customer_id = self.request.matchdict.get('customer_id')
        order_id = self.request.matchdict.get('order_id')
        oids_to_delete = self.request.POST.getall('order_items_to_delete[]')
        customer = Customer.load(customer_id)
        self.forbid_if(not customer or customer.campaign.company.enterprise_id != self.enterprise_id)
        order = customer.get_order(order_id)
        self.forbid_if(not order)
        order.shipping_total = self.request.POST.get('shipping_total') if self.request.POST.get('shipping_total') else 0.0
        order.create_dt = self.request.POST.get('create_dt') if self.request.POST.get('create_dt') else order.create_dt
        order.save()

        total_payments_applied = order.total_payments_applied()

        for oid in oids_to_delete:
            oitem = OrderItem.load(oid)
            Status.add(customer, oitem, Status.find_event(self.enterprise_id, oitem, 'DELETED'), 'OrderItem deleted ')
            prod = oitem.product
            if prod.track_inventory:
                InventoryJournal.create_new(prod, 'Cancelled Item', oitem.quantity, oitem)
            for attr_kid in oitem.children:
                Status.add(customer, attr_kid, Status.find_event(self.enterprise_id, attr_kid, 'DELETED'), 'OrderItem deleted ')
                attr_kid_prod = attr_kid.product
                if attr_kid_prod.track_inventory:
                    InventoryJournal.create_new(attr_kid_prod, 'Cancelled Item', oitem.quantity, attr_kid)
                attr_kid.soft_delete()
            oitem.soft_delete()                

        # extract order_items[27][quantity] to set those properties.
        order_items = {}
        for key in self.request.POST.keys():
            if key.startswith('order_items'):
                match = re.search(r'^.*\[(.*)\]\[(.*)\]', key)
                if match:
                    order_item_id = match.group(1)
                    attr = match.group(2)
                    new_val = float(self.request.POST.get(key)) if attr != 'product_id' else self.request.POST.get(key)
                    # KB: [2011-03-07]: If the ID ends in '_', its not really an ID but a new item.
                    # product_id will only show up as non-null in the hash of a new product
                    if order_item_id[-1] == '_':
                        order_item_product = Product.load(self.request.POST.get('order_items[%s][product_id]' % order_item_id))
                        if not order_items.has_key(order_item_id):
                            order_items[order_item_id] = order.augment_order(customer,
                                                                             order_item_product,
                                                                             customer.campaign,
                                                                             self.request.ctx.user)
                        oitem = order_items[order_item_id]
                        assert oitem.product is not None
                        if 'quantity' == attr:
                            new_val = float(new_val)
                            if order_item_product.track_inventory:
                                InventoryJournal.create_new(order_item_product, 'Sale', new_val, oitem)
                        setattr(oitem, attr, new_val)
                        oitem.save()
                    else:
                        if not order_items.has_key(order_item_id):
                            order_items[order_item_id] = OrderItem.load(order_item_id)
                        oitem = order_items[order_item_id]
                        order_item_product = oitem.product

                        if util.money(getattr(oitem, attr)) != util.money(new_val):
                            Status.add(customer, oitem, Status.find_event(self.enterprise_id, oitem, 'MODIFIED'),
                                       'Order Item modified: (id=%s). %s : %s -> %s' % (oitem.order_item_id, attr, util.money(getattr(oitem, attr)), util.money(new_val)))
                        if 'quantity' == attr:
                            new_val = float(new_val)
                            if not total_payments_applied:
                                if order_item_product.track_inventory:
                                    InventoryJournal.cleanup(oitem, 'Sale')
                                    InventoryJournal.create_new(order_item_product, 'Sale', new_val, oitem)
                        setattr(oitem, attr, new_val)
                        oitem.save()
        Status.add(customer, order, Status.find_event(self.enterprise_id, order, 'MODIFIED'), 'Order modified')
        customer.invalidate_caches()
        self.flash("Saved Order")
        return 'True'