Skip to content

Commit

Permalink
Sort by Download and rating (OCA#46)
Browse files Browse the repository at this point in the history
* [WIP] added initial support for Google recaptcha

* [WIP]added dependencies

* [IMP]Added google captcha with download functionality with reset and validation

* [IMP]added download count fields and increament it when donwloaded

* [ADD]added missing files

* [IMP]website_apps_store: add sort by download count on website

* remove console and not extra space

* [VER]changed version number

* [FIX]website_apps_store: fix test case error

* [FIX]reset only if google recaptcha is initiated
  • Loading branch information
bizzappdev authored and Victor Martin committed May 2, 2019
1 parent 4569351 commit b0991b5
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 41 deletions.
3 changes: 2 additions & 1 deletion website_apps_store/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
{
"name": "Website Apps Store",
"version": "11.0.2.2.0",
"version": "11.0.3.0.0",
'author': 'Odoo Community Association (OCA), BizzAppDev',
"website": "https://github.com/OCA/apps-store",
"license": "AGPL-3",
"category": "Sales",
"depends": [
'website_sale',
'website_form_recaptcha',
'apps_download',
'apps_product_creator',
],
Expand Down
41 changes: 28 additions & 13 deletions website_apps_store/controllers/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from odoo.addons.http_routing.models.ir_http import slug
from odoo.addons.website.controllers.main import QueryURL
from odoo.addons.website_sale.controllers.main import WebsiteSale, TableCompute
from odoo.exceptions import ValidationError

_logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -168,22 +169,34 @@ def change_product_attribute_version(self, **kwargs):
}
return vals

@http.route('/shop/cart/download_source', type='json',
auth="public", website=True)
def download_source_product(self, **kwargs):
product_id = kwargs.get('product_id', False)
tmpl_id = kwargs.get('product_template_id', False)
product = request.env['product.product'].sudo().browse(product_id)
if not product:
product_tmpl = request.env['product.template'].sudo().browse(
tmpl_id)
product = product_tmpl.get_version_info()
return product.id
def validate_recaptcha(self, captcha):
""" Function for validating Recaptcha """
captcha_obj = request.env['website.form.recaptcha']
ip_addr = request.httprequest.environ.get('HTTP_X_FORWARDED_FOR')
if ip_addr:
ip_addr = ip_addr.split(',')[0]
else:
ip_addr = request.httprequest.remote_addr
try:
captcha_obj.action_validate(
captcha, ip_addr
)
except ValidationError:
raise ValidationError([captcha_obj.RESPONSE_ATTR])

@http.route(
'/shop/download_product_zip/<model("product.product"):product>',
['/shop/download_product_zip/<model("product.template"):product_tmpl>'
'/<model("product.product"):product>/'
'<string:google_captcha>',
'/shop/download_product_zip/<model("product.template"):product_tmpl>/'
'<string:google_captcha>'],
type='http', auth="public", website=True)
def download_product_zip(self, product, **kwargs):
def download_product_zip(self, product_tmpl, product=False,
google_captcha='', **kwargs):
self.validate_recaptcha(google_captcha)
if not product:
product = product_tmpl.get_version_info()

attachment = request.env['ir.attachment'].sudo().search([
('res_id', '=', product.id),
('res_model', '=', product._name),
Expand All @@ -198,6 +211,8 @@ def download_product_zip(self, product, **kwargs):
if attachment:
filecontent = base64.b64decode(attachment.datas)
disposition = 'attachment; filename="%s"' % attachment.datas_fname
# increasing count for the product download
product.download_count = product.download_count + 1
return request.make_response(
filecontent,
[('Content-Type', 'application/zip, application/octet-stream'),
Expand Down
1 change: 1 addition & 0 deletions website_apps_store/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from . import product
from . import product_template
19 changes: 4 additions & 15 deletions website_apps_store/models/product.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,10 @@
# Copyright (C) 2017-Today: Odoo Community Association (OCA)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from odoo import models
from odoo import models, fields


class ProductTemplate(models.Model):
_inherit = 'product.template'
class ProductProduct(models.Model):
_inherit = 'product.product'

def get_author_details(self):
author_ids = []
for variant in self.product_variant_ids:
for author in variant.app_author_ids:
if author not in author_ids:
author_ids.append(author)
return author_ids

def get_version_info(self):
products = self.product_variant_ids.sorted(
lambda a: a.attribute_value_ids.sequence, reverse=True)
return products[0]
download_count = fields.Integer()
31 changes: 31 additions & 0 deletions website_apps_store/models/product_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Copyright (C) 2017-Today: Odoo Community Association (OCA)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from odoo import models, fields, api


class ProductTemplate(models.Model):
_inherit = 'product.template'

@api.multi
@api.depends('product_variant_ids', 'product_variant_ids.download_count')
def _compute_total_download_count(self):
for product in self:
product.total_download_count = sum(
product.mapped('product_variant_ids.download_count'))

total_download_count = fields.Integer(
compute="_compute_total_download_count", store=True)

def get_author_details(self):
author_ids = []
for variant in self.product_variant_ids:
for author in variant.app_author_ids:
if author not in author_ids:
author_ids.append(author)
return author_ids

def get_version_info(self):
products = self.product_variant_ids.sorted(
lambda a: a.attribute_value_ids.sequence, reverse=True)
return products[0]
37 changes: 27 additions & 10 deletions website_apps_store/static/src/js/website_sale.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ odoo.define('website_apps_store.website_sale', function (require) {
require("website.content.zoomodoo");
var _t = core._t;


$('.oe_website_sale').each(function () {
var oe_website_sale = this;
var $product_global;
Expand All @@ -31,6 +32,7 @@ odoo.define('website_apps_store.website_sale', function (require) {
return formatted.join(l10n.decimal_point);
}


function update_product_image(event_source, product_id) {
var $img;
if ($('#o-carousel-product').length) {
Expand Down Expand Up @@ -155,16 +157,31 @@ odoo.define('website_apps_store.website_sale', function (require) {
});

$('#download_zip').on('click', function(ev){
var product_template_id = $(this).data('tmpl-id');

ajax.jsonRpc("/shop/cart/download_source", 'call', {
'product_id': $product_global,
'product_template_id': product_template_id,
}).then(function (data) {
if(data){
window.location.href = "/shop/download_product_zip/" + data;
}
});
var product_template_id = $(this).data('tmpl-id');
event.preventDefault();
var google_captcha = $('#g-recaptcha-response').val();
if (!google_captcha)
return ;
if (grecaptcha !== 'undefined'){
grecaptcha.reset();
}
if ($product_global){
window.location.href = "/shop/download_product_zip/" + product_template_id + '/' + $product_global + '/' + google_captcha;
}else{
window.location.href = "/shop/download_product_zip/" + product_template_id + '/' + google_captcha;
}
});
var $captchas = $('.o_website_form_recaptcha');
ajax.post('/website/recaptcha/', {}).then(
function (result) {
var data = JSON.parse(result);
$captchas.append($(
'<div class="g-recaptcha" data-sitekey="' + data.site_key + '"></div>'
));
if ($captchas.length) {
$.getScript('https://www.google.com/recaptcha/api.js');
}
}
);
});
});
23 changes: 21 additions & 2 deletions website_apps_store/views/templates.xml
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,16 @@
<t t-call="website_apps_store.version_display"/>
<t t-call="website_apps_store.maturity_display"/>
</xpath>
<xpath expr="//t[@t-set='website_sale_sortable']" position="before">
<t t-set="download_count_desc_label">Download Count - Max to Min</t>
<t t-set="download_count_asc_label">Download Count - Min to Max</t>
</xpath>
<xpath expr="//t[@t-set='website_sale_sortable']" position="replace">
<t t-set="website_sale_sortable" t-value="[
(name_asc_label, 'name asc'),
(name_desc_label, 'name desc')
(name_desc_label, 'name desc'),
(download_count_desc_label, 'total_download_count desc'),
(download_count_asc_label, 'total_download_count asc'),
]"/>
</xpath>
</template>
Expand Down Expand Up @@ -129,6 +135,13 @@
<span t-esc="' / '.join(value.name for value in attr.value_ids.sorted(reverse=True))" class="font_12"/>
</t>
</t>

<!--Sort by Download counts-->
<div class="pull-right">
<span class="fa fa-download"></span>
<sapn t-esc="product.total_download_count"></sapn>
</div>

</xpath>
<xpath expr='//div[hasclass("product_price")]//span[@t-esc="product.website_price"]' position="replace">
<span t-esc="product.website_price" t-options="{'widget': 'monetary', 'display_currency': website.currency_id}" t-if="not product.odoo_module_id"/>
Expand Down Expand Up @@ -180,7 +193,13 @@
<xpath expr="//div[@id='product_details']/h1[@t-field='product.name']" position="attributes">
<attribute name="class">name_product</attribute>
</xpath>
<xpath expr='//form[hasclass("js_add_cart_variants")]' position="after">
<xpath expr='//form[hasclass("js_add_cart_variants")]'
position="after">
<div class="form-group form-field o_website_form_required_custom">
<div class="col-md-7 col-sm-8">
<span class="o_website_form_recaptcha" />
</div>
</div>
<div class="col-xs-12 padd_0" t-if="product.odoo_module_id">
<div class="col-xs-4 mt16 mb16">
<button class="btn btn-primary btn-lg"
Expand Down

0 comments on commit b0991b5

Please sign in to comment.