uom.id, product.list_price, context['uom'])
else:
res[product.id] = product.list_price
- price_extra = 0.0
- for variant_id in product.attribute_value_ids:
- price_extra += variant_id.price_extra
- res[product.id] = (res[product.id] or 0.0) + price_extra
+ res[product.id] = res[product.id] + product.price_extra
+
return res
def _get_partner_code_name(self, cr, uid, ids, product, partner_id, context=None):
def _get_price_extra(self, cr, uid, ids, name, args, context=None):
result = dict.fromkeys(ids, False)
for product in self.browse(cr, uid, ids, context=context):
+ ctx = context.copy()
+ ctx.update(active_id=product.product_tmpl_id.id)
price_extra = 0.0
for variant_id in product.attribute_value_ids:
for price_id in variant_id.price_ids:
variants = [[p.id, map(int, p.attribute_value_ids), p.price] for p in product.product_variant_ids]
+
+ optional_products = {}
+ for o in product.optional_product_ids:
+ if not optional_products.get(o.product_tmpl_id.id):
+ optional_products[o.product_tmpl_id.id] = {
+ 'product_tmpl_id': o.product_tmpl_id,
+ 'product_ids': []
+ }
+ if o not in optional_products[o.product_tmpl_id.id]:
+ optional_products[o.product_tmpl_id.id]['product_ids'].append(o)
+
values = {
'search': search,
'category': category,
'main_object': product,
'product': product,
'variants': variants,
+ 'optional_products': optional_products
}
return request.website.render("website_sale.product", values)
@http.route(['/shop/cart'], type='http', auth="public", website=True)
def cart(self, **post):
+ cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
order = request.website.sale_get_order()
+
values = {
'order': order,
- 'suggested_products': [],
+ 'suggested_products': []
}
if order:
- if not request.context.get('pricelist'):
- request.context['pricelist'] = order.pricelist_id.id
- values['suggested_products'] = order._cart_accessories(context=request.context)
+ if not context.get('pricelist'):
+ context['pricelist'] = order.pricelist_id.id
+ values['suggested_products'] = order._cart_accessories(context=context)
+
return request.website.render("website_sale.cart", values)
@http.route(['/shop/cart/update'], type='http', auth="public", methods=['POST'], website=True)
def cart_update(self, product_id, add_qty=1, set_qty=0, **kw):
- cr, uid, context = request.cr, request.uid, request.context
- request.website.sale_get_order(force_create=1)._cart_update(product_id=int(product_id), add_qty=add_qty, set_qty=set_qty)
+ cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
+ order = request.website.sale_get_order(force_create=1)
+
+ print kw
+ for key,val in kw.items():
+ if 'option-' in key:
+ order._cart_update(product_id=int(key.split("-")[1]), add_qty=1)
+
+ order._cart_update(product_id=int(product_id), add_qty=add_qty, set_qty=set_qty)
return request.redirect("/shop/cart")
@http.route(['/shop/cart/update_json'], type='json', auth="public", methods=['POST'], website=True)
@http.route(['/shop/checkout'], type='http', auth="public", website=True)
def checkout(self, **post):
- cr, uid, context, registry = request.cr, request.uid, request.context, request.registry
+ cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
order = request.website.sale_get_order(force_create=1, context=context)
'website_sequence': fields.integer('Sequence', help="Determine the display order in the Website E-commerce"),
'website_url': fields.function(_website_url, string="Website url", type="char"),
'public_categ_ids': fields.many2many('product.public.category', string='Public Category', help="Those categories are used to group similar products for e-commerce."),
+ 'optional_product_ids': fields.many2many('product.product', string='Optional Products'),
}
def _defaults_website_sequence(self, cr, uid, *l, **kwargs):
product_ids = random.sample(s, min(len(s),3))
return self.pool['product.product'].browse(cr, uid, product_ids, context=context)
+ def _cart_optional_products(self, cr, uid, ids, context=None):
+ for order in self.browse(cr, uid, ids, context=context):
+ products = {}
+ for l in order.website_order_line:
+ opt = {}
+ for o in l.product_id.optional_product_ids:
+ if not opt.get(o.product_tmpl_id.id):
+ opt[o.product_tmpl_id.id] = {
+ 'product_tmpl_id': o.product_tmpl_id,
+ 'product_ids': []
+ }
+ if o not in opt[o.product_tmpl_id.id]:
+ opt[o.product_tmpl_id.id]['product_ids'].append(o)
+
+ if opt:
+ products[l.id] = {
+ 'order_line_id': l,
+ 'optional_product_tmpl': opt
+ }
+
+ return products
+
class website(orm.Model):
_inherit = 'website'
$(this).closest("form").submit();
});
+ // modal to select optional product in my cart
+ $("#modal_optional_products label").mousedown(function(event) {
+ $(event.currentTarget).parents('li.optional_product_tmpl:first').find("input[type=checkbox]").each(function () {
+ if($(this).parent()[0] != event.currentTarget) $(this).removeAttr('checked');
+ });
+ });
+
// change price when they are variants
var $price = $(".oe_price .oe_currency_value");
$('form.js_add_cart_json label').on('mouseup', function (ev) {
var $form_var = $('form.js_add_cart_variants');
var variant_ids = $form_var.data("attribute_value_ids");
- $form_var.on('change', 'input, select', function (ev) {
+ $form_var.on('change', 'input.js_variant_change, select.js_variant_change', function (ev) {
var values = [];
$form_var.find("label").removeClass("text-muted css_not_available");
$form_var.find(".a-submit").removeProp("disabled");
- $form_var.find('input:checked, select').each(function () {
+ $form_var.find('input.js_variant_change:checked, select').each(function () {
values.push(+$(this).val());
});
var available = false;
}
}
- $form_var.find("input:radio, select").each(function () {
+ $form_var.find("input.js_variant_change:radio, select.js_variant_change").each(function () {
var id = +$(this).val();
var values = [id];
- $form_var.find(">ul>li:not(:has(input[value='" + id + "'])) input:checked, select").each(function () {
+ $form_var.find(">ul>li: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) {
$(".oe_price_h4").addClass("hidden");
$(".oe_not_available").removeClass("hidden");
$form_var.find('input[name="product_id"]').val(0);
- $form_var.find(".a-submit").prop("disabled", "disabled");
+ $form_var.find(".js_check_product").prop("disabled", "disabled");
}
});
- $form_var.find("input:first").trigger('change');
-
+ $form_var.find("input.js_variant_change:first").trigger('change');
});
<t t-call="website_sale.product_price"/>
- <a class="btn btn-primary btn-lg mt8 a-submit">Add to Cart</a>
+ <a t-if="not optional_products" class="btn btn-primary btn-lg mt8 a-submit js_check_product">Add to Cart</a>
+ <a t-if="optional_products" class="btn btn-primary btn-lg mt8 js_check_product" href="#" data-toggle="modal" data-target="#modal_optional_products">Add to Cart</a>
+
+ <t t-call="website_sale.product_modal_optional_products"/>
+
</form>
<hr t-if="product.description_sale"/>
</div>
</section>
<div itemprop="description" t-field="product.website_description" class="oe_structure mt16" id="product_full_description"/>
+
</div>
</t>
</template>
+<template id="product_modal_optional_products">
+ <div t-if="optional_products" id="modal_optional_products" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
+ <h4 class="modal-title" id="myModalLabel">Choose your optional products</h4>
+ </div>
+ <div class="modal-body">
+ <ul>
+ <li class="optional_product_tmpl" t-foreach="optional_products" t-as="t">
+ <t t-set="o_tmpl" t-value="optional_products[t]"/>
+
+ <t t-if="len(o_tmpl['product_ids']) == 1">
+ <label><input t-att-name="'option-%s' % o_tmpl['product_ids'][0].id" type="checkbox"/> <span t-field="o_tmpl['product_tmpl_id'].name"/></label>
+
+ <span class="badge" t-if="o_tmpl['product_ids'][0].price">
+ + <span t-field="o_tmpl['product_ids'][0].price" t-field-options='{
+ "widget": "monetary",
+ "display_currency": "website.pricelist_id.currency_id"
+ }'/>
+ </span>
+ </t>
+ <t t-if="len(o_tmpl['product_ids']) > 1">
+ <span t-field="o_tmpl['product_tmpl_id'].name"/>
+ <ul>
+ <li t-foreach="o_tmpl['product_ids']" t-as="product_id">
+ <label><input t-att-name="'option-%s' % product_id.id" type="checkbox"/> <span t-esc="', '.join([value_id.name for value_id in product_id.attribute_value_ids])"/></label>
+ <span class="badge" t-if="product_id.price">
+ + <span t-field="product_id.price" t-field-options='{
+ "widget": "monetary",
+ "display_currency": "website.pricelist_id.currency_id"
+ }'/>
+ </span>
+ </li>
+ </ul>
+ </t>
+ </li>
+ </ul>
+ </div>
+ <div class="modal-footer">
+ <a class="btn btn-primary a-submit">Continue</a>
+ <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
+ </div>
+ </div>
+ </div>
+ </div>
+</template>
+
<template id="product_price">
<div itemprop="offers" itemscope="itemscope" itemtype="http://schema.org/Offer" class="product_price mt16">
<h4 class="oe_price_h4">
<strong t-field="variant_id.attribute_id.name"/>
<t t-if="variant_id.attribute_id.type == 'select'">
- <select class="form-control" t-att-name="'attribute-%s' % variant_id.attribute_id.id">
+ <select class="form-control js_variant_change" t-att-name="'attribute-%s' % variant_id.attribute_id.id">
<t t-foreach="variant_id.value_ids" t-as="value_id">
<option t-att-value="value_id.id">
<span t-field="value_id.name"/>
<t t-foreach="variant_id.value_ids" t-as="value_id">
<li t-if="value_id.product_ids" class="form-group js_attribute_value" style="margin: 0;">
<label class="control-label" style="margin: 0 20px;">
- <input type="radio" t-att-checked="'checked' if not inc else ''" t-att-name="'attribute-%s' % variant_id.attribute_id.id" t-att-value="value_id.id" style="vertical-align: top; margin-right: 10px;"/>
+ <input type="radio" class="js_variant_change" t-att-checked="'checked' if not inc else ''" t-att-name="'attribute-%s' % variant_id.attribute_id.id" t-att-value="value_id.id" style="vertical-align: top; margin-right: 10px;"/>
<span t-field="value_id.name"/>
<span class="badge" t-if="value_id.price_extra">
<t t-esc="value_id.price_extra > 0 and '+' or ''"/><span t-field="value_id.price_extra" t-field-options='{
<t t-foreach="variant_id.value_ids" t-as="value_id">
<label t-attf-style="background-color:#{value_id.color or value_id.name}"
t-attf-class="css_attribute_color #{'active' if not inc else ''}">
- <input type="radio"
+ <input type="radio" class="js_variant_change"
t-att-checked="'checked' if not inc else ''"
t-att-name="'attribute-%s' % variant_id.attribute_id.id"
t-att-value="value_id.id"
<t t-call="website_sale.product_price"/>
- <a class="btn btn-primary btn-lg mt8 a-submit">Add to Cart</a>
+ <a t-if="not optional_products" class="btn btn-primary btn-lg mt8 a-submit">Add to Cart</a>
+ <a t-if="optional_products" class="btn btn-primary btn-lg mt8 " href="#" data-toggle="modal" data-target="#modal_optional_products">Add to Cart</a>
+
+ <t t-call="website_sale.product_modal_optional_products"/>
</form>
</xpath>
</template>
</table>
<t t-call="website_sale.total"/>
<div class="clearfix"/>
- <a t-if="website_sale_order and website_sale_order.website_order_line" href="/shop/checkout" class="btn btn-primary pull-right mb32">Process Checkout <span class="fa fa-long-arrow-right"/></a>
+
+ <a t-if="not optional_products and website_sale_order and website_sale_order.website_order_line" class="btn btn-primary pull-right mb32" href="/shop/checkout">Process Checkout <span class="fa fa-long-arrow-right"/></a>
+
<div class="oe_structure"/>
</div>
<div class="col-lg-3 col-lg-offset-1 col-sm-3 col-md-3 text-muted" id="right_column">
<field name="website_published" class="pull-right" widget="website_button"/>
<field name="alternative_product_ids" widget="many2many_tags"/>
<field name="accessory_product_ids" widget="many2many_tags"/>
+ <field name="optional_product_ids" widget="many2many_tags"/>
<field name="website_style_ids" widget="many2many_tags"/>
<field name="website_sequence"/>
</group>