From e13f7622baa4e326abc41ec3aec497bb2f4f0b80 Mon Sep 17 00:00:00 2001 From: marination Date: Thu, 11 Mar 2021 10:56:00 +0530 Subject: [PATCH] feat: Card Actions and Wishlist - Rough UI for card actions - Wishlist doctype - Indicators on card based on stock availability --- .../e_commerce/doctype/wishlist/__init__.py | 0 .../doctype/wishlist/test_wishlist.py | 10 ++ .../e_commerce/doctype/wishlist/wishlist.js | 8 ++ .../e_commerce/doctype/wishlist/wishlist.json | 70 ++++++++++++ .../e_commerce/doctype/wishlist/wishlist.py | 10 ++ .../doctype/wishlist_items/__init__.py | 0 .../wishlist_items/wishlist_items.json | 104 ++++++++++++++++++ .../doctype/wishlist_items/wishlist_items.py | 10 ++ erpnext/e_commerce/product_query.py | 14 ++- erpnext/public/scss/shopping_cart.scss | 50 +++++++++ erpnext/templates/includes/macros.html | 52 ++++++--- erpnext/www/all-products/item_row.html | 2 +- 12 files changed, 314 insertions(+), 16 deletions(-) create mode 100644 erpnext/e_commerce/doctype/wishlist/__init__.py create mode 100644 erpnext/e_commerce/doctype/wishlist/test_wishlist.py create mode 100644 erpnext/e_commerce/doctype/wishlist/wishlist.js create mode 100644 erpnext/e_commerce/doctype/wishlist/wishlist.json create mode 100644 erpnext/e_commerce/doctype/wishlist/wishlist.py create mode 100644 erpnext/e_commerce/doctype/wishlist_items/__init__.py create mode 100644 erpnext/e_commerce/doctype/wishlist_items/wishlist_items.json create mode 100644 erpnext/e_commerce/doctype/wishlist_items/wishlist_items.py diff --git a/erpnext/e_commerce/doctype/wishlist/__init__.py b/erpnext/e_commerce/doctype/wishlist/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/e_commerce/doctype/wishlist/test_wishlist.py b/erpnext/e_commerce/doctype/wishlist/test_wishlist.py new file mode 100644 index 00000000000..6565e71b9e7 --- /dev/null +++ b/erpnext/e_commerce/doctype/wishlist/test_wishlist.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +# import frappe +import unittest + +class TestWishlist(unittest.TestCase): + pass diff --git a/erpnext/e_commerce/doctype/wishlist/wishlist.js b/erpnext/e_commerce/doctype/wishlist/wishlist.js new file mode 100644 index 00000000000..d96e552ecdb --- /dev/null +++ b/erpnext/e_commerce/doctype/wishlist/wishlist.js @@ -0,0 +1,8 @@ +// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Wishlist', { + // refresh: function(frm) { + + // } +}); diff --git a/erpnext/e_commerce/doctype/wishlist/wishlist.json b/erpnext/e_commerce/doctype/wishlist/wishlist.json new file mode 100644 index 00000000000..7e2c67478dc --- /dev/null +++ b/erpnext/e_commerce/doctype/wishlist/wishlist.json @@ -0,0 +1,70 @@ +{ + "actions": [], + "autoname": "field:user", + "creation": "2021-03-10 18:52:28.769126", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "user", + "section_break_2", + "items" + ], + "fields": [ + { + "fieldname": "user", + "fieldtype": "Link", + "in_list_view": 1, + "label": "User", + "options": "User", + "reqd": 1, + "unique": 1 + }, + { + "fieldname": "section_break_2", + "fieldtype": "Section Break" + }, + { + "fieldname": "items", + "fieldtype": "Table", + "label": "Items", + "options": "Wishlist Items" + } + ], + "index_web_pages_for_search": 1, + "links": [], + "modified": "2021-03-10 19:05:52.373601", + "modified_by": "Administrator", + "module": "E-commerce", + "name": "Wishlist", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Stock Manager", + "share": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/e_commerce/doctype/wishlist/wishlist.py b/erpnext/e_commerce/doctype/wishlist/wishlist.py new file mode 100644 index 00000000000..94e2754f88b --- /dev/null +++ b/erpnext/e_commerce/doctype/wishlist/wishlist.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +# import frappe +from frappe.model.document import Document + +class Wishlist(Document): + pass diff --git a/erpnext/e_commerce/doctype/wishlist_items/__init__.py b/erpnext/e_commerce/doctype/wishlist_items/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/e_commerce/doctype/wishlist_items/wishlist_items.json b/erpnext/e_commerce/doctype/wishlist_items/wishlist_items.json new file mode 100644 index 00000000000..29f40660a45 --- /dev/null +++ b/erpnext/e_commerce/doctype/wishlist_items/wishlist_items.json @@ -0,0 +1,104 @@ +{ + "actions": [], + "creation": "2021-03-10 19:03:00.662714", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "item_code", + "website_item", + "column_break_3", + "item_name", + "item_details_section", + "description", + "column_break_7", + "image", + "image_view", + "warehouse_section", + "warehouse" + ], + "fields": [ + { + "fieldname": "item_code", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Item Code", + "options": "Item", + "reqd": 1 + }, + { + "fieldname": "website_item", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Website Item", + "options": "Website Item" + }, + { + "fieldname": "column_break_3", + "fieldtype": "Column Break" + }, + { + "fetch_from": "item_code.item_name", + "fetch_if_empty": 1, + "fieldname": "item_name", + "fieldtype": "Data", + "label": "Item Name" + }, + { + "collapsible": 1, + "fieldname": "item_details_section", + "fieldtype": "Section Break", + "label": "Item Details" + }, + { + "fetch_from": "item_code.description", + "fieldname": "description", + "fieldtype": "Text Editor", + "label": "Description" + }, + { + "fieldname": "column_break_7", + "fieldtype": "Column Break" + }, + { + "fetch_from": "item_code.image", + "fieldname": "image", + "fieldtype": "Attach", + "hidden": 1, + "label": "Image" + }, + { + "fetch_from": "item_code.image", + "fieldname": "image_view", + "fieldtype": "Image", + "hidden": 1, + "label": "Image View", + "options": "image", + "print_hide": 1 + }, + { + "fieldname": "warehouse_section", + "fieldtype": "Section Break", + "label": "Warehouse" + }, + { + "fieldname": "warehouse", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Warehouse", + "options": "Warehouse" + } + ], + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2021-03-10 19:13:41.310816", + "modified_by": "Administrator", + "module": "E-commerce", + "name": "Wishlist Items", + "owner": "Administrator", + "permissions": [], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/e_commerce/doctype/wishlist_items/wishlist_items.py b/erpnext/e_commerce/doctype/wishlist_items/wishlist_items.py new file mode 100644 index 00000000000..25ce17d655b --- /dev/null +++ b/erpnext/e_commerce/doctype/wishlist_items/wishlist_items.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +# import frappe +from frappe.model.document import Document + +class WishlistItems(Document): + pass diff --git a/erpnext/e_commerce/product_query.py b/erpnext/e_commerce/product_query.py index 36a17d7260c..10b393d8393 100644 --- a/erpnext/e_commerce/product_query.py +++ b/erpnext/e_commerce/product_query.py @@ -20,7 +20,7 @@ class ProductQuery: self.page_length = self.settings.products_per_page or 20 self.fields = ['wi.name', 'wi.item_name', 'wi.item_code', 'wi.website_image', 'wi.variant_of', 'wi.has_variants', 'wi.item_group', 'wi.image', 'wi.web_long_description', 'wi.description', - 'wi.route'] + 'wi.route', 'wi.website_warehouse'] self.conditions = "" self.or_conditions = "" self.substitutions = [] @@ -51,12 +51,22 @@ class ProductQuery: result = self.query_items(self.conditions, self.or_conditions, self.substitutions, start=start) - # add price info in results + # add price and availability info in results for item in result: product_info = get_product_info_for_website(item.item_code, skip_quotation_creation=True).get('product_info') if product_info: item.formatted_price = product_info['price'].get('formatted_price') if product_info['price'] else None + if self.settings.show_stock_availability and item.get("website_warehouse"): + stock_qty = frappe.utils.flt( + frappe.db.get_value("Bin", + { + "item_code": item.item_code, + "warehouse": item.get("website_warehouse") + }, + "actual_qty") + ) + item.in_stock = "green" if stock_qty else "red" return result def query_items(self, conditions, or_conditions, substitutions, start=0): diff --git a/erpnext/public/scss/shopping_cart.scss b/erpnext/public/scss/shopping_cart.scss index 977841a2d5c..f5c71d71d66 100644 --- a/erpnext/public/scss/shopping_cart.scss +++ b/erpnext/public/scss/shopping_cart.scss @@ -518,3 +518,53 @@ body.product-page { } } +.card-indicator { + margin-left: 6px; +} + +.like-action { + text-align: center; + margin-top: -2px; + margin-left: 12px; +} + +.wish-icon { + cursor: pointer; + stroke: #F47A7A !important; + + &:hover { + fill: #F47A7A; + } +} + +.wished { + .wish-icon { + stroke: none; + fill: #F47A7A !important; + } +} + +.list-row-checkbox { + &:before { + display: none; + } + + &:checked:before { + display: block; + z-index: 1; + } +} + +.btn-add-to-cart-list { + color: var(--blue-500); + background-color: white; + box-shadow: none; + border: 1px solid var(--blue-500); + margin: var(--margin-sm) 0; + flex: none; + + &:hover { + background-color: var(--blue-500); + color: white; + } +} \ No newline at end of file diff --git a/erpnext/templates/includes/macros.html b/erpnext/templates/includes/macros.html index c44bfb53848..b07934f1ae6 100644 --- a/erpnext/templates/includes/macros.html +++ b/erpnext/templates/includes/macros.html @@ -59,7 +59,7 @@ {% endmacro %} -{%- macro item_card(title, image, url, description, rate, category, is_featured=False, is_full_width=False, align="Left") -%} +{%- macro item_card(title, image, url, description, rate, category, in_stock=None, is_featured=False, is_full_width=False, align="Left") -%} {%- set align_items_class = resolve_class({ 'align-items-end': align == 'Right', 'align-items-center': align == 'Center', @@ -89,35 +89,61 @@
{% if image %} -
- {{ title }} -
+
+ + {{ title }} + +
{% else %} -
- {{ frappe.utils.get_abbr(title) }} -
+ +
+ {{ frappe.utils.get_abbr(title) }} +
+
{% endif %} - {{ item_card_body(title, description, url, rate, category, is_featured, align) }} + {{ item_card_body(title, description, url, rate, category, is_featured, align, in_stock) }}
{% endif %} {%- endmacro -%} -{%- macro item_card_body(title, description, url, rate, category, is_featured, align) -%} +{%- macro item_card_body(title, description, url, rate, category, is_featured, align, in_stock=None) -%} {%- set align_class = resolve_class({ 'text-right': align == 'Right', 'text-center': align == 'Center' and not is_featured, 'text-left': align == 'Left' or is_featured, }) -%} -
-
{{ title or '' }}
+
+ +
+ +
{{ title or '' }}
+
+ {% if in_stock %} + + {% endif %} + + +
{% if is_featured %}
{{ rate or '' }}
{{ description or '' }}
{% else %}
{{ category or '' }}
-
{{ rate or '' }}
+
+ {% if rate %} +
{{ rate or '' }}
+ {% endif %} +
+ {{ _('Add to Cart') }} +
+
{% endif %}
- {%- endmacro -%} \ No newline at end of file diff --git a/erpnext/www/all-products/item_row.html b/erpnext/www/all-products/item_row.html index 20fc9a4878c..4f2071f2680 100644 --- a/erpnext/www/all-products/item_row.html +++ b/erpnext/www/all-products/item_row.html @@ -2,6 +2,6 @@ {{ item_card( item.item_name or item.name, item.website_image or item.image, item.route, item.website_description or item.description, - item.formatted_price, item.item_group + item.formatted_price, item.item_group, in_stock=item.in_stock ) }}