def show_returns(self): product_id = self.request.matchdict['product_id'] product = Product.load(product_id) self.forbid_if(not product or product.company.enterprise_id != self.enterprise_id) return {'product' : product, 'events' : util.select_list(StatusEvent.find_all_applicable(self.enterprise_id, product), 'event_id', 'display_name'), 'returns' : ProductReturn.find(product)}
def save_inventory(self): prod = Product.load(self.request.POST.get('id')) self.forbid_if(not prod or prod.company.enterprise_id != self.enterprise_id) InventoryJournal.create_new(prod, 'Inventory Adjust', float(self.request.POST.get('inventory', 0))) prod.name = self.request.POST.get('name') prod.manufacturer = self.request.POST.get('manufacturer') prod.unit_cost = util.nvl(self.request.POST.get('unit_cost'), 0.0) prod.sku = self.request.POST.get('sku') prod.inventory_par = util.nvl(self.request.POST.get('inventory_par'), None) prod.save() # save all the prices, prefixed by "cmp_" for k in self.request.POST.keys(): if k.startswith('cmp_'): match = re.search(r'^.*_(.*)', k) if match: campaign = Campaign.load(match.group(1)) price = self.request.POST.get(k) if price: price = util.float_(price) prod.set_price_only(campaign, price) else: prod.remove_price(campaign) prod.invalidate_caches(campaign_id=campaign.campaign_id) return 'True'
def product(self): product_id = self.request.matchdict.get("product_id") if not util.is_uuid(product_id): # it's not really a product ID, but a search string from a bot. raise HTTPFound("/ecom/search?search=%s" % product_id) prod = Product.load(product_id) self.redir_if(not prod or not prod.enabled or not prod.web_visible) page = self.request.matchdict.get( "page", util.nvl(prod.render_template, "product") ) # /product/{product_id}/{page} self.session["last_product_id"] = product_id self.session["back_link"] = "/product/%s" % product_id params = self.params() self._add_to_recent_products(prod) params["product"] = prod params["products_also_liked"] = SmartCatalog.also_liked_product_list(prod, params["campaign"]) params["products_related"] = SmartCatalog.related_product_list(prod, params["campaign"]) params["product_attributes"] = self._prep_product_attributes(prod.get_product_attributes()) params["attrs"] = prod.get_attrs() params["price"] = SmartPricing.product_price(prod, params["campaign"]) (params["seo_title"], params["seo_keywords"], params["seo_description"]) = SmartSeo.product_seo( prod, self.request.ctx.site ) return self.render(page, params)
def upload_picture(self): product_id = self.request.matchdict.get('product_id') product = Product.load(product_id) self.forbid_if(not product or product.company.enterprise_id != self.enterprise_id) ass = Asset.create_new(product, self.enterprise_id, self.request) self.flash('Uploaded new image to product') product.invalidate_caches() return str(ass.id)
def show_purchases(self): product_id = self.request.matchdict['product_id'] from pvscore.model.crm.purchase import PurchaseOrderItem product = Product.load(product_id) self.forbid_if(not product or product.company.enterprise_id != self.enterprise_id) return {'product' : product, 'events' : util.select_list(StatusEvent.find_all_applicable(self.enterprise_id, product), 'event_id', 'display_name'), 'purchase_order_items' : PurchaseOrderItem.find_by_product(product) }
def delete_picture(self): product_id = self.request.matchdict.get('product_id') product = Product.load(product_id) self.forbid_if(not product or product.company.enterprise_id != self.enterprise_id) asset_id = self.request.matchdict.get('asset_id') asset = Asset.load(asset_id) self.forbid_if(asset.fk_type != 'Product' or str(asset.fk_id) != str(product.product_id)) asset.delete() return 'True'
def save_status(self): product_id = self.request.POST['product_id'] product = Product.load(product_id) self.forbid_if(not product or product.company.enterprise_id != self.enterprise_id) event = StatusEvent.load(self.request.POST['event_id']) self.forbid_if(not event or (not event.is_system and event.enterprise_id != self.enterprise_id)) note = self.request.POST.get('note') Status.add(None, product, event, note, self.request.ctx.user) return HTTPFound('/crm/product/show_history/%s' % product_id)
def delete(self): product_id = self.request.matchdict.get('product_id') product = Product.load(product_id) self.forbid_if(not product or str(product.company.enterprise_id) != str(self.enterprise_id)) product.mod_dt = util.now() product.delete_dt = util.now() Status.add(None, product, StatusEvent.find(self.enterprise_id, 'Product', 'DELETED'), 'Product Deleted') product.invalidate_caches() return 'True'
def update(self): product_id = self.request.matchdict.get('product_id') quantity = self.request.matchdict.get('quantity') redir = self.request.GET.get('redir') cart = self.session['cart'] product = Product.load(product_id) cart.remove_item(product) cart.add_item(product, self.request.ctx.campaign, quantity) self.session.changed() return 'True' if not redir else HTTPFound(redir)
def remove(self): if not 'cart' in self.session: return 'False' #pragma: no cover redir = self.request.GET.get('redir') cart = self.session['cart'] product_id = self.request.matchdict.get('product_id') product = Product.load(product_id) cart.remove_item(product) self.session.changed() return 'True' if not redir else HTTPFound(redir)
def _edit_impl(self): product_id = self.request.matchdict.get('product_id') campaigns = Campaign.find_all(self.enterprise_id) companies = util.select_list(Company.find_all(self.enterprise_id), 'company_id', 'name') product_types = Product.get_types() vendors = util.select_list(Vendor.find_all(self.enterprise_id), 'vendor_id', 'name', True) categories = util.select_list(ProductCategory.find_all(self.enterprise_id), 'category_id', 'name', True) if product_id: product = Product.load(product_id) self.forbid_if(not product or product.company.enterprise_id != self.enterprise_id) product_categories = ProductCategory.find_by_product(product) else: product = Product() product_categories = [] self.forbid_if(self.request.ctx.user.is_vendor_user() and product.product_id and not self.request.ctx.user.vendor_id == product.vendor_id) children = product.get_children() other_products = product.find_eligible_children() non_children = [] for prod in other_products: found = False for kid in children: if kid.child_id == prod.product_id: found = True break if found == False: non_children.append(prod) return { 'product' : product, 'campaigns' : campaigns, 'companies' : companies, 'product_types' : product_types, 'vendors' : vendors, 'categories' : categories, 'product_categories' : product_categories, 'children' : children, 'non_children': non_children, 'other_products' : other_products, 'events' : util.select_list(StatusEvent.find_all_applicable(self.enterprise_id, product), 'event_id', 'display_name'), 'is_attribute' : self.request.GET.get('is_attribute') == 'True', 'parent_product' : Product.load(self.request.GET.get('parent_id')) if 'parent_id' in self.request.GET else None }
def import_product_list(company_id, filename='/tmp/products/products.csv'): company = Company.load(company_id) default_campaign = company.default_campaign products = [] with open(filename) as f: products = f.readlines() products = [p.rstrip() for p in products[1:]] product_categories = {} for pline in products: log(pline) (product_name, category_id, pic) = pline.split(',') pic = pic.strip() key = '%s%s' % (product_name.strip(), category_id.strip()) cat = ProductCategory.load(category_id.strip(), False) prod = None if key in product_categories: prod = Product.load(product_categories[key][0], False) else: prod = Product() prod.company = company prod.name = product_name.strip() prod.type = 'Parent or Child' prod.save() prod.flush() product_categories[key] = [str(prod.product_id), str(cat.category_id)] ass = Asset() ass.fk_type = 'Product' ass.fk_id = prod.product_id ass.enterprise_id = company.enterprise_id ass.name = os.path.basename(pic) ass.extension = os.path.splitext(pic)[1] ass.save() ass.flush() storage_root = Asset.get_storage_root() if not storage_root: storage_root = '/apps/pvs/storage' fs_real_dir = "{root}/{reldir}".format(root=storage_root, reldir=ass.relative_dir) util.mkdir_p(fs_real_dir) fs_real_path = "{fs_real_dir}/{assid}{ext}".format(fs_real_dir=fs_real_dir, assid=ass.id, ext=ass.extension) shutil.copyfile(pic, fs_real_path) for pc in product_categories: pcat = product_categories[pc] cat = ProductCategory.load(pcat[1], False) cat.add_product(pcat[0]) db.commit()
def add(self): """ KB: [2013-02-20]: MOD ATTR: CartController.add : Allow for ajax of adding a simple item (HUS), or post/redir for adding products with attributes. """ product_id = self.request.matchdict.get('product_id') quantity = self.request.matchdict.get('quantity') redir = self.request.POST.get('redir') note = self.request.POST.get('note') cart = self.session['cart'] product = Product.load(product_id) cart.add_item(product, self.request.ctx.campaign, quantity, note=note) self.session.changed() return 'True' if not redir else HTTPFound(redir)
def add_order(self): """ KB: [2013-02-20]: MOD ATTR CustomerController.add_order : Modify to allow for attributes to be passed in the post. """ customer_id = self.request.matchdict.get('customer_id') cust = Customer.load(customer_id) self.forbid_if(not cust) # KB: [2013-02-24]: products are passed as products[$product_id] = quantity product_ids = {} for key in self.request.POST.keys(): if key.startswith('products'): match = re.search(r'^.*\[(.*)\]', key) if match: pid = match.group(1) quant = float(util.nvl(self.request.POST.get(key), '1.0')) if pid not in product_ids: product_ids[pid] = 0 product_ids[pid] += quant # KB: [2013-02-24]: attributes are passed as attributes[$attribute_id] = $parent_product_id attributes = {} for key in self.request.POST.keys(): if key.startswith('attributes'): match = re.search(r'^.*\[(.*)\]', key) if match: attribute_product_id = match.group(1) parent_product_id = self.request.POST.get(key) attributes[attribute_product_id] = { 'parent_product' : Product.load(parent_product_id), 'attribute_product' : Product.load(attribute_product_id) } order_id = self._add_order_impl(customer_id, product_ids, attributes, None, self.request.ctx.user, self.request.POST.get('discount_id'), self.request.POST.get('campaign_id', self.request.GET.get('campaign_id')), self.incl_tax) cust.invalidate_caches() return str(order_id)
def add_attributed_product(self): """ KB: [2013-02-24]: var attributes = {}; attributes[$('#color_id').val()] = 0; // quantity of zero, unless its really something that requires a quantity. attributes[$('#size_id').val()] = 0; $.post('/ecom/cart/add_attributed_product', { product_id : base_product_id, attributes : attributes, quantity : $('#qty').val() }, function(resp) { if (resp == 'True') { window.location = '/product/' + base_product_id; } }); """ redir = self.request.POST.get('redir') product_id = self.request.POST.get('product_id') quantity = self.request.POST.get('quantity') cart = self.session['cart'] attributes = {} for key in self.request.POST.keys(): if key.startswith('attributes'): match = re.search(r'^.*\[(.*)\]', key) if match: pid = match.group(1) quant = float(util.nvl(self.request.POST.get(key), '1.0')) attributes[pid] = { 'quantity' : quant, 'product' : Product.load(pid) } product = Product.load(product_id) self.forbid_if(not product) cart.add_item(product, self.request.ctx.campaign, quantity, attributes=attributes) self.session.changed() return 'True' if not redir else HTTPFound(redir)
def _test_save_status(self): ent = Enterprise.find_by_name('Healthy U Store') product_id = self._create_new() product = Product.load(product_id) events = StatusEvent.find_all_applicable(ent.enterprise_id, product) R = self.post('/crm/product/save_status', {'product_id': product_id, 'note' : 'Test Note %s' % product_id, 'event_id' : events[0].event_id}) assert R.status_int == 200 R.mustcontain('Product Event History') R.mustcontain('Test Note %s' % product_id) # assert that the edit page has the name of the event in green # at the top. R = self.get('/crm/product/edit/%s' % product_id) assert R.status_int == 200 R.mustcontain('Edit Product') R.mustcontain(events[0].short_name) self._delete_new(product_id)
def _test_save_inventory(self): ent = Enterprise.find_by_name('Healthy U Store') cmpns = Campaign.find_all(ent.enterprise_id) R = self.get('/crm/product/inventory_list') assert R.status_int == 200 prods = json.loads(R.body) self.assertGreater(prods['records'], 100) self.assertEqual(prods['records'], len(prods['rows'])) # get the first product ID prod = prods['rows'][1]['cell'] # ['', '1451', '5-HTP 100 mg- Pharmax', 'SUP-1003', 'Seroyal', '123', '8.0', '15.0', '25.00', '', '25.00', '25.00'] pid = prod[1] name = prod[2] #sku = prod[3] #manu = prod[4] inventory = int(prod[5]) inventory_par = prod[6] unitcost = prod[7] R = self.post('/crm/product/save_inventory', {'id' : pid, 'inventory' : inventory + 10, 'inventory_par' : inventory_par, 'name' : name + ' xxx', 'unit_cost' : unitcost, 'cmp_%s' % cmpns[0].campaign_id : '999', 'cmp_%s' % cmpns[1].campaign_id : ''}) self.assertEquals(R.body, 'True') prod = Product.load(pid) tot = InventoryJournal.total(prod) self.assertEqual(tot, inventory + 10) self.assertEqual(999, prod.campaign_prices[cmpns[0].campaign_id].retail_price) self.assertEqual(True, cmpns[1].campaign_id not in prod.campaign_prices.keys()) R = self.get('/crm/product/edit/%s' % pid) assert R.status_int == 200 f = R.forms['frm_product'] R.mustcontain('Edit Product') self.assertEqual(f['product_id'].value, pid) self.assertEqual(f['name'].value, name + ' xxx')
def _add_order_impl(self, customer_id, product_ids, attributes, prices, user, discount_id, campaign_id, incl_tax=True): #pylint: disable-msg=R0913 """ KB: [2013-02-20]: attributes = [{quantity : 0, product : <Product...>}, {...}] """ cust = Customer.load(customer_id) self.forbid_if(not cust or cust.campaign.company.enterprise_id != self.enterprise_id) cart = Cart() campaign_id = campaign_id if campaign_id else cust.campaign_id cart.discount_id = discount_id for pid in product_ids.keys(): quantity = product_ids[pid] price = prices[pid] if prices and pid in prices else None attrs = {} for attr in [attr['attribute_product'] for attr in attributes.values() if str(attr['parent_product'].product_id) == pid]: attrs[attr.product_id] = { 'quantity' : 0, 'product' : attr} cart.add_item(product=Product.load(pid), campaign=cust.campaign, quantity=quantity, attributes=attrs, base_price=price) order = cust.add_order(cart, user, self.enterprise_id, cust.campaign, incl_tax=incl_tax) order.flush() return order.order_id
def _test_save_existing(self): ent = Enterprise.find_by_name('Healthy U Store') cmpns = Campaign.find_all(ent.enterprise_id) product_id = self._create_new() R = self.get('/crm/product/list') assert R.status_int == 200 R.mustcontain('Test Product') R.mustcontain('Product Search') # make sure product search is in 2 places R = self.get('/crm/product/edit/%s' % product_id) R.mustcontain('Edit Product') f = R.forms['frm_product'] self.assertEqual(f['product_id'].value, product_id) self.assertEqual(f['name'].value, 'Test Product') self.assertEqual(f['seo_keywords'].value, 'SEO Test') f.set('name', 'Test Product New') f.set('seo_keywords', 'SEO Test New') for prod in Product.find_all_except(Product.load(product_id))[:3]: f.set('child_incl_%s' % prod.product_id, prod.product_id) f.set('child_quantity_%s' % prod.product_id, 2) f.set('campaign_price[%s]' % cmpns[0].campaign_id, "123") f.set('campaign_price[%s]' % cmpns[1].campaign_id, None) f.set('prod_inventory', 25) #cat = ProductCategory.find_all(ent.enterprise_id)[0] #f.set('category_id', cat.category_id) R = f.submit('submit') self.assertEqual(R.status_int, 302) R = R.follow() assert R.status_int == 200 f = R.forms['frm_product'] R.mustcontain('Edit Product') self.assertEqual(f['product_id'].value, product_id) self.assertEqual(f['name'].value, 'Test Product New') self.assertEqual(f['seo_keywords'].value, 'SEO Test New') self.assertEqual(f['campaign_price[%s]' % cmpns[0].campaign_id].value, "123.00") self.assertEqual(f['campaign_price[%s]' % cmpns[1].campaign_id].value, "") #self.assertEqual(f['category_id'].value, cat.category_id) prod = Product.load(product_id) self.assertEqual(25, InventoryJournal.total(prod)) for prod in Product.find_all_except(Product.load(product_id))[:3]: self.assertEqual(int(f['child_quantity_%s' % prod.product_id].value), 2) #put pricing back. R = self.get('/crm/product/edit/%s' % product_id) R.mustcontain('Edit Product') f = R.forms['frm_product'] self.assertEqual(f['product_id'].value, product_id) f.set('campaign_price[%s]' % cmpns[0].campaign_id, "123") f.set('campaign_price[%s]' % cmpns[1].campaign_id, "234") R = f.submit('submit') self.assertEqual(R.status_int, 302) R = R.follow() assert R.status_int == 200 f = R.forms['frm_product'] R.mustcontain('Edit Product') self.assertEqual(f['product_id'].value, product_id) self.assertEqual(f['campaign_price[%s]' % cmpns[1].campaign_id].value, "234.00") self._delete_new(product_id)
def save(self): #pylint: disable-msg=R0912,R0915 product_id = self.request.POST.get('product_id') if product_id: prod = Product.load(product_id) else: prod = Product() prod.bind(self.request.POST, True) prod.mod_dt = util.now() prod.save() self.db_flush() new_children = {} for k in self.request.POST.keys(): if k.startswith('campaign_price'): match = re.search(r'^.*\[(.*)\]', k) if match: campaign = Campaign.load(match.group(1)) price = self.request.POST.get(k) discount = self.request.POST.get('campaign_discount[%s]' % campaign.campaign_id) if price: price = util.float_(price) discount = util.float_(util.nvl(discount, 0.0)) prod.set_price(campaign, price, discount) else: prod.remove_price(campaign) if k.startswith('child_incl'): child_product_id = self.request.POST.get(k) child_product_quantity = self.request.POST.get('child_quantity_%s' % child_product_id) new_children[child_product_id] = child_product_quantity # KB: [2013-02-23]: Clear out old children that were just deselected and add the ones that are still selected. for current_child in prod.get_children(): if current_child.child_id not in new_children.keys(): prod.clear_child(current_child.child_id) for new_child_product_id in new_children.keys(): new_child_product_quantity = new_children[new_child_product_id] prod.add_child(new_child_product_id, new_child_product_quantity) prod.save() self.db_flush() redir_params = '' if 'parent_id' in self.request.POST and self.request.POST['parent_id']: parent = Product.load(self.request.POST['parent_id']) if not parent.has_child(prod.product_id): parent.add_child(prod.product_id) parent.save() redir_params = '?is_attribute=True&parent_id=%s' % parent.product_id inventory = str(self.request.POST.get('prod_inventory', '0')) if inventory and str(round(float(inventory), 2)) != str(round(util.nvl(InventoryJournal.total(prod), 0), 2)): InventoryJournal.create_new(prod, 'Inventory Adjust', inventory) self.db_flush() self.flash('Inventory Adjusted to %s' % inventory) prod.clear_attributes() for i in range(30): attr_name = self.request.POST.get('attr_name[%d]' % i) attr_value = self.request.POST.get('attr_value[%d]' % i) if attr_name and attr_value: prod.set_attr(attr_name, attr_value) category_id = self.request.POST.get('category_id') if category_id: category = ProductCategory.load(category_id) self.forbid_if(not category) category.add_product(prod.product_id) self.flash('Successfully saved %s.' % prod.name) return HTTPFound('/crm/product/edit/%s%s' % (prod.product_id, redir_params))
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'