Selaa lähdekoodia

primer commit

edgar 7 vuotta sitten
commit
1e6ea2dd55
71 muutettua tiedostoa jossa 799 lisäystä ja 0 poistoa
  1. 2 0
      __init__.py
  2. 24 0
      __openerp__.py
  3. 1 0
      controllers/__init__.py
  4. 121 0
      controllers/main.py
  5. BIN
      images/websale1.png
  6. 2 0
      models/__init__.py
  7. 33 0
      models/sale_order.py
  8. BIN
      static/description/analytics.png
  9. BIN
      static/description/blog.png
  10. BIN
      static/description/checkout.png
  11. BIN
      static/description/event_top.png
  12. BIN
      static/description/icon.png
  13. 88 0
      static/description/index.html
  14. BIN
      static/description/openerp_translation_tool.png
  15. BIN
      static/description/reseller.png
  16. BIN
      static/description/ribbon.png
  17. BIN
      static/description/suggested.png
  18. BIN
      static/description/warehouse_illu_01.png
  19. BIN
      static/description/web_pos10.png
  20. BIN
      static/description/web_pos2.png
  21. BIN
      static/description/web_pos3.png
  22. BIN
      static/description/web_pos4.png
  23. BIN
      static/description/web_pos5.png
  24. BIN
      static/description/web_pos6.png
  25. BIN
      static/description/web_pos7.png
  26. BIN
      static/description/web_pos8.png
  27. BIN
      static/description/web_pos9.png
  28. BIN
      static/description/websale1.png
  29. BIN
      static/description/website_edit.png
  30. BIN
      static/description/website_home.png
  31. BIN
      static/description/website_sale_home.png
  32. BIN
      static/description/website_sale_product.png
  33. BIN
      static/description/website_seo.png
  34. 16 0
      static/src/css/dialog_box.css
  35. BIN
      static/src/css/images/close.gif
  36. BIN
      static/src/css/images/dialog_close.gif
  37. BIN
      static/src/css/images/error_bg.jpg
  38. BIN
      static/src/css/images/error_header.gif
  39. BIN
      static/src/css/images/prompt_bg.jpg
  40. BIN
      static/src/css/images/prompt_header.gif
  41. BIN
      static/src/css/images/success_bg.jpg
  42. BIN
      static/src/css/images/success_header.gif
  43. BIN
      static/src/css/images/warning_bg.jpg
  44. BIN
      static/src/css/images/warning_header.gif
  45. 43 0
      static/src/css/website_sale_ext.css
  46. BIN
      static/src/img/AZERTY.jpg
  47. BIN
      static/src/img/accessory1.jpg
  48. BIN
      static/src/img/accessory1_features.png
  49. BIN
      static/src/img/anywhere_anything.png
  50. BIN
      static/src/img/apps.png
  51. BIN
      static/src/img/bluetooth.jpg
  52. BIN
      static/src/img/buds_closeup.png
  53. BIN
      static/src/img/design.png
  54. BIN
      static/src/img/icon.png
  55. BIN
      static/src/img/imac1.png
  56. BIN
      static/src/img/imac2.png
  57. BIN
      static/src/img/ipad_experience.png
  58. BIN
      static/src/img/ipad_why.png
  59. BIN
      static/src/img/keyboard.png
  60. BIN
      static/src/img/mighty.png
  61. BIN
      static/src/img/more_features.png
  62. BIN
      static/src/img/overview_design_silver.png
  63. BIN
      static/src/img/overview_hero.png
  64. BIN
      static/src/img/play_where_you_play.jpg
  65. BIN
      static/src/img/promo_headphones.png
  66. BIN
      static/src/img/purple.png
  67. BIN
      static/src/img/redcross.png
  68. BIN
      static/src/img/wireless.png
  69. 127 0
      static/src/js/dialog_box.js
  70. 263 0
      static/src/js/website_sale_ext.js
  71. 79 0
      views/templates.xml

+ 2 - 0
__init__.py

@@ -0,0 +1,2 @@
+import controllers
+import models

+ 24 - 0
__openerp__.py

@@ -0,0 +1,24 @@
+{
+    'name': 'eCommerce Extension to Display Stock Info',
+    'category': 'Website',
+    'summary': 'Sell Your Products Online with Product Stock Info',
+    'website': 'http://www.credativ.in',
+    'version': '1.0',
+    'description': """
+OpenERP E-Commerce
+==================
+ Add features like, showing Stock Information on Products and validates not to allow more Quantity while Adding to Cart.
+        """,
+    'author': 'Murali Krishna Reddy',
+    'depends': ['website_sale'],
+    'sequence':0,
+    'images':['images/websale1.png'],
+    'data': [
+        'views/templates.xml',
+    ],
+    'demo': [
+    ],
+    #'qweb': ['static/src/xml/*.xml'],
+    'installable': True,
+    'application': True,
+}

+ 1 - 0
controllers/__init__.py

@@ -0,0 +1 @@
+import main

+ 121 - 0
controllers/main.py

