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"> </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"> </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"> </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"> </td><td align="right">$%s</td></tr>' % util.money( self.total_tax(), True ) ret += ( '<tr><td><i>Total Payments</i></td><td colspan="2"> </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"> </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"> </td><td align="right">$%s</td></tr>' % util.money( self.total_payments_due(), True ) ret += "</table>" return ret
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)
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"> </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)
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'
def product_price(product, campaign): return util.money(product.get_price(campaign))
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
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'