def newDelivery(): formMaker = SelectMakerForm() formMaker.maker.choices = [(a.id, a.name) for a in Maker.query.all()] formQuantities = ProductQuantityForm() products = None if formMaker.is_submitted(): if formMaker.validate_on_submit(): maker_id = formMaker.maker.data if not maker_id: flash(gettext("Maker not found.")) return redirect(url_for("deliveries")) products = Product.query.order_by(Product.maker_id, Product.code)\ .filter_by(maker_id=int(maker_id), active_flg=True).all() for p in products: formQuantities.fields.append_entry() urls = getImgUrls(p.id) if urls: p.img_url = urls[0] return render_template('deliveries/newDelivery.html', title=gettext("New Delivery"), formMaker=formMaker, formQuantities=formQuantities, products=products)
def makerStock(): products = None if g.user.maker: products = Product.query.filter_by(active_flg=True)\ .filter_by(maker_id=g.user.maker_id)\ .all() if products: for p in products: if not p.price_unit: p.price_unit = 0 urls = getImgUrls(p.id) p.img_urls = [] p.img_thumb_urls = [] if urls: for u in urls: u = u.split('app')[1] p.img_urls.append(u) p.img_thumb_urls.append(getThumbUrls(u, height=80, width=80).split('app')[1]) else: p.img_urls.append(NO_PHOTO_URL.split('app')[1]) p.img_thumb_urls.append(NO_PHOTO_THUMB_URL.split('app')[1]) form = SimpleSubmitForm() if form.is_submitted(): string = request.form.getlist('product_data') if string: data_to_update = [] for s in string: raw = s.split(',') id = int(raw[0].split(':')[1]) code = raw[1].split(':')[1] str_qty = raw[2].split(':')[1] qty = 0 if str_qty: try: qty = int(str_qty) except ValueError: qty = 0; data_to_update.append({'id': id, 'code': code, 'qty': qty}) if data_to_update: for d in data_to_update: p = Product.query.get(d['id']) p.maker_code = d['code'] p.maker_qty_stock = d['qty'] db.session.add(p) db.session.commit() return render_template('maker/makerStock.html', title=gettext("My Stock"), products=products, form=form)
def generate_product_details_csv(categories=[]): path = os.path.join(CSV_PATH, ('axm_products_' + datetime.utcnow().strftime("%Y%m%d") + '.csv')) outfile = open(path, 'wb+') outcsv = csv.writer(outfile) products = Product.query\ .filter_by(active_flg=True) if categories: products = products.filter(Product.category_id.in_(categories)) products = products.order_by(Product.category_id)\ .order_by(Product.maker_id)\ .order_by(Product.code)\ .all() headers = [gettext('Product code'), gettext('Product Name'), gettext('Retail price'), gettext('Purchase price'), gettext('Image 1 URL'), gettext('Image 2 URL'), gettext('Image 3 URL'), gettext('Image 4 URL'), gettext('Image 5 URL')] outcsv.writerow([unicode(header).encode('utf-8') for header in headers]) discount = 0 if current_user.role == USER_ROLES['ROLE_CUSTOMER'] and current_user.customer: discount = current_user.customer.base_discount for product in products: if not product.price_retail: product.price_retail = 0 unrounded_price = product.price_retail * (1.0 - discount) product.customer_price = int(5 * round(float(unrounded_price)/5)) columns = [product.code, product.desc_JP, product.price_retail, product.customer_price] urls = getImgUrls(product.id) product.img_urls = [] if urls: for i in xrange(5): if i >= len(urls): columns.append('') else: url = request.url_root + urls[i].split('app')[1] url = url.replace('\\', '/') url = url.replace('//', '/') columns.append(url) else: for i in xrange(5): columns.append('') outcsv.writerow([unicode(column).encode('utf-8') for column in columns]) outfile.close() match = re.search(r"[^a-zA-Z](csv)[^a-zA-Z]", path) pos = match.start(1) filename = path[pos:] return filename
def editProduct(id=0): # for stock: return to the same page stock_page = request.args.get('stock_page') if request.args.get('stock_page') else 1 product = Product.query.filter_by(id=id).first() if product == None: flash(gettext('Product not found.')) return redirect(url_for('stock', page=stock_page)) form = AddProductForm(obj=product) makers = Maker.query.all() if makers: form.maker.choices = [(a.id, a.name) for a in makers] #for existing code validation form.request = request if form.validate_on_submit(): #delete product if 'delete' in request.form: product.active_flg = False db.session.add(product) db.session.commit() flash(gettext('Product has been deleted.')) return redirect(url_for("stock", page=stock_page)) #update catalog terms new_ids_str = request.form.getlist('term') new_ids = [] for id in new_ids_str: new_ids.append(int(id)) old_ids = [] for term in product.catalog_terms: old_ids.append(term.catalog_id) for id in old_ids: if id not in new_ids: t = CatalogedProducts.query\ .filter_by(catalog_id=id)\ .filter_by(product_id=product.id)\ .first() db.session.delete(t) for id in new_ids: if id not in old_ids: t = CatalogedProducts() t.product_id = product.id t.catalog_id = id db.session.add(t) db.session.commit() #update product product.code = form.code.data product.maker_id = form.maker.data product.maker_code = form.maker_code.data product.desc_CS = form.desc_CS.data product.desc_JP = form.desc_JP.data product.long_desc = form.long_desc.data product.detailed_desc = form.detailed_desc.data product.subcategory_desc = form.subcategory_desc.data product.keywords = form.keywords.data product.price_unit = form.price_unit.data product.price_retail = form.price_retail.data product.qty_stock = form.qty_stock.data product.limited_flg = form.limited_flg.data product.axm_node = form.axm_node.data if form.package_size.data == '': product.package_size = None else: product.package_size = form.package_size.data category_id = Maker.query.filter_by(id=product.maker_id).first().category_id if category_id: product.category_id = category_id db.session.add(product) db.session.commit() flash(gettext("Product successfully changed.")) return redirect(url_for("stock", page=stock_page)) selected_maker = product.maker_id imgUrls = getImgUrls(product.id) catalog = prepare_catalog() terms = product.catalog_terms terms.sort(key=lambda x: x.catalog.order) selected_catalog_terms = [] for term in terms: if term.catalog.super_id == None: level = 0 else: level = 1 selected_catalog_terms.append([term.catalog.id, level, unicode(term.catalog.name_CS)]) return render_template('product/editProduct.html', title=gettext("Edit Product"), product=product, catalog=catalog, imgUrls=imgUrls, selected_maker=selected_maker, selected_catalog_terms=selected_catalog_terms, stock_page=stock_page, form=form)
def stock(page=1): #Query products with conditions products = Product.query.filter_by(active_flg=True) curr_search = None if session['search_string']: curr_search = session['search_string'] products = products.filter(or_(Product.code.ilike('%' + session['search_string'] + '%'), (Product.desc_CS.ilike('%' + session['search_string'] + '%')), (Product.desc_JP.ilike('%' + session['search_string'] + '%')))) if g.maker_id is not None: products = products.filter(Product.maker_id == int(g.maker_id)) g.category_id = Maker.query.filter_by(id=g.maker_id).one().category_id if g.category_id: curr_category = Category.query.filter_by(id=g.category_id).one() products = products.filter_by(category_id=int(g.category_id)) available_makers_id = [maker.id for maker in curr_category.makers] else: available_makers_id = [maker.id for maker in Maker.query.all()] #Custom ordering if session['order_type']: order_type = session['order_type'].split('-') if order_type[0] == 'csdesc': property = Product.desc_CS elif order_type[0] == 'maker': property = Product.maker_id elif order_type[0] == 'jpdesc': property = Product.desc_CS elif order_type[0] == 'unitp': property = Product.price_unit elif order_type[0] == 'retap': property = Product.price_retail elif order_type[0] == 'stock': property = Product.qty_stock elif order_type[0] == 'req': property = Product.request_qty elif order_type[0] == 'ord': property = Product.order_qty elif order_type[0] == 'net': property = (Product.qty_stock - Product.request_qty + Product.order_qty) else: session['order_type'] = None property = None style = order_type[1] if style: if style == '3' or style == '4': products = products.filter(property > 0) if style == '5' or style == '6': products = products.filter(property <= 0) if style == '1' or style == '3' or style == '5': products = products.order_by(property.desc()) else: products = products.order_by(property) products = products.order_by(Product.maker_id, Product.code) products = products.paginate(page, current_user.products_per_page, False) #Query end categories = Category.query.order_by(Category.order.asc()).all() makers = Maker.query.filter(Maker.id.in_(available_makers_id)).all() curr_maker_name = Maker.query.filter_by(id=g.maker_id).one().name if g.maker_id else None form = EditQtyStockForm() if form.is_submitted(): if form.validate(): qty = form.qty_stock.data id = request.form['product_id'] if (qty and id) or (qty == 0 and id): product = Product.query.filter_by(id=int(id)).first() if product: product.qty_stock = qty db.session.add(product) db.session.commit() flash(gettext('Stock quantity successfully updated.')) else: flash(gettext('Input value error.')) else: flash(gettext('Input value error.')) page = request.form['page'] if request.form['product_id'] else 1 return redirect(url_for("stock", page=page)) for p in products.items: urls = getImgUrls(p.id) if urls: p.img_url = urls[0] return render_template("stock.html", title=gettext('Stock condition'), categories=categories, makers=makers, curr_maker_name=curr_maker_name, curr_search=curr_search, form=form, form_search=SearchForm(), axm_product_url=AXM_PRODUCT_URL, products=products)
def supplyProducts(): # Redirected from unsuppliedproducts? cust_id = request.args.get('cust_id') data_to_populate = request.args.get('deliver_items_data') # Yes, redirected from unsuppliedproducts if cust_id: cust_type_num = Customer.query.filter_by(id=cust_id).first().customer_type if cust_type_num == CUSTOMER_TYPES['TYPE_AXM']: custType = 'axm' else: custType = 'cust' # No, redirected from newsupply else: if not session['new_supply']: flash(gettext('No customer data!')) return redirect(url_for("supplies")) custType = session['new_supply'][0][1] cust_id = session['new_supply'][1][1] cust = Customer.query.filter_by(id=cust_id).first() if not cust: flash(gettext('Customer not found!')) return redirect(url_for("supplies")) if request.method == 'POST': ids = {} for attr in flask.request.form: if attr.startswith("supp_qty-"): key = attr.split('-')[1] if flask.request.form[attr] != '0': ids[key] = flask.request.form[attr] if not ids: flash(gettext('No product quantities!')) return redirect(url_for("supplies")) last_supply = Supply.query.filter_by(customer_id=cust_id).order_by(desc(Supply.created_dt)).first() new_supply = Supply() #TODO other date than now new_supply.created_dt = new_supply.customer_id = cust_id new_supply.user_id = g.user.id db.session.add(new_supply) db.session.commit() #variable for reporting purposes report = {'sender': g.user.nickname, 'customer': cust, 'date': new_supply.created_dt, 'order_no': cust.order_no, 'products': [], 'closed_requests': [], 'changed_requests': [], 'oversent_requests': False} # For recommender notification mail overall_product_value = 0 for id in ids: new_quantity = int(ids[id]) if new_quantity > 0: new_product = Product.query.filter_by(id=int(id)).first() if new_product: overall_product_value += new_product.price_retail * new_quantity rp = SuppliedProducts(quantity=new_quantity) rp.product = new_product rp.supply_id = new_supply.id new_supply.products.append(rp) report_details = {'product': new_product, 'qty': new_quantity, 'over': 0} temp_qty = new_quantity #get requested products from current customer for product from oldest all_products = new_product.request_assocs requested_products = [] for p in all_products: if p.request.customer_id == cust.id: requested_products.append(p) if not requested_products: flash(gettext('No requested products!')) return redirect(url_for("supplies")) requested_products.sort(key=lambda x: x.request.created_dt, reverse=False) for rp in requested_products: #count requested products quantity - qty_supplied = delta qty if rp.qty_supplied is None: rp.qty_supplied = 0 delta_qty = rp.quantity - rp.qty_supplied if delta_qty <= temp_qty: if new_product.qty_stock is not None: new_product.qty_stock -= (rp.quantity - rp.qty_supplied) rp.qty_supplied = rp.quantity #if request completely supplied add to report if rp.request.active_flg: if rp.request.check_completely_supplied(): while True: if rp.request in report['changed_requests']: report['changed_requests'].remove(rp.request) else: break report['closed_requests'].append(rp.request) else: if rp.request not in report['changed_requests']: report['changed_requests'].append(rp.request) if delta_qty == temp_qty: temp_qty = 0 break else: if new_product.qty_stock is not None: new_product.qty_stock -= temp_qty rp.qty_supplied += temp_qty temp_qty -= rp.qty_supplied if rp.request not in report['changed_requests']: report['changed_requests'].append(rp.request) break temp_qty -= delta_qty if temp_qty > 0: if new_product.qty_stock is not None: new_product.qty_stock -= temp_qty report_details['over'] = temp_qty report['oversent_requests'] = True report['products'].append(report_details) #set new nohinsho number if custType = customer if cust.customer_type == CUSTOMER_TYPES['TYPE_CUSTOMER']: if not cust.order_no: cust.order_no = 1 else: if last_supply: date_old = datetime.datetime(*map(int, re.split('[^\d]', str(last_supply.created_dt))[:-1])) date_new = datetime.datetime(*map(int, re.split('[^\d]', str(new_supply.created_dt))[:-1])) if date_old.year == date_new.year: if date_old.month == date_new.month: cust.order_no += 1 else: cust.order_no = 1 else: cust.order_no = 1 db.session.add(cust) #FINAL COMMIT db.session.commit() flash(gettext('New supply sent sucessfully.')) print report #prepare data for xls product_ids=[] for p in report['products']: product_ids.append([p['product'].id, p['qty']]) session['new_supply_data'] = {'date': report['date'], 'customer': cust.id, 'products': product_ids} # If this customer has a recommender-customer, send notification mail with supply price amount if cust.recommender_id and cust.recommender_id is not '': send_notification_mail_to_recommender(cust, overall_product_value) return render_template('supplies/supplyReport.html', title=gettext("Supply Report"), custType=custType, report=report) requests = cust.requests.all() products = [] for r in requests: for rp in r.products: if rp.product not in products: rp.product.cust_request_qty = rp.product.customer_request_qty(cust.id) if rp.product.cust_request_qty > 0: products.append(rp.product) products = sorted(products, key=lambda k: (k.maker_id, k.code)) for p in products: urls = getImgUrls(p.id) if urls: p.img_url = urls[0] # If AxM customer, check if the order is paid for paid_for = True if cust.customer_type == CUSTOMER_TYPES['TYPE_AXM']: req = cust.requests.all()[0] paid_for = req.paid_for_flg return render_template('supplies/supplyProducts.html', custType=custType, customer=cust, products=products, paid_for=paid_for, data_to_populate=data_to_populate)
def unsuppliedProducts(id=None): form = SimpleSubmitForm() if form.is_submitted(): if 'checked-items-ids-hid' in request.form: cust_id = request.form['curr-customer-id-hid'] data = request.form['checked-items-ids-hid'] return redirect(url_for('supplyProducts', cust_id=cust_id, deliver_items_data=data)) unsupplied_requests = Request.query.filter_by(active_flg=True).all() customer_ids = [] for ur in unsupplied_requests: if ur.customer_id not in customer_ids: customer_ids.append(ur.customer_id) unsupplied_customers = db.session.query(Customer)\ .filter(Customer.id.in_(customer_ids)).order_by(Customer.id)\ .all() for uc in unsupplied_customers: uc.unsupplied_products_count = 0 for ur in unsupplied_requests: if ur.customer_id == uc.id: for product in ur.products: if product.quantity > product.qty_supplied: uc.unsupplied_products_count += (product.quantity - product.qty_supplied) if not id: id = unsupplied_customers[0].id cust = Customer.query.filter_by(id=id).first() requests = cust.requests.all() products = [] for r in requests: for rp in r.products: if rp.product not in products: rp.product.cust_request_qty = rp.product.customer_request_qty(cust.id) if rp.product.cust_request_qty > 0: products.append(rp.product) # Load number of products reserved earlier by other customers for p in products: stock = p.qty_stock cust_earliest_request_dt = RequestedProducts.query.filter_by(product_id=p.id)\ .filter(RequestedProducts.quantity - RequestedProducts.qty_supplied > 0)\ .join(Request).order_by(Request.created_dt)\ .join(Customer).filter(Customer.id == cust.id)\ .first().request.created_dt earlier_requests = RequestedProducts.query.filter_by(product_id=p.id)\ .filter(RequestedProducts.quantity - RequestedProducts.qty_supplied > 0)\ .join(Request).filter(Request.created_dt < cust_earliest_request_dt)\ .join(Customer).filter(Customer.id != cust.id)\ .all() p.reserved_earlier_qty = 0 for er in earlier_requests: p.reserved_earlier_qty += er.quantity - er.qty_supplied temp = p.qty_stock - p.reserved_earlier_qty if temp <= 0: p.deliverable_qty = 0 elif temp > p.cust_request_qty: p.deliverable_qty = p.cust_request_qty else: p.deliverable_qty = temp products = sorted(products, key=lambda k: (k.maker_id, k.code)) for p in products: urls = getImgUrls(p.id) if urls: p.img_url = urls[0] # If AxM customer, is the order paid for_ curr_paid = True if cust.customer_type == CUSTOMER_TYPES['TYPE_AXM']: curr_req = cust.requests.all()[0] if curr_req: curr_paid = curr_req.paid_for_flg return render_template('supplies/unsuppliedproducts.html', title=gettext("Unsupplied products"), form=form, unsupplied_customers=unsupplied_customers, products=products, CUSTOMER_TYPES=CUSTOMER_TYPES, curr_id=id, curr_paid=curr_paid)
def shop(page=1): products = Product.query.filter_by(active_flg=True) curr_search = None if session['search_string']: curr_search = session['search_string'] products = products.filter(or_(Product.code.ilike('%' + session['search_string'] + '%'), (Product.desc_CS.ilike('%' + session['search_string'] + '%')), (Product.desc_JP.ilike('%' + session['search_string'] + '%')))) curr_catalog_terms = None if session['catalog_ids']: cps = CatalogedProducts.query.filter(CatalogedProducts.catalog_id.in_(session['catalog_ids'])).all() cataloged_product_ids = [] curr_catalog_terms = [] for cp in cps: cataloged_product_ids.append(cp.product_id) for id in session['catalog_ids']: curr_catalog_terms.append(Catalog.query.get(id).name_JP) products = products.filter(Product.id.in_(cataloged_product_ids)) if g.category_id: products = products.filter_by(category_id=int(g.category_id)) if session['available_only'] is True: products = products.filter(Product.available_qty > 0) products = products.order_by(Product.maker_id, Product.code) products = products.paginate(page, current_user.products_per_page, False) discount = 0 if current_user.role == USER_ROLES['ROLE_CUSTOMER'] and current_user.customer: discount = current_user.customer.base_discount for p in products.items: if not p.price_retail: p.price_retail = 0 unrounded_price = p.price_retail * (1.0 - discount) p.customer_price = int(5 * round(float(unrounded_price)/5)) urls = getImgUrls(p.id) p.img_urls = [] p.img_thumb_urls = [] if urls: for u in urls: u = u.split('app')[1] p.img_urls.append(u) p.img_thumb_urls.append(getThumbUrls(u).split('app')[1]) else: p.img_urls.append(NO_PHOTO_URL.split('app')[1]) p.img_thumb_urls.append(NO_PHOTO_THUMB_URL.split('app')[1]) form = ShopHeaderForm() categories = [(a.id, a.name_JP) for a in Category.query.all()] categories = [(0, gettext('All'))] + categories form.category.choices = categories catalog = prepare_catalog() return render_template('/shop/shop.html', title=gettext('AxiStore shop'), products=products, curr_category=g.category_id, axm_product_url=AXM_PRODUCT_URL_JA, curr_search=curr_search, curr_catalog_terms=curr_catalog_terms, catalog=catalog, form=form)
def placeorder(): cart_items = Cart.query.filter_by(user_id=current_user.id).all() form = ShopOrderConfirmForm() if form.validate_on_submit(): new_request = Request() new_request.user_id = current_user.id if not current_user.customer: flash(gettext("We apologize but your customer data is insufficient. Please, contact our customer support.")) return redirect(url_for("shop")) customer_note = form.note.data if customer_note: new_request.note = customer_note new_request.customer_id = current_user.customer.id new_request.active_flg = True db.session.add(new_request) db.session.commit() for item in cart_items: new_product = db.session.query(Product).filter_by(id=item.product_id).first() if not new_product: flash(gettext("Product not found.")) return redirect(url_for("shop")) rp = RequestedProducts(quantity=item.quantity) rp.product = new_product rp.request_id = new_request.id new_request.products.append(rp) db.session.delete(item) db.session.commit() # send confirmation email mailer.order_confirmation(current_user, new_request) flash(gettext("Order created successfully.")) return redirect(url_for("orderconfirm", req_id=new_request.id)) discount = 0 if current_user.role == USER_ROLES['ROLE_CUSTOMER'] and current_user.customer: discount = current_user.customer.base_discount total = 0 pieces = 0 for item in cart_items: if not item.product.price_retail: item.product.price_retail = 0 unrounded_price = item.product.price_retail * (1.0 - discount) item.customer_price = int(5 * round(float(unrounded_price)/5)) total += item.customer_price * item.quantity pieces += item.quantity urls = getImgUrls(item.product.id) if urls: item.img_url = urls[0].split('app')[1] else: item.img_url = NO_PHOTO_URL.split('app')[1] return render_template('/shop/placeorder.html', title=gettext('Place order'), cart_items=cart_items, total=total, pieces=pieces, form=form)
def generate_product_details_csv(categories=[]): path = os.path.join( CSV_PATH, ('axm_products_' + datetime.utcnow().strftime("%Y%m%d") + '.csv')) outfile = open(path, 'wb+') outcsv = csv.writer(outfile) products = Product.query\ .filter_by(active_flg=True) if categories: products = products.filter(Product.category_id.in_(categories)) products = products.order_by(Product.category_id)\ .order_by(Product.maker_id)\ .order_by(Product.code)\ .all() headers = [ gettext('Product code'), gettext('Product Name'), gettext('Retail price'), gettext('Purchase price'), gettext('Image 1 URL'), gettext('Image 2 URL'), gettext('Image 3 URL'), gettext('Image 4 URL'), gettext('Image 5 URL') ] outcsv.writerow([unicode(header).encode('utf-8') for header in headers]) discount = 0 if current_user.role == USER_ROLES[ 'ROLE_CUSTOMER'] and current_user.customer: discount = current_user.customer.base_discount for product in products: if not product.price_retail: product.price_retail = 0 unrounded_price = product.price_retail * (1.0 - discount) product.customer_price = int(5 * round(float(unrounded_price) / 5)) columns = [ product.code, product.desc_JP, product.price_retail, product.customer_price ] urls = getImgUrls(product.id) product.img_urls = [] if urls: for i in xrange(5): if i >= len(urls): columns.append('') else: url = request.url_root + urls[i].split('app')[1] url = url.replace('\\', '/') url = url.replace('//', '/') columns.append(url) else: for i in xrange(5): columns.append('') outcsv.writerow( [unicode(column).encode('utf-8') for column in columns]) outfile.close() match = re.search(r"[^a-zA-Z](csv)[^a-zA-Z]", path) pos = match.start(1) filename = path[pos:] return filename