@@ -0,0 +1,121 @@
+# -*- coding: utf-8 -*-
+import werkzeug
+
+from openerp import SUPERUSER_ID
+from openerp import http
+from openerp.http import request
+from openerp.tools.translate import _
+from openerp.addons.website.models.website import slug
+
+PPG = 20 # Products Per Page
+PPR = 4  # Products Per Row
+
+class web_site_sale_extend(http.Controller):
+
+    def get_pricelist(self):
+        return get_pricelist()
+
+    def get_attribute_value_ids_ext(self, product):
+        sale_order_id = request.session.get('sale_last_order_id')
+        cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
+        currency_obj = pool['res.currency']
+        attribute_value_ids = []
+        if request.website.pricelist_id.id != context['pricelist']:
+            website_currency_id = request.website.currency_id.id
+            currency_id = self.get_pricelist().currency_id.id
+            for p in product.product_variant_ids:
+                price = currency_obj.compute(cr, uid, website_currency_id, currency_id, p.lst_price)
+                attribute_value_ids.append([p.id, map(int, p.attribute_value_ids), p.price, price, p.qty_available])
+        else:
+            attribute_value_ids = [[p.id, map(int, p.attribute_value_ids), p.price, p.lst_price, p.qty_available] for p in product.product_variant_ids]
+        
+        return attribute_value_ids
+        
+        
+    @http.route(['/shop/product/<model("product.template"):product>'], type='http', auth="public", website=True)
+    def product(self, product, category='', search='', **kwargs):
+        cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
+        category_obj = pool['product.public.category']
+        template_obj = pool['product.template']
+
+        context.update(active_id=product.id)
+
+        if category:
+            category = category_obj.browse(cr, uid, int(category), context=context)
+
+        attrib_list = request.httprequest.args.getlist('attrib')
+        attrib_values = [map(int,v.split("-")) for v in attrib_list if v]
+        attrib_set = set([v[1] for v in attrib_values])
+
+        keep = QueryURL('/shop', category=category and category.id, search=search, attrib=attrib_list)
+
+        category_ids = category_obj.search(cr, uid, [], context=context)
+        category_list = category_obj.name_get(cr, uid, category_ids, context=context)
+        category_list = sorted(category_list, key=lambda category: category[1])
+
+        pricelist = self.get_pricelist()
+
+        from_currency = pool.get('product.price.type')._get_field_currency(cr, uid, 'list_price', context)
+        to_currency = pricelist.currency_id
+        compute_currency = lambda price: pool['res.currency']._compute(cr, uid, from_currency, to_currency, price, context=context)
+
+        if not context.get('pricelist'):
+            context['pricelist'] = int(self.get_pricelist())
+            product = template_obj.browse(cr, uid, int(product), context=context)
+
+        values = {
+            'search': search,
+            'category': category,
+            'pricelist': pricelist,
+            'attrib_values': attrib_values,
+            'compute_currency': compute_currency,
+            'attrib_set': attrib_set,
+            'keep': keep,
+            'category_list': category_list,
+            'main_object': product,
+            'product': product,
+            'get_attribute_value_ids': self.get_attribute_value_ids_ext
+        }
+        return request.website.render("website_sale.product", values)
+    
+        
+    @http.route(['/shop/cart/get_added_qty_product_json'], type='json', auth="public", methods=['POST'], website=True)
+    def cart_stock_for_product_json(self, product_id):
+        cr, uid, context = request.cr, request.uid, request.context
+        qty = request.website.added_to_cart_product_qty_variant(product_id)
+        return qty;
+
+class QueryURL(object):
+    def __init__(self, path='', **args):
+        self.path = path
+        self.args = args
+
+    def __call__(self, path=None, **kw):
+        if not path:
+            path = self.path
+        for k,v in self.args.items():
+            kw.setdefault(k,v)
+        l = []
+        for k,v in kw.items():
+            if v:
+                if isinstance(v, list) or isinstance(v, set):
+                    l.append(werkzeug.url_encode([(k,i) for i in v]))
+                else:
+                    l.append(werkzeug.url_encode([(k,v)]))
+        if l:
+            path += '?' + '&'.join(l)
+        return path
+    
+def get_pricelist():
+    cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
+    sale_order = context.get('sale_order')
+    if sale_order:
+        pricelist = sale_order.pricelist_id
+    else:
+        partner = pool['res.users'].browse(cr, SUPERUSER_ID, uid, context=context).partner_id
+        pricelist = partner.property_product_pricelist
+    return pricelist
+
+
+
+# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:

BIN
images/websale1.png


+ 2 - 0
models/__init__.py

@@ -0,0 +1,2 @@
+import sale_order
+

+ 33 - 0
models/sale_order.py

