[IMP] website_quote: adding layout categories to website quotations

This commit is contained in:
Julien Louette
2016-03-25 11:34:26 +01:00
committed by David Monjoie
parent b391c8d494
commit 293c1c06e6
5 changed files with 151 additions and 44 deletions
+2
View File
@@ -148,10 +148,12 @@ class sale_quote(http.Controller):
'name': option.name,
'order_id': order.id,
'product_id': option.product_id.id,
'layout_category_id': option.layout_category_id.id,
'product_uom_qty': option.quantity,
'product_uom': option.uom_id.id,
'discount': option.discount,
}
line = request.registry.get('sale.order.line').create(request.cr, SUPERUSER_ID, vals, context=request.context)
request.registry.get('sale.order.line')._compute_tax_id(request.cr, SUPERUSER_ID, [line], context=request.context)
option_obj.write(request.cr, SUPERUSER_ID, [option.id], {'line_id': line}, context=request.context)
+37
View File
@@ -36,6 +36,7 @@ class sale_quote_template(osv.osv):
'url': '/quote/template/%d' % quote_id[0]
}
class sale_quote_line(osv.osv):
_name = "sale.quote.line"
_description = "Quotation Template Lines"
@@ -44,6 +45,7 @@ class sale_quote_line(osv.osv):
'quote_id': fields.many2one('sale.quote.template', 'Quotation Template Reference', required=True, ondelete='cascade', select=True),
'name': fields.text('Description', required=True, translate=True),
'product_id': fields.many2one('product.product', 'Product', domain=[('sale_ok', '=', True)], required=True),
'layout_category_id': fields.many2one('sale.layout_category', string='Section'),
'website_description': fields.related('product_id', 'product_tmpl_id', 'quote_description', string='Line Description', type='html', translate=True),
'price_unit': fields.float('Unit Price', required=True, digits_compute= dp.get_precision('Product Price')),
'discount': fields.float('Discount (%)', digits_compute= dp.get_precision('Discount')),
@@ -217,6 +219,7 @@ class sale_order(osv.osv):
'discount': line.discount,
'product_uom_qty': line.product_uom_qty,
'product_id': line.product_id.id,
'layout_category_id': line.layout_category_id,
'product_uom': line.product_uom_id.id,
'website_description': line.website_description,
'state': 'draft',
@@ -232,6 +235,7 @@ class sale_order(osv.osv):
price = option.price_unit
options.append((0, 0, {
'product_id': option.product_id.id,
'layout_category_id': option.layout_category_id,
'name': option.name,
'quantity': option.quantity,
'uom_id': option.uom_id.id,
@@ -309,6 +313,7 @@ class sale_quote_option(osv.osv):
'template_id': fields.many2one('sale.quote.template', 'Quotation Template Reference', ondelete='cascade', select=True, required=True),
'name': fields.text('Description', required=True, translate=True),
'product_id': fields.many2one('product.product', 'Product', domain=[('sale_ok', '=', True)], required=True),
'layout_category_id': fields.many2one('sale.layout_category', string='Section'),
'website_description': fields.html('Option Description', translate=True),
'price_unit': fields.float('Unit Price', required=True, digits_compute= dp.get_precision('Product Price')),
'discount': fields.float('Discount (%)', digits_compute= dp.get_precision('Discount')),
@@ -356,6 +361,7 @@ class sale_order_option(osv.osv):
'line_id': fields.many2one('sale.order.line', on_delete="set null"),
'name': fields.text('Description', required=True),
'product_id': fields.many2one('product.product', 'Product', domain=[('sale_ok', '=', True)]),
'layout_category_id': fields.many2one('sale.layout_category', string='Section'),
'website_description': fields.html('Line Description'),
'price_unit': fields.float('Unit Price', required=True, digits_compute= dp.get_precision('Product Price')),
'discount': fields.float('Discount (%)', digits_compute= dp.get_precision('Discount')),
@@ -418,6 +424,37 @@ class sale_order_option(osv.osv):
domain = {'uom_id': [('category_id', '=', self.product_id.uom_id.category_id.id)]}
return {'domain': domain}
@api.multi
def button_add_to_order(self):
order = self.order_id
if order.state not in ['draft', 'sent']:
return False
option = self
if option.product_id in [line.product_id for line in order.order_line]:
line = [line for line in order.order_line if line.product_id == option.product_id][0]
vals = {
'product_uom_qty': line.product_uom_qty + 1,
}
line.write(vals)
else:
vals = {
'price_unit': option.price_unit,
'website_description': option.website_description,
'name': option.name,
'order_id': order.id,
'product_id': option.product_id.id,
'layout_category_id': option.layout_category_id.id,
'product_uom_qty': option.quantity,
'product_uom': option.uom_id.id,
'discount': option.discount,
}
line = self.env['sale.order.line'].create(vals)
self.env['sale.order.line']._compute_tax_id()
self.env['sale.order.option'].write({'line_id': line})
return {'type':'ir.actions.client', 'tag':'reload'}
class product_template(osv.Model):
_inherit = "product.template"
@@ -9,7 +9,7 @@
</div>
</xpath>
<xpath expr="//div[@class='page']/p[@id='fiscal_position_remark']" position="after">
<div t-if="doc.options and doc.state in ['draft', 'sent']">
<div t-if="doc.options and doc.state in ['draft', 'sent']" style="page-break-before:always;">
<h2>
<span>Suggested Products</span>
</h2>
@@ -26,47 +26,96 @@
</tr>
</thead>
<tbody>
<tr t-foreach="quotation.order_line" t-as="line">
<td>
<span t-field="line.name"/>
</td>
<td>
<div id="quote_qty">
<span t-field="line.product_uom_qty"/>
<span t-field="line.product_uom"/>
</div>
</td>
<td>
<div t-foreach="line.tax_id" t-as="tax">
<t t-esc="tax.name"/>
</div>
</td>
<td>
<strong t-if="line.discount" class="text-info">
<t t-esc="((line.discount % 1) and '%s' or '%d') % line.discount"/>% discount
</strong>
</td>
<td>
<div t-field="line.price_unit"
t-field-options='{"widget": "monetary", "display_currency": "quotation.pricelist_id.currency_id"}'
t-att-style="line.discount and 'text-decoration: line-through' or ''"
t-att-class="(line.discount and 'text-danger' or '') + 'text-right'"/>
<!-- TODO: apply monetary widget formating -->
<div t-if="line.discount">
<t t-esc="'%.2f' % ((1-line.discount / 100.0) * line.price_unit)"/>
</div>
</td>
<td>
<div class="text-right"
t-field="line.price_subtotal"
t-field-options='{"widget": "monetary", "display_currency": "quotation.pricelist_id.currency_id"}'/>
</td>
<td class="text-center">
<a t-attf-href="./update_line/#{ line.id }/?order_id=#{ quotation.id }&amp;unlink=True&amp;token=#{ quotation.access_token }" class="mb8 js_update_line_json hidden-print" t-if="line.option_line_id">
<span class="fa fa-trash-o"></span>
</a>
</td>
</tr>
<t t-foreach="quotation.layout_categories()" t-as="layout_category">
<t t-if="layout_category_size > 1" groups="sale.group_sale_layout">
<tr class="active">
<td colspan="7" style="font-weight: bold; border-bottom: 1px solid black;">&amp;bull;
<t t-esc="layout_category['name']"/>
</td>
</tr>
</t>
<!-- Lines associated -->
<t t-foreach="layout_category['lines']" t-as="line">
<tr>
<td>
<span t-field="line.name"/>
</td>
<td>
<div id="quote_qty">
<span t-field="line.product_uom_qty"/>
<span t-field="line.product_uom"/>
</div>
</td>
<td>
<div t-foreach="line.tax_id" t-as="tax">
<t t-esc="tax.name"/>
</div>
</td>
<td>
<strong t-if="line.discount" class="text-info">
<t t-esc="((line.discount % 1) and '%s' or '%d') % line.discount"/>% discount
</strong>
</td>
<td>
<div t-field="line.price_unit"
t-field-options='{"widget": "monetary", "display_currency": "quotation.pricelist_id.currency_id"}'
t-att-style="line.discount and 'text-decoration: line-through' or ''"
t-att-class="(line.discount and 'text-danger' or '') + 'text-right'"/>
<!-- TODO: apply monetary widget formating -->
<div t-if="line.discount">
<t t-esc="'%.2f' % ((1-line.discount / 100.0) * line.price_unit)"/>
</div>
</td>
<td>
<div class="text-right"
t-field="line.price_subtotal"
t-field-options='{"widget": "monetary", "display_currency": "quotation.pricelist_id.currency_id"}'/>
</td>
<td class="text-center">
<a t-attf-href="./update_line/#{ line.id }/?order_id=#{ quotation.id }&amp;unlink=True&amp;token=#{ quotation.access_token }" class="mb8 js_update_line_json hidden-print" t-if="line.option_line_id">
<span class="fa fa-trash-o"></span>
</a>
</td>
</tr>
</t>
<t t-if="layout_category_size > 1 and layout_category['subtotal']" groups="sale.group_sale_layout">
<tr>
<td></td><td></td><td></td><td></td>
<td class="text-right"><strong>Subtotal:</strong></td>
<td class="text-right">
<t t-set="subtotal" t-value="sum(line.price_subtotal for line in layout_category['lines'])"/>
<strong data-id="total_amount" t-esc="subtotal" t-esc-options='{"widget": "monetary","display_currency": "quotation.pricelist_id.currency_id"}'/>
</td>
</tr>
</t>
<t t-if="layout_category_size > 1 and layout_category['pagebreak']" groups="sale.group_sale_layout">
<![CDATA[
</tbody>
</table>
<p style="page-break-before:always;"> </p>
<table class="table table-condensed">
]]>
<thead>
<tr>
<th>Products</th>
<th>Quantity</th>
<th>Taxes</th>
<th><span t-if="True in [line.discount > 0 for line in quotation.order_line]">Discount</span></th>
<th class="text-right">Unit Price</th>
<th class="text-right">Tax Excluded Price</th>
<th></th>
</tr>
</thead>
<![CDATA[
<tbody>
]]>
</t>
</t>
<tr>
<td></td><td></td><td></td><td></td>
<td class="text-right"><strong>Subtotal:</strong></td>
@@ -74,6 +123,7 @@
<strong data-id="total_amount" t-field="quotation.amount_untaxed" t-field-options='{"widget": "monetary","display_currency": "quotation.pricelist_id.currency_id"}'/>
</td>
</tr>
<tr>
<td></td><td></td><td></td><td></td>
<td class="text-right">Taxes:</td>
@@ -18,11 +18,13 @@
<tree string="Sales Quotation Template Lines" editable="bottom">
<field name="sequence" widget="handle"/>
<field name="product_id"/>
<field name="layout_category_id" groups="sale.group_sale_layout"/>
<field name="name"/>
<field name="quantity"/>
<field name="uom_id" groups="product.group_uom"/>
<field name="price_unit"/>
<field name="discount" groups="sale.group_discount_per_so_line"/>
<button name="button_add_to_order" class="oe_link" icon="fa-shopping-cart" string="Add to order lines" type="object"/>
<field name="website_description" invisible="1"/>
</tree>
</field>
@@ -72,6 +74,7 @@
<group>
<group>
<field name="product_id" on_change="on_change_product_id(product_id, product_uom_id)"/>
<field name="layout_category_id" groups="sale.group_sale_layout"/>
<label for="product_uom_qty"/>
<div>
<field
@@ -96,6 +99,7 @@
<tree string="Sales Quotation Template Lines" editable="bottom">
<field name="sequence" widget="handle"/>
<field name="product_id" on_change="on_change_product_id(product_id, product_uom_id)"/>
<field name="layout_category_id" groups="sale.group_sale_layout"/>
<field name="name"/>
<field name="product_uom_qty"/>
<field name="product_uom_id" groups="product.group_uom" on_change="product_uom_change(product_id, product_uom_id"/>
@@ -105,6 +109,20 @@
</tree>
</field>
</page>
<page string="Suggested Products">
<field name="options">
<tree string="Sales Quotation Template Lines" editable="bottom">
<field name="product_id"/>
<field name="layout_category_id" groups="sale.group_sale_layout"/>
<field name="name"/>
<field name="quantity"/>
<field name="uom_id" groups="product.group_uom"/>
<field name="price_unit"/>
<field name="discount" groups="sale.group_discount_per_so_line"/>
<field name="website_description" invisible="1"/>
</tree>
</field>
</page>
<page string="Suggested Products">
<field name="options">
<tree string="Sales Quotation Template Lines" editable="bottom">
@@ -163,10 +181,10 @@
<p class="oe_view_nocontent_create">
Create a Quotation, the first step of a new sale.
</p><p>
Your next actions should flow efficiently: confirm the Quotation
Your next actions should flow efficiently: confirm the Quotation
to a Sale Order, then create the Invoice and collect the Payment.
</p><p>
Note that once a Quotation becomes a Sale Order, it will be moved
Note that once a Quotation becomes a Sale Order, it will be moved
from the Quotations list to the Sales Order list.
</p>
</field>