[MOV] website_quote: reorganize addon and split models according to guidelines
This commit is contained in:
committed by
Thibault Delavallée
parent
4c8a5b164a
commit
1fe106ef7a
@@ -1,2 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import controllers
|
||||
import models
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
{
|
||||
'name': 'Online Proposals',
|
||||
'category': 'Website',
|
||||
@@ -11,12 +13,13 @@ Odoo Sale Quote Roller
|
||||
""",
|
||||
'depends': ['website', 'sale', 'mail', 'payment', 'website_portal_sale', 'website_mail'],
|
||||
'data': [
|
||||
'quotation_report.xml',
|
||||
'views/website_quotation.xml',
|
||||
'views/website_quotation_backend.xml',
|
||||
'views/report_saleorder.xml',
|
||||
'views/report_quotation.xml',
|
||||
'data/website_quotation_data.xml',
|
||||
'report/sale_order_reports.xml',
|
||||
'report/sale_order_templates.xml',
|
||||
'report/website_quote_templates.xml',
|
||||
'views/sale_order_views.xml',
|
||||
'views/sale_quote_views.xml',
|
||||
'views/website_quote_templates.xml',
|
||||
'security/ir.model.access.csv',
|
||||
],
|
||||
'demo': [
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import main
|
||||
|
||||
@@ -1 +1,6 @@
|
||||
import order
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import sale_order
|
||||
import sale_quote
|
||||
import product_template
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp.osv import osv, fields
|
||||
|
||||
class product_template(osv.Model):
|
||||
_inherit = "product.template"
|
||||
|
||||
_columns = {
|
||||
'website_description': fields.html('Description for the website'), # hack, if website_sale is not installed
|
||||
'quote_description': fields.html('Description for the quote'),
|
||||
}
|
||||
@@ -13,100 +13,6 @@ from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
|
||||
from openerp.tools.translate import _, html_translate
|
||||
|
||||
|
||||
class sale_quote_template(osv.osv):
|
||||
_name = "sale.quote.template"
|
||||
_description = "Sale Quotation Template"
|
||||
_columns = {
|
||||
'name': fields.char('Quotation Template', required=True),
|
||||
'website_description': fields.html('Description', translate=html_translate, sanitize=False),
|
||||
'quote_line': fields.one2many('sale.quote.line', 'quote_id', 'Quotation Template Lines', copy=True),
|
||||
'note': fields.text('Terms and conditions'),
|
||||
'options': fields.one2many('sale.quote.option', 'template_id', 'Optional Products Lines', copy=True),
|
||||
'number_of_days': fields.integer('Quotation Duration', help='Number of days for the validity date computation of the quotation'),
|
||||
'require_payment': fields.selection([
|
||||
(0, 'Not mandatory on website quote validation'),
|
||||
(1, 'Immediate after website order validation'),
|
||||
(2, 'Immediate after website order validation and save a token'),
|
||||
], 'Payment', help="Require immediate payment by the customer when validating the order from the website quote"),
|
||||
'mail_template_id': fields.many2one('mail.template', 'Confirmation Mail', help="This e-mail template will be sent on confirmation. Leave empty to send nothing.")
|
||||
}
|
||||
def open_template(self, cr, uid, quote_id, context=None):
|
||||
return {
|
||||
'type': 'ir.actions.act_url',
|
||||
'target': 'self',
|
||||
'url': '/quote/template/%d' % quote_id[0]
|
||||
}
|
||||
|
||||
|
||||
class sale_quote_line(osv.osv):
|
||||
_name = "sale.quote.line"
|
||||
_description = "Quotation Template Lines"
|
||||
_columns = {
|
||||
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of sale quote lines."),
|
||||
'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')),
|
||||
'product_uom_qty': fields.float('Quantity', required=True, digits_compute= dp.get_precision('Product UoS')),
|
||||
'product_uom_id': fields.many2one('product.uom', 'Unit of Measure ', required=True),
|
||||
}
|
||||
_order = 'sequence, id'
|
||||
_defaults = {
|
||||
'product_uom_qty': 1,
|
||||
'discount': 0.0,
|
||||
'sequence': 10,
|
||||
}
|
||||
def on_change_product_id(self, cr, uid, ids, product, uom_id=None, context=None):
|
||||
vals, domain = {}, []
|
||||
product_obj = self.pool.get('product.product').browse(cr, uid, product, context=context)
|
||||
name = product_obj.name
|
||||
if product_obj.description_sale:
|
||||
name += '\n' + product_obj.description_sale
|
||||
vals.update({
|
||||
'price_unit': product_obj.lst_price,
|
||||
'product_uom_id': product_obj.uom_id.id,
|
||||
'website_description': product_obj and (product_obj.quote_description or product_obj.website_description) or '',
|
||||
'name': name,
|
||||
'product_uom_id': uom_id or product_obj.uom_id.id,
|
||||
})
|
||||
uom_obj = self.pool.get('product.uom')
|
||||
if vals['product_uom_id'] != product_obj.uom_id.id:
|
||||
selected_uom = uom_obj.browse(cr, uid, vals['product_uom_id'], context=context)
|
||||
new_price = uom_obj._compute_price(cr, uid, [product_obj.uom_id.id], vals['price_unit'], selected_uom)
|
||||
vals['price_unit'] = new_price
|
||||
if not uom_id:
|
||||
domain = {'product_uom_id': [('category_id', '=', product_obj.uom_id.category_id.id)]}
|
||||
return {'value': vals, 'domain': domain}
|
||||
|
||||
def product_uom_change(self, cr, uid, ids, product, uom_id, context=None):
|
||||
context = context or {}
|
||||
if not uom_id:
|
||||
return {'value': {'price_unit': 0.0, 'uom_id': False}}
|
||||
return self.on_change_product_id(cr, uid, ids, product, uom_id=uom_id, context=context)
|
||||
|
||||
def _inject_quote_description(self, cr, uid, values, context=None):
|
||||
values = dict(values or {})
|
||||
if not values.get('website_description') and values.get('product_id'):
|
||||
product = self.pool['product.product'].browse(cr, uid, values['product_id'], context=context)
|
||||
values['website_description'] = product.quote_description or product.website_description or ''
|
||||
return values
|
||||
|
||||
def create(self, cr, uid, values, context=None):
|
||||
values = self._inject_quote_description(cr, uid, values, context)
|
||||
ret = super(sale_quote_line, self).create(cr, uid, values, context=context)
|
||||
# hack because create don t make the job for a related field
|
||||
if values.get('website_description'):
|
||||
self.write(cr, uid, ret, {'website_description': values['website_description']}, context=context)
|
||||
return ret
|
||||
|
||||
def write(self, cr, uid, ids, values, context=None):
|
||||
values = self._inject_quote_description(cr, uid, values, context)
|
||||
return super(sale_quote_line, self).write(cr, uid, ids, values, context=context)
|
||||
|
||||
|
||||
class sale_order_line(osv.osv):
|
||||
_inherit = "sale.order.line"
|
||||
_description = "Sales Order Line"
|
||||
@@ -321,74 +227,6 @@ class sale_order(osv.osv):
|
||||
else:
|
||||
return 'form'
|
||||
|
||||
class sale_quote_option(osv.osv):
|
||||
_name = "sale.quote.option"
|
||||
_description = "Quotation Option"
|
||||
_columns = {
|
||||
'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=html_translate, sanitize=False),
|
||||
'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')),
|
||||
'uom_id': fields.many2one('product.uom', 'Unit of Measure ', required=True),
|
||||
'quantity': fields.float('Quantity', required=True, digits_compute= dp.get_precision('Product UoS')),
|
||||
}
|
||||
_defaults = {
|
||||
'quantity': 1,
|
||||
}
|
||||
|
||||
@api.onchange('product_id')
|
||||
def _onchange_product_id(self):
|
||||
if not self.product_id:
|
||||
return
|
||||
product = self.product_id
|
||||
self.price_unit = product.list_price
|
||||
self.website_description = product.product_tmpl_id.quote_description
|
||||
self.name = product.name
|
||||
self.uom_id = product.uom_id
|
||||
domain = {'uom_id': [('category_id', '=', self.product_id.uom_id.category_id.id)]}
|
||||
return {'domain': domain}
|
||||
|
||||
@api.onchange('uom_id')
|
||||
def _onchange_product_uom(self):
|
||||
if not self.product_id:
|
||||
return
|
||||
if not self.uom_id:
|
||||
self.price_unit = 0.0
|
||||
return
|
||||
if self.uom_id.id != self.product_id.uom_id.id:
|
||||
new_price = self.product_id.uom_id._compute_price(self.price_unit, self.uom_id)
|
||||
self.price_unit = new_price
|
||||
|
||||
def on_change_product_id(self, cr, uid, ids, product, uom_id=None, context=None):
|
||||
vals, domain = {}, []
|
||||
product_obj = self.pool.get('product.product').browse(cr, uid, product, context=context)
|
||||
name = product_obj.name
|
||||
if product_obj.description_sale:
|
||||
name += '\n' + product_obj.description_sale
|
||||
vals.update({
|
||||
'price_unit': product_obj.list_price,
|
||||
'website_description': product_obj.product_tmpl_id.quote_description,
|
||||
'name': name,
|
||||
'uom_id': uom_id or product_obj.uom_id.id,
|
||||
})
|
||||
uom_obj = self.pool.get('product.uom')
|
||||
if vals['uom_id'] != product_obj.uom_id.id:
|
||||
selected_uom = uom_obj.browse(cr, uid, vals['uom_id'], context=context)
|
||||
new_price = uom_obj._compute_price(cr, uid, [product_obj.uom_id.id],
|
||||
vals['price_unit'], selected_uom)
|
||||
vals['price_unit'] = new_price
|
||||
if not uom_id:
|
||||
domain = {'uom_id': [('category_id', '=', product_obj.uom_id.category_id.id)]}
|
||||
return {'value': vals, 'domain': domain}
|
||||
|
||||
def product_uom_change(self, cr, uid, ids, product, uom_id, context=None):
|
||||
if not uom_id:
|
||||
return {'value': {'price_unit': 0.0, 'uom_id': False}}
|
||||
return self.on_change_product_id(cr, uid, ids, product, uom_id=uom_id, context=context)
|
||||
|
||||
|
||||
class sale_order_option(osv.osv):
|
||||
_name = "sale.order.option"
|
||||
@@ -492,12 +330,3 @@ class sale_order_option(osv.osv):
|
||||
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"
|
||||
|
||||
_columns = {
|
||||
'website_description': fields.html('Description for the website', sanitize=False, translate=html_translate), # hack, if website_sale is not installed
|
||||
'quote_description': fields.html('Description for the quote', sanitize=False, translate=html_translate),
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp import api
|
||||
from openerp.osv import osv, fields
|
||||
|
||||
import openerp.addons.decimal_precision as dp
|
||||
from openerp.tools.translate import html_translate
|
||||
|
||||
|
||||
class sale_quote_template(osv.osv):
|
||||
_name = "sale.quote.template"
|
||||
_description = "Sale Quotation Template"
|
||||
_columns = {
|
||||
'name': fields.char('Quotation Template', required=True),
|
||||
'website_description': fields.html('Description', translate=html_translate, sanitize=False),
|
||||
'quote_line': fields.one2many('sale.quote.line', 'quote_id', 'Quotation Template Lines', copy=True),
|
||||
'note': fields.text('Terms and conditions'),
|
||||
'options': fields.one2many('sale.quote.option', 'template_id', 'Optional Products Lines', copy=True),
|
||||
'number_of_days': fields.integer('Quotation Duration', help='Number of days for the validity date computation of the quotation'),
|
||||
'require_payment': fields.selection([
|
||||
(0, 'Not mandatory on website quote validation'),
|
||||
(1, 'Immediate after website order validation'),
|
||||
(2, 'Immediate after website order validation and save a token'),
|
||||
], 'Payment', help="Require immediate payment by the customer when validating the order from the website quote"),
|
||||
'mail_template_id': fields.many2one('mail.template', 'Confirmation Mail', help="This e-mail template will be sent on confirmation. Leave empty to send nothing.")
|
||||
}
|
||||
def open_template(self, cr, uid, quote_id, context=None):
|
||||
return {
|
||||
'type': 'ir.actions.act_url',
|
||||
'target': 'self',
|
||||
'url': '/quote/template/%d' % quote_id[0]
|
||||
}
|
||||
|
||||
|
||||
class sale_quote_line(osv.osv):
|
||||
_name = "sale.quote.line"
|
||||
_description = "Quotation Template Lines"
|
||||
_columns = {
|
||||
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of sale quote lines."),
|
||||
'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')),
|
||||
'product_uom_qty': fields.float('Quantity', required=True, digits_compute= dp.get_precision('Product UoS')),
|
||||
'product_uom_id': fields.many2one('product.uom', 'Unit of Measure ', required=True),
|
||||
}
|
||||
_order = 'sequence, id'
|
||||
_defaults = {
|
||||
'product_uom_qty': 1,
|
||||
'discount': 0.0,
|
||||
'sequence': 10,
|
||||
}
|
||||
def on_change_product_id(self, cr, uid, ids, product, uom_id=None, context=None):
|
||||
vals, domain = {}, []
|
||||
product_obj = self.pool.get('product.product').browse(cr, uid, product, context=context)
|
||||
name = product_obj.name
|
||||
if product_obj.description_sale:
|
||||
name += '\n' + product_obj.description_sale
|
||||
vals.update({
|
||||
'price_unit': product_obj.lst_price,
|
||||
'product_uom_id': product_obj.uom_id.id,
|
||||
'website_description': product_obj and (product_obj.quote_description or product_obj.website_description) or '',
|
||||
'name': name,
|
||||
'product_uom_id': uom_id or product_obj.uom_id.id,
|
||||
})
|
||||
uom_obj = self.pool.get('product.uom')
|
||||
if vals['product_uom_id'] != product_obj.uom_id.id:
|
||||
selected_uom = uom_obj.browse(cr, uid, vals['product_uom_id'], context=context)
|
||||
new_price = uom_obj._compute_price(cr, uid, [product_obj.uom_id.id], vals['price_unit'], selected_uom)
|
||||
vals['price_unit'] = new_price
|
||||
if not uom_id:
|
||||
domain = {'product_uom_id': [('category_id', '=', product_obj.uom_id.category_id.id)]}
|
||||
return {'value': vals, 'domain': domain}
|
||||
|
||||
def product_uom_change(self, cr, uid, ids, product, uom_id, context=None):
|
||||
context = context or {}
|
||||
if not uom_id:
|
||||
return {'value': {'price_unit': 0.0, 'uom_id': False}}
|
||||
return self.on_change_product_id(cr, uid, ids, product, uom_id=uom_id, context=context)
|
||||
|
||||
def _inject_quote_description(self, cr, uid, values, context=None):
|
||||
values = dict(values or {})
|
||||
if not values.get('website_description') and values.get('product_id'):
|
||||
product = self.pool['product.product'].browse(cr, uid, values['product_id'], context=context)
|
||||
values['website_description'] = product.quote_description or product.website_description or ''
|
||||
return values
|
||||
|
||||
def create(self, cr, uid, values, context=None):
|
||||
values = self._inject_quote_description(cr, uid, values, context)
|
||||
ret = super(sale_quote_line, self).create(cr, uid, values, context=context)
|
||||
# hack because create don t make the job for a related field
|
||||
if values.get('website_description'):
|
||||
self.write(cr, uid, ret, {'website_description': values['website_description']}, context=context)
|
||||
return ret
|
||||
|
||||
def write(self, cr, uid, ids, values, context=None):
|
||||
values = self._inject_quote_description(cr, uid, values, context)
|
||||
return super(sale_quote_line, self).write(cr, uid, ids, values, context=context)
|
||||
|
||||
|
||||
class sale_quote_option(osv.osv):
|
||||
_name = "sale.quote.option"
|
||||
_description = "Quotation Option"
|
||||
_columns = {
|
||||
'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=html_translate, sanitize=False),
|
||||
'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')),
|
||||
'uom_id': fields.many2one('product.uom', 'Unit of Measure ', required=True),
|
||||
'quantity': fields.float('Quantity', required=True, digits_compute= dp.get_precision('Product UoS')),
|
||||
}
|
||||
_defaults = {
|
||||
'quantity': 1,
|
||||
}
|
||||
|
||||
@api.onchange('product_id')
|
||||
def _onchange_product_id(self):
|
||||
if not self.product_id:
|
||||
return
|
||||
product = self.product_id
|
||||
self.price_unit = product.list_price
|
||||
self.website_description = product.product_tmpl_id.quote_description
|
||||
self.name = product.name
|
||||
self.uom_id = product.uom_id
|
||||
domain = {'uom_id': [('category_id', '=', self.product_id.uom_id.category_id.id)]}
|
||||
return {'domain': domain}
|
||||
|
||||
@api.onchange('uom_id')
|
||||
def _onchange_product_uom(self):
|
||||
if not self.product_id:
|
||||
return
|
||||
if not self.uom_id:
|
||||
self.price_unit = 0.0
|
||||
return
|
||||
if self.uom_id.id != self.product_id.uom_id.id:
|
||||
new_price = self.product_id.uom_id._compute_price(self.price_unit, self.uom_id)
|
||||
self.price_unit = new_price
|
||||
|
||||
def on_change_product_id(self, cr, uid, ids, product, uom_id=None, context=None):
|
||||
vals, domain = {}, []
|
||||
product_obj = self.pool.get('product.product').browse(cr, uid, product, context=context)
|
||||
name = product_obj.name
|
||||
if product_obj.description_sale:
|
||||
name += '\n' + product_obj.description_sale
|
||||
vals.update({
|
||||
'price_unit': product_obj.list_price,
|
||||
'website_description': product_obj.product_tmpl_id.quote_description,
|
||||
'name': name,
|
||||
'uom_id': uom_id or product_obj.uom_id.id,
|
||||
})
|
||||
uom_obj = self.pool.get('product.uom')
|
||||
if vals['uom_id'] != product_obj.uom_id.id:
|
||||
selected_uom = uom_obj.browse(cr, uid, vals['uom_id'], context=context)
|
||||
new_price = uom_obj._compute_price(cr, uid, [product_obj.uom_id.id],
|
||||
vals['price_unit'], selected_uom)
|
||||
vals['price_unit'] = new_price
|
||||
if not uom_id:
|
||||
domain = {'uom_id': [('category_id', '=', product_obj.uom_id.category_id.id)]}
|
||||
return {'value': vals, 'domain': domain}
|
||||
|
||||
def product_uom_change(self, cr, uid, ids, product, uom_id, context=None):
|
||||
if not uom_id:
|
||||
return {'value': {'price_unit': 0.0, 'uom_id': False}}
|
||||
return self.on_change_product_id(cr, uid, ids, product, uom_id=uom_id, context=context)
|
||||
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0"?>
|
||||
<odoo>
|
||||
<record model="ir.ui.view" id="sale_order_form_quote">
|
||||
<field name="name">sale.order.form.payment</field>
|
||||
<field name="model">sale.order</field>
|
||||
<field name="inherit_id" ref="sale.view_order_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//header/button[@name='action_confirm'][1]" position="after">
|
||||
<button name="open_quotation" type="object"
|
||||
class="o_open_quotation" string="Preview"
|
||||
attrs="{'invisible': [('template_id', '=', False)]}"/>
|
||||
</xpath>
|
||||
<xpath expr="//page/field[@name='order_line']/.." position="after">
|
||||
<page string="Suggested Products">
|
||||
<field name="quote_viewed" invisible="1"/>
|
||||
<field name="options">
|
||||
<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>
|
||||
</page>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='partner_shipping_id']" position="after">
|
||||
<label for="template_id"/>
|
||||
<div>
|
||||
<field name="template_id" context="{'company_id': company_id}"
|
||||
on_change="onchange_template_id(template_id, partner_id, fiscal_position_id, pricelist_id)"
|
||||
options="{'no_create': True, 'no_open': True}"/>
|
||||
</div>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='client_order_ref']" position="after">
|
||||
<field name="require_payment" widget="radio"/>
|
||||
<field name="website_description" invisible="1"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="sale.action_quotations" model="ir.actions.act_window">
|
||||
<field name="help" type="html">
|
||||
<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
|
||||
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
|
||||
from the Quotations list to the Sales Order list.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
-58
@@ -1,50 +1,6 @@
|
||||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record model="ir.ui.view" id="sale_order_form_quote">
|
||||
<field name="name">sale.order.form.payment</field>
|
||||
<field name="model">sale.order</field>
|
||||
<field name="inherit_id" ref="sale.view_order_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//header/button[@name='action_confirm'][1]" position="after">
|
||||
<button name="open_quotation" type="object"
|
||||
class="o_open_quotation" string="Preview"
|
||||
attrs="{'invisible': [('template_id', '=', False)]}"/>
|
||||
</xpath>
|
||||
<xpath expr="//page/field[@name='order_line']/.." position="after">
|
||||
<page string="Suggested Products">
|
||||
<field name="quote_viewed" invisible="1"/>
|
||||
<field name="options">
|
||||
<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>
|
||||
</page>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='partner_shipping_id']" position="after">
|
||||
<label for="template_id"/>
|
||||
<div>
|
||||
<field name="template_id" context="{'company_id': company_id}"
|
||||
on_change="onchange_template_id(template_id, partner_id, fiscal_position_id, pricelist_id)"
|
||||
options="{'no_create': True, 'no_open': True}"/>
|
||||
</div>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='client_order_ref']" position="after">
|
||||
<field name="require_payment" widget="radio"/>
|
||||
<field name="website_description" invisible="1"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_sale_quote_template_form">
|
||||
<field name="name">sale.quote.template.form</field>
|
||||
<field name="model">sale.quote.template</field>
|
||||
@@ -176,20 +132,6 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="sale.action_quotations" model="ir.actions.act_window">
|
||||
<field name="help" type="html">
|
||||
<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
|
||||
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
|
||||
from the Quotations list to the Sales Order list.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="action_sale_quotation_template" id="menu_sale_quote_template" parent="sales_team.menu_sales_config" sequence="1" name="Quotation Templates" groups="sales_team.group_sale_salesman,sales_team.group_sale_manager"/>
|
||||
</data>
|
||||
</openerp>
|
||||
Reference in New Issue
Block a user