@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+import random
+
+from openerp import SUPERUSER_ID
+from openerp.osv import osv, orm, fields
+from openerp.addons.web.http import request
+
+
+class sale_order(osv.Model):
+    _inherit = "sale.order"
+        
+    def _cart_update(self, cr, uid, ids, product_id=None, line_id=None, add_qty=0, set_qty=0, context=None, **kwargs):
+        ret = super(sale_order,self)._cart_update(cr, uid, ids, product_id=product_id, line_id=line_id, add_qty=add_qty, set_qty=set_qty, context=context, **kwargs)
+        return ret
+        
+        
+class website(orm.Model):
+    _inherit = 'website'
+
+    def added_to_cart_product_qty(self, cr, uid, ids, product_id=None, context=None):
+        ret = {}
+        quantity = 0.00
+        sale_order_obj = self.pool['sale.order']
+        sale_order_id = request.session.get('sale_order_id')
+        if sale_order_id:
+            for line in sale_order_obj.browse(cr, uid, sale_order_id, context=context).website_order_line:
+                if product_id and product_id == line.product_id.product_tmpl_id.id:
+               
+                    quantity+=line.product_uom_qty
+                    ret[line.product_id.id] = line.product_uom_qty
+        return ret
+               
+

BIN
static/description/analytics.png


BIN
static/description/blog.png


BIN
static/description/checkout.png


BIN
static/description/event_top.png


BIN
static/description/icon.png


+ 88 - 0
static/description/index.html

@@ -0,0 +1,88 @@
+<section class="oe_container">
+    <div class="oe_row oe_spaced">
+        <div class="oe_span12">
+            <h2 class="oe_slogan">eCommerce Extension to Display Stock Info</h2>
+            <h3 class="oe_slogan">Also Validates while adding products to Cart.</h3>
+        </div>
+        <div >
+            <div class="oe_demo oe_picture oe_screenshot">
+            <img class="oe_picture oe_screenshot" src="web_pos2.png"/>
+            </div>
+        </div>
+        <div class="oe_span6">
+            <p class='oe_mt32'>
+                When you Check "Product STock Label" under Customize, system shall display Quantity Available with UOM if configured at the Top of the Product Image.
+		    </p><p>
+				If Available Stock is Zero, then system displays as SOLD OUT.
+            </p>            
+        </div>
+    </div>
+</section>
+
+<section class="oe_container oe_dark">
+    <div class="oe_row">
+        <h2 class="oe_slogan">Display Stock based on Variant</h2>
+        <h3 class="oe_slogan"></h3>
+        <div >
+            <div class="oe_demo oe_picture oe_screenshot">
+            <img class="oe_picture oe_screenshot" src="web_pos3.png"/>
+            </div>
+        </div>
+        <div class="oe_span6">
+            <p class='oe_mt32'>
+                When user checks the "Product Stock Available" under Customize in Add a Product to Stock Page, system displays the product Stock Information.
+            </p><p>
+                Based on selected Variant Stock Information shall be changed. If stock is not Available then, SOLD OUT shall be displayed and Add to Cart button shall be Disabled.
+            </p>
+        </div>
+        
+    </div>
+</section>
+
+<section class="oe_container">
+    <div class="oe_row">
+        <h2 class="oe_slogan">Validate while adding to Cart</h2>
+        <h3 class="oe_slogan"></h3>
+        <div >
+            <img class="oe_picture oe_screenshot" src="web_pos6.png">
+        </div>
+        <div class="oe_span6">
+           <p class='oe_mt32'>
+                Error Warning shall be displayed and Add to Cart button shall be Disabled, while Adding to Cart more than Available.
+            </p><p>
+                and While Already some Products are Added and Trying to Add more than Available.
+		    </p><p>
+                In Shipping Cart Page Error Warning shall be displayed and Process Checkout button shall be Disabled, while adding more than Available.
+           </p>
+        </div>
+   </div>
+</section>
+
+<section class="oe_container oe_dark">
+    <div class="oe_row">
+        <h2 class="oe_slogan">Display Stock Based on Selected Variant</h2>  </div>      
+        <div>
+            <img class="oe_picture oe_screenshot" src="web_pos4.png">
+        </div>
+   	<div>
+            <img class="oe_picture oe_screenshot" src="web_pos5.png">
+        </div>
+</section>
+
+<section class="oe_container oe_dark">
+    <div class="oe_row">
+        <h2 class="oe_slogan">Various Error Messages</h2>  </div>      
+        <div>
+            <img class="oe_picture oe_screenshot" src="web_pos7.png">
+        </div>
+   	<div>
+            <img class="oe_picture oe_screenshot" src="web_pos8.png">
+        </div>
+        <div>
+            <img class="oe_picture oe_screenshot" src="web_pos9.png">
+        </div>
+        <div>
+            <img class="oe_picture oe_screenshot" src="web_pos10.png">
+        </div>
+</section>
+

BIN
static/description/openerp_translation_tool.png


BIN
static/description/reseller.png


BIN
static/description/ribbon.png


BIN
static/description/suggested.png


BIN
static/description/warehouse_illu_01.png


BIN
static/description/web_pos10.png


BIN
static/description/web_pos2.png


BIN
static/description/web_pos3.png


BIN
static/description/web_pos4.png


BIN
static/description/web_pos5.png


BIN
static/description/web_pos6.png


BIN
static/description/web_pos7.png


BIN
static/description/web_pos8.png


BIN
static/description/web_pos9.png


BIN
static/description/websale1.png


BIN
static/description/website_edit.png


BIN
static/description/website_home.png


BIN
static/description/website_sale_home.png


BIN
static/description/website_sale_product.png


