[Website] Items list and stock (#11480)
* Add stock availability in items list and a parameter to set the number of products per page * Substract reserved_qty from actual_qty for website stock
This commit is contained in:
parent
82b200e497
commit
2a89a502f0
@ -1,17 +1,23 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2016-04-22 09:11:55.272398",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 0,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "If checked, the Home page will be the default Item Group for the website",
|
||||
"fieldname": "home_page_is_products",
|
||||
"fieldtype": "Check",
|
||||
@ -19,7 +25,9 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Home Page is Products",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
@ -28,6 +36,7 @@
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@ -35,16 +44,20 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "products_as_list",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Show Products as a List",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
@ -53,6 +66,39 @@
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "6",
|
||||
"fieldname": "products_per_page",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Products per Page",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@ -60,16 +106,17 @@
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-04-22 09:11:59.537639",
|
||||
"modified": "2017-11-07 19:34:33.055048",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Portal",
|
||||
"name": "Products Settings",
|
||||
@ -100,7 +147,9 @@
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Products Settings", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Products Settings
|
||||
() => frappe.tests.make('Products Settings', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
class TestProductsSettings(unittest.TestCase):
|
||||
pass
|
@ -57,7 +57,7 @@ class ItemGroup(NestedSet, WebsiteGenerator):
|
||||
|
||||
def get_context(self, context):
|
||||
context.show_search=True
|
||||
context.page_length = 6
|
||||
context.page_length = cint(frappe.db.get_single_value('Products Settings', 'products_per_page')) or 6
|
||||
context.search_link = '/product_search'
|
||||
|
||||
start = int(frappe.form_dict.start or 0)
|
||||
@ -81,24 +81,26 @@ def get_product_list_for_group(product_group=None, start=0, limit=10, search=Non
|
||||
child_groups = ", ".join(['"' + i[0] + '"' for i in get_child_groups(product_group)])
|
||||
|
||||
# base query
|
||||
query = """select name, item_name, item_code, route, image, website_image, thumbnail, item_group,
|
||||
description, web_long_description as website_description
|
||||
from `tabItem`
|
||||
where show_in_website = 1
|
||||
and disabled=0
|
||||
and (end_of_life is null or end_of_life='0000-00-00' or end_of_life > %(today)s)
|
||||
and (variant_of = '' or variant_of is null)
|
||||
and (item_group in ({child_groups})
|
||||
or name in (select parent from `tabWebsite Item Group` where item_group in ({child_groups})))
|
||||
query = """select I.name, I.item_name, I.item_code, I.route, I.image, I.website_image, I.thumbnail, I.item_group,
|
||||
I.description, I.web_long_description as website_description,
|
||||
case when (S.actual_qty - S.reserved_qty) > 0 then 1 else 0 end as in_stock
|
||||
from `tabItem` I
|
||||
left join tabBin S on I.item_code = S.item_code and I.website_warehouse = S.warehouse
|
||||
where I.show_in_website = 1
|
||||
and I.disabled = 0
|
||||
and (I.end_of_life is null or I.end_of_life='0000-00-00' or I.end_of_life > %(today)s)
|
||||
and (I.variant_of = '' or I.variant_of is null)
|
||||
and (I.item_group in ({child_groups})
|
||||
or I.name in (select parent from `tabWebsite Item Group` where item_group in ({child_groups})))
|
||||
""".format(child_groups=child_groups)
|
||||
# search term condition
|
||||
if search:
|
||||
query += """ and (web_long_description like %(search)s
|
||||
or item_name like %(search)s
|
||||
or name like %(search)s)"""
|
||||
query += """ and (I.web_long_description like %(search)s
|
||||
or I.item_name like %(search)s
|
||||
or I.name like %(search)s)"""
|
||||
search = "%" + cstr(search) + "%"
|
||||
|
||||
query += """order by weightage desc, item_name, modified desc limit %s, %s""" % (start, limit)
|
||||
query += """order by I.weightage desc, in_stock desc, I.item_name limit %s, %s""" % (start, limit)
|
||||
|
||||
data = frappe.db.sql(query, {"product_group": product_group,"search": search, "today": nowdate()}, as_dict=1)
|
||||
|
||||
|
@ -3,8 +3,13 @@
|
||||
<a class="product-link" href="{{ route|abs_url }}">
|
||||
<div class="col-sm-4 col-xs-4 product-image-wrapper">
|
||||
<div class="product-image-img">
|
||||
{{ product_image_square(thumbnail or website_image) }}
|
||||
<div class="product-text" itemprop="name">{{ item_name }}</div>
|
||||
{{ product_image_square(thumbnail or website_image) }}
|
||||
<div class="product-text" itemprop="name">{{ item_name }}</div>
|
||||
{% if in_stock %}
|
||||
<div style='color: green'> <i class='fa fa-check'></i> {{ _("In stock") }}</div>
|
||||
{% else %}
|
||||
<div style='color: red'> <i class='fa fa-close'></i> {{ _("Not in stock") }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
@ -17,23 +17,25 @@ def get_product_list(search=None, start=0, limit=12):
|
||||
# limit = 12 because we show 12 items in the grid view
|
||||
|
||||
# base query
|
||||
query = """select name, item_name, item_code, route, website_image, thumbnail, item_group,
|
||||
description, web_long_description as website_description
|
||||
from `tabItem`
|
||||
where (show_in_website = 1 or show_variant_in_website = 1)
|
||||
and disabled=0
|
||||
and (end_of_life is null or end_of_life='0000-00-00' or end_of_life > %(today)s)"""
|
||||
query = """select I.name, I.item_name, I.item_code, I.route, I.website_image, I.thumbnail, I.item_group,
|
||||
I.description, I.web_long_description as website_description,
|
||||
case when (S.actual_qty - S.reserved_qty) > 0 then 1 else 0 end as in_stock
|
||||
from `tabItem` I
|
||||
left join tabBin S on I.item_code = S.item_code and I.website_warehouse = S.warehouse
|
||||
where (I.show_in_website = 1 or I.show_variant_in_website = 1)
|
||||
and I.disabled = 0
|
||||
and (I.end_of_life is null or I.end_of_life='0000-00-00' or I.end_of_life > %(today)s)"""
|
||||
|
||||
# search term condition
|
||||
if search:
|
||||
query += """ and (web_long_description like %(search)s
|
||||
or description like %(search)s
|
||||
or item_name like %(search)s
|
||||
or name like %(search)s)"""
|
||||
query += """ and (I.web_long_description like %(search)s
|
||||
or I.description like %(search)s
|
||||
or I.item_name like %(search)s
|
||||
or I.name like %(search)s)"""
|
||||
search = "%" + cstr(search) + "%"
|
||||
|
||||
# order by
|
||||
query += """ order by weightage desc, idx desc, modified desc limit %s, %s""" % (cint(start), cint(limit))
|
||||
query += """ order by I.weightage desc, in_stock desc, I.item_name limit %s, %s""" % (cint(start), cint(limit))
|
||||
|
||||
data = frappe.db.sql(query, {
|
||||
"search": search,
|
||||
|
@ -16,7 +16,7 @@ def get_qty_in_stock(item_code, item_warehouse_field):
|
||||
warehouse = frappe.db.get_value("Item", template_item_code, item_warehouse_field)
|
||||
|
||||
if warehouse:
|
||||
stock_qty = frappe.db.sql("""select actual_qty from tabBin where
|
||||
stock_qty = frappe.db.sql("""select GREATEST(actual_qty - reserved_qty, 0) from tabBin where
|
||||
item_code=%s and warehouse=%s""", (item_code, warehouse))
|
||||
if stock_qty:
|
||||
in_stock = stock_qty[0][0] > 0 and 1 or 0
|
||||
|
Loading…
x
Reference in New Issue
Block a user