BIN
static/description/website_seo.png


+ 16 - 0
static/src/css/dialog_box.css

@@ -0,0 +1,16 @@
+body {margin:0; font-family:Verdana, Arial, Helvetica; font-size:14px}
+#content {padding:20px}
+#dialog {position:absolute; width:425px; padding:10px; z-index:200; background:#fff}
+#dialog-header {display:block; position:relative; width:405px; padding:3px 6px 7px; height:26px; font-size:14px; font-weight:bold}
+#dialog-title {float:left}
+#dialog-close {float:right; cursor:pointer; margin:3px 3px 0 0; height:20px; width:20px; background:url(images/close.gif) no-repeat}
+#dialog-content {display:block; height:160px; padding:6px; color:#0a0a0a; font-size:16px}
+#dialog-mask {position:absolute; top:0; left:0; min-height:100%; width:100%; background:#FFF; opacity:.75; filter:alpha(opacity=75); z-index:100}
+.error {background:#fff url(images/error_bg.jpg) bottom right no-repeat; border:1px solid #924949; border-top:none}
+.errorheader {background:url(images/error_header.gif) repeat-x; color:#6f2c2c; border:1px solid #924949; border-bottom:none}
+.warning {background:#fff url(images/warning_bg.jpg) bottom right no-repeat; border:1px solid #c5a524; border-top:none}
+.warningheader {background:url(images/warning_header.gif) repeat-x; color:#957c17; border:1px solid #c5a524; border-bottom:none}
+.success {background:#fff url(images/success_bg.jpg) bottom right no-repeat; border:1px solid #60a174; border-top:none}
+.successheader {background:url(images/success_header.gif) repeat-x; color:#3c7f51; border:1px solid #60a174; border-bottom:none}
+.prompt {background:#fff url(images/prompt_bg.jpg) bottom right no-repeat; border:1px solid #4f6d81; border-top:none}
+.promptheader {background:url(images/prompt_header.gif) repeat-x; color:#355468; border:1px solid #4f6d81; border-bottom:none}

BIN
static/src/css/images/close.gif


BIN
static/src/css/images/dialog_close.gif


BIN
static/src/css/images/error_bg.jpg


BIN
static/src/css/images/error_header.gif


BIN
static/src/css/images/prompt_bg.jpg


BIN
static/src/css/images/prompt_header.gif


BIN
static/src/css/images/success_bg.jpg


BIN
static/src/css/images/success_header.gif


BIN
static/src/css/images/warning_bg.jpg


BIN
static/src/css/images/warning_header.gif


+ 43 - 0
static/src/css/website_sale_ext.css

@@ -0,0 +1,43 @@
+@charset "utf-8";
+/* ---- Default Styles ---- */
+/*
+.tooltip {
+    position: relative;
+    display: inline-block;
+    border-bottom: 1px dotted black;
+}
+*/
+.tooltiptext {
+    visibility: hidden;
+    width: 120px;
+    background-color: #555;
+    color: #fff;
+    text-align: center;
+    border-radius: 6px;
+    padding: 5px 0;
+    position: absolute;
+    z-index: 1;
+    bottom: 125%;
+    left: 50%;
+    margin-left: -60px;
+    opacity: 0;
+    transition: opacity 1s;
+}
+
+.tooltiptext::after {
+    content: "";
+    position: absolute;
+    top: 100%;
+    left: 50%;
+    margin-left: -5px;
+    border-width: 5px;
+    border-style: solid;
+    border-color: #555 transparent transparent transparent;
+}
+
+.tooltipt:hover .tooltiptext {
+    visibility: visible;
+    opacity: 1;
+}
+a.disabled { color:gray; }
+

BIN
static/src/img/AZERTY.jpg


BIN
static/src/img/accessory1.jpg


BIN
static/src/img/accessory1_features.png


BIN
static/src/img/anywhere_anything.png


BIN
static/src/img/apps.png


BIN
static/src/img/bluetooth.jpg


BIN
static/src/img/buds_closeup.png


BIN
static/src/img/design.png


BIN
static/src/img/icon.png


BIN
static/src/img/imac1.png


BIN
static/src/img/imac2.png


BIN
static/src/img/ipad_experience.png


BIN
static/src/img/ipad_why.png


BIN
static/src/img/keyboard.png


BIN
static/src/img/mighty.png


BIN
static/src/img/more_features.png


BIN
static/src/img/overview_design_silver.png


BIN
static/src/img/overview_hero.png


BIN
static/src/img/play_where_you_play.jpg


BIN
static/src/img/promo_headphones.png


BIN
static/src/img/purple.png


BIN
static/src/img/redcross.png


BIN
static/src/img/wireless.png


+ 127 - 0
static/src/js/dialog_box.js

@@ -0,0 +1,127 @@
+// global variables //
+var TIMER = 5;
+var SPEED = 10;
+var WRAPPER = 'content';
+
+// calculate the current window width //
+function pageWidth() {
+  return window.innerWidth != null ? window.innerWidth : document.documentElement && document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body != null ? document.body.clientWidth : null;
+}
+
+// calculate the current window height //
+function pageHeight() {
+  return window.innerHeight != null? window.innerHeight : document.documentElement && document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body != null? document.body.clientHeight : null;
+}
+
+// calculate the current window vertical offset //
+function topPosition() {
+  return typeof window.pageYOffset != 'undefined' ? window.pageYOffset : document.documentElement && document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ? document.body.scrollTop : 0;
+}
+
+// calculate the position starting at the left of the window //
+function leftPosition() {
+  return typeof window.pageXOffset != 'undefined' ? window.pageXOffset : document.documentElement && document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ? document.body.scrollLeft : 0;
+}
+
+// build/show the dialog box, populate the data and call the fadeDialog function //
+function showDialog(title,message,type,autohide) {
+  if(!type) {
+    type = 'error';
+  }
+  var dialog;
+  var dialogheader;
+  var dialogclose;
+  var dialogtitle;
+  var dialogcontent;
+  var dialogmask;
+  if(!document.getElementById('dialog')) {
+    dialog = document.createElement('div');
+    dialog.id = 'dialog';
+    dialogheader = document.createElement('div');
+    dialogheader.id = 'dialog-header';
+    dialogtitle = document.createElement('div');
+    dialogtitle.id = 'dialog-title';
+    dialogclose = document.createElement('div');
+    dialogclose.id = 'dialog-close'
+    dialogcontent = document.createElement('div');
+    dialogcontent.id = 'dialog-content';
+    dialogmask = document.createElement('div');
+    dialogmask.id = 'dialog-mask';
+    document.body.appendChild(dialogmask);
+    document.body.appendChild(dialog);
+    dialog.appendChild(dialogheader);
+    dialogheader.appendChild(dialogtitle);
+    dialogheader.appendChild(dialogclose);
+    dialog.appendChild(dialogcontent);;
+    dialogclose.setAttribute('onclick','hideDialog()');
+    dialogclose.onclick = hideDialog;
+  } else {
+    dialog = document.getElementById('dialog');
+    dialogheader = document.getElementById('dialog-header');
+    dialogtitle = document.getElementById('dialog-title');
+    dialogclose = document.getElementById('dialog-close');
+    dialogcontent = document.getElementById('dialog-content');
+    dialogmask = document.getElementById('dialog-mask');
+    dialogmask.style.visibility = "visible";
+    dialog.style.visibility = "visible";
+  }
+  dialog.style.opacity = .00;
+  dialog.style.filter = 'alpha(opacity=0)';
+  dialog.alpha = 0;
+  var width = pageWidth();
+  var height = pageHeight();
+  var left = leftPosition();
+  var top = topPosition();
+  var dialogwidth = dialog.offsetWidth;
+  var dialogheight = dialog.offsetHeight;
+  var topposition = top + (height / 3) - (dialogheight / 2);
+  var leftposition = left + (width / 2) - (dialogwidth / 2);
+  dialog.style.top = topposition + "px";
+  dialog.style.left = leftposition + "px";
+  dialogheader.className = type + "header";
+  dialogtitle.innerHTML = title;
+  dialogcontent.className = type;
+  dialogcontent.innerHTML = message;
+  var content = document.getElementById(WRAPPER);
+  dialogmask.style.height = '69px';//content.offsetHeight + 'px';
+  dialog.timer = setInterval("fadeDialog(1)", TIMER);
+  if(autohide) {
+    dialogclose.style.visibility = "hidden";
+    dialogclose.style.visibility = "visible";
+    window.setTimeout("hideDialog()", (autohide * 1000));
+  } else {
+    dialogclose.style.visibility = "visible";
+  }
+}
+
+// hide the dialog box //
+function hideDialog() {
+  var dialog = document.getElementById('dialog');
+  clearInterval(dialog.timer);
+  dialog.timer = setInterval("fadeDialog(0)", TIMER);
+}
+
+// fade-in the dialog box //
+function fadeDialog(flag) {
+  if(flag == null) {
+    flag = 1;
+  }
+  var dialog = document.getElementById('dialog');
+  var value;
+  if(flag == 1) {
+    value = dialog.alpha + SPEED;
+  } else {
+    value = dialog.alpha - SPEED;
+  }
+  dialog.alpha = value;
+  dialog.style.opacity = (value / 100);
+  dialog.style.filter = 'alpha(opacity=' + value + ')';
+  if(value >= 99) {
+    clearInterval(dialog.timer);
+    dialog.timer = null;
+  } else if(value <= 1) {
+    dialog.style.visibility = "hidden";
+    document.getElementById('dialog-mask').style.visibility = "hidden";
+    clearInterval(dialog.timer);
+  }
+}

+ 263 - 0
static/src/js/website_sale_ext.js

@@ -0,0 +1,263 @@
+$(document).ready(function () {
+function malformedJSON2Array (tar) {   
+    var dict = {}
+    tar = tar.replace(/^\{|\}$/g,'').split(',');
+    for(var i=0,cur,pair;cur=tar[i];i++){
+        var pair = cur.split(':');
+        dict[pair[0].trim()] = pair[1].trim();
+    }
+    return dict;
+}
+
+$('.oe_website_sale').each(function () {
+    var oe_website_sale = this;
+    
+    $(oe_website_sale).find('#cart_products').find('tbody tr').each(function () {
+        var prod = $(this).find('strong').text();
+        stock = $(this).find('#stock_available_line').text();
+        value = parseInt($(this).find('input.js_quantity').val(), 10);
+        if(value>parseInt(stock))
+    {        
+        showDialog('Error','You can\'t enter more than Available Quanity ('+parseInt(stock)+' for product : '+prod+') .','error',5);
+        $( "div.oe_cart a.btn-primary" ).addClass("disabled");        
+        return false;
+    }
+    else
+    {
+        $( "div.oe_cart a.btn-primary" ).removeClass("disabled");
+    }
+        });
+    
+    $( "input[name='add_qty']" ).addClass('tooltipt');
+    var stock = $( "span[name='stock_available']" ).text();
+    
+    if(stock!='' && stock !=NaN && stock!=undefined)
+    {
+        if(stock<=0)
+        {
+             $( ".fa-plus" ).addClass('hidden');
+             $( ".fa-minus" ).addClass("hidden");
+             $( "input[name='add_qty']" ).prop("readonly",true);
+        }
+        else{
+            $( "i.fa-plus" ).removeClass("hidden");
+            $( "i.fa-minus" ).removeClass("hidden");
+            $( "input[name='add_qty']" ).prop("readonly",false);
+        }
+    }
+    
+ $(oe_website_sale).on("change", "div.css_quantity input.js_quantity", function () {
+        var $input = $(this);
+        var value = parseInt($input.val(), 10);
+        var stock = $( "span[name='stock_available']" ).text();
+        var variant_qty = $( "#qty_avail_variant" ).attr('value');
+	  if(variant_qty==undefined){    
+	    if(value>stock)
+	    {        
+		showDialog('Error','You can\'t enter more than Available Quanity ('+parseInt(stock)+').','error',4);
+		$( "#add_to_cart" ).addClass("disabled");
+	    }
+	    else
+	    {
+		$( "#add_to_cart" ).removeClass("disabled");
+	    }
+	  }
+	    
+	    if(variant_qty!=undefined){
+		if(variant_qty>0){
+		    if(value>variant_qty)
+		    {     
+			showDialog('Error','You can\'t enter more than Available Quanity ('+parseInt(variant_qty)+').','error',4);
+			$( "#add_to_cart" ).addClass("disabled");
+		    }
+		    else
+		    {
+			$( "#add_to_cart" ).removeClass("disabled");
+		    }
+		  }
+		  else if(variant_qty<=0){
+		    $( "#add_to_cart" ).addClass("disabled");    
+		  }
+	    }
+    
+  });  
+  
+$(oe_website_sale).on("change", "table#cart_products input.js_quantity", function () {
+        var $input = $(this);
+        var value = parseInt($input.val(), 10);
+        var line_id = parseInt($input.data('line-id'),10);
+        var product_id = parseInt($input.data('product-id'),10);
+        var stock = $( "span[name='stock_available_line'][data-line-id="+line_id+"]" ).text();
+        if(value>stock)
+    {        
+        showDialog('Error','You can\'t enter more than Available Quanity ('+parseInt(stock)+').','error',4);
+        $( "div.oe_cart a.btn-primary" ).addClass("disabled");
+        return false;
+    }
+    else
+    {
+        $( "div.oe_cart a.btn-primary" ).removeClass("disabled");
+    }
+    $input.closest('#cart_products').find('tbody tr').each(function () {
+        var prod = $(this).find('strong').text();
+        stock = $(this).find('#stock_available_line').text();
+        value = parseInt($(this).find('input.js_quantity').val(), 10);
+        if(value>parseInt(stock))
+    {        
+        showDialog('Error','You can\'t enter more than Available Quanity ('+parseInt(stock)+' for product : '+prod+') .','error',5);
+        $( "div.oe_cart a.btn-primary" ).addClass("disabled");
+        return false;
+    }
+    else
+    {
+        $( "div.oe_cart a.btn-primary" ).removeClass("disabled");
+    }
+        });
+  });
+  $('div.oe_cart a.btn-primary', oe_website_sale).off('click').on('click', function () {
+
+  $(oe_website_sale).find('#cart_products').find('tbody tr').each(function () {
+        var prod = $(this).find('strong').text();
+        stock = $(this).find('#stock_available_line').text();
+        value = parseInt($(this).find('input.js_quantity').val(), 10);
+        if(value>parseInt(stock))
+    {        
+        showDialog('Error','You can\'t enter more than Available Quanity ('+parseInt(stock)+' for product : '+prod+') .','error',5);
+        $( "div.oe_cart a.btn-primary" ).addClass("disabled");        
+        return false;
+    }
+    else
+    {
+        $( "div.oe_cart a.btn-primary" ).removeClass("disabled");
+    }
+        });
+      
+  });
+  
+    $(oe_website_sale).on('change', 'input.js_variant_change, select.js_variant_change', function (ev) {
+        var $ul = $(this).parents('ul.js_add_cart_variants:first');
+        var $parent = $ul.closest('.js_product');
+        var $product_id = $parent.find('input.product_id').first();
+        var $price = $parent.find(".oe_price:first .oe_currency_value");
+        var $default_price = $parent.find(".oe_default_price:first .oe_currency_value");
+        var variant_ids = $ul.data("attribute_value_ids");
+        var values = [];
+        $parent.find('input.js_variant_change:checked, select.js_variant_change').each(function () {
+            values.push(+$(this).val());
+        });
+
+        $parent.find("label").removeClass("text-muted css_not_available");
+
+        var product_id = false;
+        var product_qty = false;
+        for (var k in variant_ids) {
+            if (_.isEmpty(_.difference(variant_ids[k][1], values))) {                
+                product_id = variant_ids[k][0];
+                product_qty = variant_ids[k][4];                
+                //$( "#prod_variant_id" ).attr('value', product_id);  
+                //$( "#prod_variant_id" ).text(product_id);   
+                break;
+            }            
+        }
+        
+        var $input_qty = $( "input[name='add_qty']" );
+        $input_qty.val(1);
+        
+        $( "div.stock_label_div" ).addClass("hidden");
+        $( "div.stock_label_variant_in" ).addClass("hidden"); 
+        $( "div.stock_label_variant_out" ).addClass("hidden"); 
+        if (product_id) {
+        if(product_qty<=0){
+            $( "div.stock_label_variant_out" ).removeClass("hidden");
+            $( "div.stock_label_variant_in" ).addClass("hidden"); 
+            $( "#qty_avail_variant" ).attr('value', product_qty);
+            $( "#qty_avail_variant" ).text(product_qty);   
+            $( "#add_to_cart" ).addClass("disabled"); 
+            $( ".fa-plus" ).addClass('hidden');
+            $( ".fa-minus" ).addClass("hidden");
+            $( "input[name='add_qty']" ).prop("readonly",true);
+            
+            }
+        if(product_qty>0){
+            $( "div.stock_label_variant_in" ).removeClass("hidden"); 
+            $( "div.stock_label_variant_out" ).addClass("hidden"); 
+            $( "#qty_avail_variant" ).attr('value', product_qty);  
+            $( "#qty_avail_variant" ).text(product_qty);
+            $( "#add_to_cart" ).removeClass("disabled");
+            $( "i.fa-plus" ).removeClass("hidden");
+            $( "i.fa-minus" ).removeClass("hidden");
+            $( "input[name='add_qty']" ).prop("readonly",false);
+            }
+        }    
+     if (product_id) {
+            var $img = $(this).closest('tr.js_product, .oe_website_sale').find('span[data-oe-model^="product."][data-oe-type="image"] img:first, img.product_detail_img');
+            $img.attr("src", "/website/image/product.product/" + product_id + "/image");
+            $img.parent().attr('data-oe-model', 'product.product').attr('data-oe-id', product_id)
+                .data('oe-model', 'product.product').data('oe-id', product_id);
+        }
+
+        $parent.find("input.js_variant_change:radio, select.js_variant_change").each(function () {
+            var $input = $(this);
+            var id = +$input.val();
+            var values = [id];
+
+            $parent.find("ul:not(:has(input.js_variant_change[value='" + id + "'])) input.js_variant_change:checked, select").each(function () {
+                values.push(+$(this).val());
+            });
+
+            for (var k in variant_ids) {
+                if (!_.difference(values, variant_ids[k][1]).length) {
+                    return;
+                }
+            }
+            $input.closest("label").addClass("css_not_available");
+            $input.find("option[value='" + id + "']").addClass("css_not_available");
+        });
+
+        if (product_id) {
+            $parent.removeClass("css_not_available");
+            $product_id.val(product_id);
+            $parent.find(".js_check_product").removeAttr("disabled");
+        } else {
+            $parent.addClass("css_not_available");
+            $product_id.val(0);
+            $parent.find(".js_check_product").attr("disabled", "disabled");
+        }
+    });
+    
+$('ul.js_add_cart_variants', oe_website_sale).each(function () {
+        $('input.js_variant_change, select.js_variant_change', this).first().trigger('change');
+    }); 
+    
+$('.a-submit', oe_website_sale).off('click').on('click', function () {
+        var product_added_Dict = $( "#product_added_qty" ).text();   
+        var $parent = $(this).closest('.js_product');
+        var $product_id = $parent.find('input.product_id').first();
+        var product_id = $product_id.val();
+        var product_added_list = malformedJSON2Array(product_added_Dict);
+        var product_added_qty = product_added_list[product_id];
+        var stock = $( "span[name='stock_available']" ).text();
+        var $input_qty = $( "input[name='add_qty']" );
+        var value = parseInt($input_qty.val(), 10);
+        var variant_qty = $( "#qty_avail_variant" ).attr('value');
+        
+	  if(variant_qty!=undefined)
+	      stock = parseInt(variant_qty);
+        
+       
+        
+        //alert(product_added_qty);alert(value);alert(stock);alert(parseInt(product_added_qty) + parseInt(value));
+        if((parseInt(product_added_qty) + parseInt(value))>parseInt(stock))
+        {
+           showDialog('Error','As you already added some of the Products, You can\'t add more than '+parseInt(stock-product_added_qty)+'.','error',6);
+           return false;
+        }
+        $(this).closest('form').submit();
+    });
+$('form.js_attributes input, form.js_attributes select', oe_website_sale).on('change', function () {
+        $(this).closest("form").submit();
+    }); 
+   
+});
+});
+

+ 79 - 0
views/templates.xml

@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+<data>
+
+<!-- Layout and common templates -->
+<template id="assets_frontend_ext" inherit_id="website.assets_frontend" name="Shop Ext">
+  <xpath expr="." position="inside">
+      <link rel='stylesheet' href='/web_site_sale_extend/static/src/css/website_sale_ext.css'/>
+      <link rel='stylesheet' href='/web_site_sale_extend/static/src/css/dialog_box.css'/>
+      <script type="text/javascript" src="/web_site_sale_extend/static/src/js/website_sale_ext.js"></script>
+      <script type="text/javascript" src="/web_site_sale_extend/static/src/js/dialog_box.js"></script>
+  </xpath>
+</template>
+<template id="products_stock_avail" inherit_id="website_sale.products_item" active="False" customize_show="True" name="Product Stock Label">
+  <xpath expr="//div[@class='oe_product_image']" position="inside">  
+    <div style="top:0;left:0;width:50%;position: relative; z-index: 9999;">
+      <t t-if="product.qty_available &gt; 0">
+      <div class="badge btn" style="background-color:green;opacity: 0.6;filter: alpha(opacity=60);">
+          <span t-esc="int(product.qty_available)"/>&#160;
+          <span t-esc="product.uom_id.name" groups="product.group_uom"></span>&#160;
+          <span>In Stock</span>
+      </div>
+      </t>
+      <t t-if="product.qty_available &lt;= 0" style="background-color:red;">
+          <div class="badge btn" style="background-color:red;opacity: 0.6;filter: alpha(opacity=60);">SOLD OUT</div>
+      </t>
+    </div>    
+  </xpath>  
+</template>
+
+<template id="product_stock_avail_add_page" inherit_id="website_sale.product" active="False" customize_show="True" name="Product Stock Available">
+  <xpath expr="//a[@id='add_to_cart']" position="before">
+      <div class="stock_label_div" style="width:50%;position: relative; z-index: 9999;">
+      <t t-if="product.qty_available &gt; 0">
+        <div class="badge btn stock_label" style="background-color:green;opacity: 0.6;filter: alpha(opacity=60);">
+          <span t-esc="int(product.qty_available)"/>&#160;
+          <span t-esc="product.uom_id.name" groups="product.group_uom"></span>&#160;
+          <span>In Stock</span>
+        </div>
+      </t>
+      <t t-if="product.qty_available &lt;= 0" style="background-color:red;">
+        <div class="badge btn stock_label" style="background-color:red;opacity: 0.6;filter: alpha(opacity=60);">SOLD OUT</div>        
+      </t>
+    </div>
+    <div class="stock_label_div_variant" style="width:50%;position: relative; z-index: 9999;">
+      <t>
+        <div class="badge btn stock_label_variant_in hidden" style="background-color:green;opacity: 0.6;filter: alpha(opacity=60);">
+          <span t-esc="int(product.qty_available)" id="qty_avail_variant" name="qty_avail_variant"/>&#160;
+          <span t-esc="product.uom_id.name" groups="product.group_uom"></span>&#160;
+          <span>In Stock</span>
+        </div>
+      </t>
+      <t style="background-color:red;">
+        <div class="badge btn stock_label_variant_out hidden" style="background-color:red;opacity: 0.6;filter: alpha(opacity=60);">SOLD OUT</div>        
+      </t>
+    </div>&#160;
+    <!--span  t-value="product.product_variant_ids[0].id" name="prod_variant_id" id="prod_variant_id"/-->
+    <span t-esc="website.added_to_cart_product_qty(product.id)" name="product_added_qty" id="product_added_qty" class="hidden"/>
+  </xpath>  
+  <xpath expr="//a[@id='add_to_cart']" position="replace">
+      <a id="add_to_cart" t-attf-class="btn btn-primary btn-lg mt8 js_check_product a-submit #{product.qty_available &lt;= 0 and 'disabled'}" href="#" >Add to Cart</a>
+  </xpath>  
+</template> 
+
+<template id="product_quantity_add_page" inherit_id="website_sale.product_quantity">
+  <xpath expr="//input[@name='add_qty']" position="after">    
+    <span id="stock_available" name="stock_available" class="hidden" t-esc="product.qty_available"/>    
+  </xpath>   
+</template> 
+
+<template id="product_quantity_add_cart" inherit_id="website_sale.cart">
+  <xpath expr="//span[@class='input-group-addon']" position="before">    
+    <span id="stock_available_line" t-att-data-line-id="line.id" t-att-data-product-id="line.product_id.id" name="stock_available_line" class="hidden" t-esc="line.product_id.qty_available"/>
+    
+  </xpath> 
+</template> 
+
+</data>
+</openerp>