[IMP] "website_sale" compatible for multi website
This commit is contained in:
parent
d00801d466
commit
23e5ea0865
@ -12,8 +12,10 @@ from flectra.http import request
|
|||||||
class WebsiteSaleBackend(WebsiteBackend):
|
class WebsiteSaleBackend(WebsiteBackend):
|
||||||
|
|
||||||
@http.route()
|
@http.route()
|
||||||
def fetch_dashboard_data(self, date_from, date_to):
|
def fetch_dashboard_data(self, date_from, date_to, website_id=None):
|
||||||
results = super(WebsiteSaleBackend, self).fetch_dashboard_data(date_from, date_to)
|
if not website_id:
|
||||||
|
website_id = request.website.id
|
||||||
|
results = super(WebsiteSaleBackend, self).fetch_dashboard_data(date_from, date_to, website_id)
|
||||||
|
|
||||||
sales_values = dict(
|
sales_values = dict(
|
||||||
graph=[],
|
graph=[],
|
||||||
@ -44,6 +46,7 @@ class WebsiteSaleBackend(WebsiteBackend):
|
|||||||
('team_id.team_type', '=', 'website'),
|
('team_id.team_type', '=', 'website'),
|
||||||
('state', 'in', ['sale', 'done']),
|
('state', 'in', ['sale', 'done']),
|
||||||
('date', '>=', date_from),
|
('date', '>=', date_from),
|
||||||
|
('website_id.id', '=', website_id),
|
||||||
('date', '<=', date_to)],
|
('date', '<=', date_to)],
|
||||||
fields=['product_id', 'product_uom_qty', 'price_subtotal'],
|
fields=['product_id', 'product_uom_qty', 'price_subtotal'],
|
||||||
groupby='product_id', orderby='product_uom_qty desc', limit=5)
|
groupby='product_id', orderby='product_uom_qty desc', limit=5)
|
||||||
@ -60,7 +63,8 @@ class WebsiteSaleBackend(WebsiteBackend):
|
|||||||
sale_order_domain = [
|
sale_order_domain = [
|
||||||
('team_id', 'in', request.env['crm.team'].search([('team_type', '=', 'website')]).ids),
|
('team_id', 'in', request.env['crm.team'].search([('team_type', '=', 'website')]).ids),
|
||||||
('date_order', '>=', fields.Datetime.to_string(datetime_from)),
|
('date_order', '>=', fields.Datetime.to_string(datetime_from)),
|
||||||
('date_order', '<=', fields.Datetime.to_string(datetime_to))]
|
('date_order', '<=', fields.Datetime.to_string(datetime_to)),
|
||||||
|
('website_id', '=', website_id)]
|
||||||
so_group_data = request.env['sale.order'].read_group(sale_order_domain, fields=['state'], groupby='state')
|
so_group_data = request.env['sale.order'].read_group(sale_order_domain, fields=['state'], groupby='state')
|
||||||
for res in so_group_data:
|
for res in so_group_data:
|
||||||
if res.get('state') == 'sent':
|
if res.get('state') == 'sent':
|
||||||
@ -74,7 +78,8 @@ class WebsiteSaleBackend(WebsiteBackend):
|
|||||||
('team_id.team_type', '=', 'website'),
|
('team_id.team_type', '=', 'website'),
|
||||||
('state', 'in', ['sale', 'done']),
|
('state', 'in', ['sale', 'done']),
|
||||||
('date', '>=', date_from),
|
('date', '>=', date_from),
|
||||||
('date', '<=', date_to)],
|
('date', '<=', date_to),
|
||||||
|
('website_id.id', '=', website_id)],
|
||||||
fields=['team_id', 'price_subtotal'],
|
fields=['team_id', 'price_subtotal'],
|
||||||
groupby=['team_id'],
|
groupby=['team_id'],
|
||||||
)
|
)
|
||||||
@ -114,7 +119,8 @@ class WebsiteSaleBackend(WebsiteBackend):
|
|||||||
('team_id.team_type', '=', 'website'),
|
('team_id.team_type', '=', 'website'),
|
||||||
('state', 'in', ['sale', 'done']),
|
('state', 'in', ['sale', 'done']),
|
||||||
('date', '>=', date_from),
|
('date', '>=', date_from),
|
||||||
('date', '<=', date_to)
|
('date', '<=', date_to),
|
||||||
|
('website_id.id', '=', website_id)
|
||||||
]
|
]
|
||||||
sales_values['graph'] += [{
|
sales_values['graph'] += [{
|
||||||
'values': self._compute_sale_graph(date_date_from, date_date_to, sales_domain),
|
'values': self._compute_sale_graph(date_date_from, date_date_to, sales_domain),
|
||||||
|
@ -135,7 +135,7 @@ class WebsiteSale(http.Controller):
|
|||||||
def get_attribute_value_ids(self, product):
|
def get_attribute_value_ids(self, product):
|
||||||
""" list of selectable attributes of a product
|
""" list of selectable attributes of a product
|
||||||
|
|
||||||
:return: list of product variant description
|
:return: list of product variant description as requested website
|
||||||
(variant id, [visible attribute ids], variant price, variant sale price)
|
(variant id, [visible attribute ids], variant price, variant sale price)
|
||||||
"""
|
"""
|
||||||
# product attributes with at least two choices
|
# product attributes with at least two choices
|
||||||
@ -185,6 +185,8 @@ class WebsiteSale(http.Controller):
|
|||||||
ids = [value[1]]
|
ids = [value[1]]
|
||||||
if attrib:
|
if attrib:
|
||||||
domain += [('attribute_line_ids.value_ids', 'in', ids)]
|
domain += [('attribute_line_ids.value_ids', 'in', ids)]
|
||||||
|
if not request.env.user.has_group('website.group_website_publisher'):
|
||||||
|
domain += [('website_ids', 'in', request.website.id)]
|
||||||
|
|
||||||
return domain
|
return domain
|
||||||
|
|
||||||
@ -222,11 +224,16 @@ class WebsiteSale(http.Controller):
|
|||||||
post["search"] = search
|
post["search"] = search
|
||||||
if category:
|
if category:
|
||||||
category = request.env['product.public.category'].browse(int(category))
|
category = request.env['product.public.category'].browse(int(category))
|
||||||
|
website = []
|
||||||
|
for web in category.website_ids:
|
||||||
|
website.append(web.id)
|
||||||
|
if request.website.id not in website:
|
||||||
|
return request.render('website.404')
|
||||||
url = "/shop/category/%s" % slug(category)
|
url = "/shop/category/%s" % slug(category)
|
||||||
if attrib_list:
|
if attrib_list:
|
||||||
post['attrib'] = attrib_list
|
post['attrib'] = attrib_list
|
||||||
|
|
||||||
categs = request.env['product.public.category'].search([('parent_id', '=', False)])
|
categs = request.env['product.public.category'].search([('parent_id', '=', False), ('website_ids', 'in', request.website.id)])
|
||||||
Product = request.env['product.template']
|
Product = request.env['product.template']
|
||||||
|
|
||||||
parent_category_ids = []
|
parent_category_ids = []
|
||||||
@ -315,7 +322,7 @@ class WebsiteSale(http.Controller):
|
|||||||
|
|
||||||
@http.route(['/shop/change_pricelist/<model("product.pricelist"):pl_id>'], type='http', auth="public", website=True)
|
@http.route(['/shop/change_pricelist/<model("product.pricelist"):pl_id>'], type='http', auth="public", website=True)
|
||||||
def pricelist_change(self, pl_id, **post):
|
def pricelist_change(self, pl_id, **post):
|
||||||
if (pl_id.selectable or pl_id == request.env.user.partner_id.property_product_pricelist) \
|
if (pl_id.website_id or pl_id == request.env.user.partner_id.property_product_pricelist) \
|
||||||
and request.website.is_pricelist_available(pl_id.id):
|
and request.website.is_pricelist_available(pl_id.id):
|
||||||
request.session['website_sale_current_pl'] = pl_id.id
|
request.session['website_sale_current_pl'] = pl_id.id
|
||||||
request.website.sale_get_order(force_pricelist=pl_id.id)
|
request.website.sale_get_order(force_pricelist=pl_id.id)
|
||||||
|
279
addons/website_sale/controllers/portal.py
Normal file
279
addons/website_sale/controllers/portal.py
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Part of Flectra. See LICENSE file for full copyright and licensing details.
|
||||||
|
from flectra import http
|
||||||
|
from flectra.http import request
|
||||||
|
from flectra import tools, _
|
||||||
|
from flectra.exceptions import AccessError
|
||||||
|
from flectra.addons.sale.controllers.portal import CustomerPortal
|
||||||
|
from flectra.addons.account.controllers.portal import PortalAccount
|
||||||
|
|
||||||
|
|
||||||
|
class SaleCustomerPortal(CustomerPortal):
|
||||||
|
|
||||||
|
def _prepare_portal_layout_values(self):
|
||||||
|
values = super(SaleCustomerPortal, self)._prepare_portal_layout_values()
|
||||||
|
partner = request.env.user.partner_id
|
||||||
|
|
||||||
|
SaleOrder = request.env['sale.order']
|
||||||
|
quotation_count = SaleOrder.search_count([
|
||||||
|
('message_partner_ids', 'child_of',
|
||||||
|
[partner.commercial_partner_id.id]),
|
||||||
|
('state', 'in', ['sent', 'cancel']),
|
||||||
|
('website_id', '=', request.website.id),
|
||||||
|
])
|
||||||
|
order_count = SaleOrder.search_count([
|
||||||
|
('message_partner_ids', 'child_of',
|
||||||
|
[partner.commercial_partner_id.id]),
|
||||||
|
('state', 'in', ['sale', 'done']),
|
||||||
|
('website_id', '=', request.website.id),
|
||||||
|
])
|
||||||
|
|
||||||
|
values.update({
|
||||||
|
'quotation_count': quotation_count,
|
||||||
|
'order_count': order_count,
|
||||||
|
})
|
||||||
|
return values
|
||||||
|
|
||||||
|
@http.route(['/my/quotes', '/my/quotes/page/<int:page>'], type='http',
|
||||||
|
auth="user", website=True)
|
||||||
|
def portal_my_quotes(self, page=1, date_begin=None, date_end=None,
|
||||||
|
sortby=None, **kw):
|
||||||
|
values = self._prepare_portal_layout_values()
|
||||||
|
partner = request.env.user.partner_id
|
||||||
|
SaleOrder = request.env['sale.order']
|
||||||
|
|
||||||
|
domain = [
|
||||||
|
('message_partner_ids', 'child_of',
|
||||||
|
[partner.commercial_partner_id.id]),
|
||||||
|
('state', 'in', ['sent', 'cancel']),
|
||||||
|
('website_id', '=', request.website.id),
|
||||||
|
]
|
||||||
|
|
||||||
|
searchbar_sortings = {
|
||||||
|
'date': {'label': _('Order Date'), 'order': 'date_order desc'},
|
||||||
|
'name': {'label': _('Reference'), 'order': 'name'},
|
||||||
|
'stage': {'label': _('Stage'), 'order': 'state'},
|
||||||
|
}
|
||||||
|
|
||||||
|
# default sortby order
|
||||||
|
if not sortby:
|
||||||
|
sortby = 'date'
|
||||||
|
sort_order = searchbar_sortings[sortby]['order']
|
||||||
|
|
||||||
|
archive_groups = self._get_archive_groups('sale.order', domain)
|
||||||
|
if date_begin and date_end:
|
||||||
|
domain += [('create_date', '>', date_begin),
|
||||||
|
('create_date', '<=', date_end)]
|
||||||
|
|
||||||
|
# count for pager
|
||||||
|
quotation_count = SaleOrder.search_count(domain)
|
||||||
|
# make pager
|
||||||
|
pager = request.website.pager(
|
||||||
|
url="/my/quotes",
|
||||||
|
url_args={'date_begin': date_begin, 'date_end': date_end,
|
||||||
|
'sortby': sortby},
|
||||||
|
total=quotation_count,
|
||||||
|
page=page,
|
||||||
|
step=self._items_per_page
|
||||||
|
)
|
||||||
|
# search the count to display, according to the pager data
|
||||||
|
quotations = SaleOrder.search(domain, order=sort_order,
|
||||||
|
limit=self._items_per_page,
|
||||||
|
offset=pager['offset'])
|
||||||
|
request.session['my_quotes_history'] = quotations.ids[:100]
|
||||||
|
values.update({
|
||||||
|
'date': date_begin,
|
||||||
|
'quotations': quotations.sudo(),
|
||||||
|
'page_name': 'quote',
|
||||||
|
'pager': pager,
|
||||||
|
'archive_groups': archive_groups,
|
||||||
|
'default_url': '/my/quotes',
|
||||||
|
'searchbar_sortings': searchbar_sortings,
|
||||||
|
'sortby': sortby,
|
||||||
|
})
|
||||||
|
return request.render("sale.portal_my_quotations",
|
||||||
|
values)
|
||||||
|
|
||||||
|
@http.route(['/my/orders', '/my/orders/page/<int:page>'], type='http',
|
||||||
|
auth="user", website=True)
|
||||||
|
def portal_my_orders(self, page=1, date_begin=None, date_end=None,
|
||||||
|
sortby=None, **kw):
|
||||||
|
values = self._prepare_portal_layout_values()
|
||||||
|
partner = request.env.user.partner_id
|
||||||
|
SaleOrder = request.env['sale.order']
|
||||||
|
|
||||||
|
domain = [
|
||||||
|
('message_partner_ids', 'child_of',
|
||||||
|
[partner.commercial_partner_id.id]),
|
||||||
|
('state', 'in', ['sale', 'done']),
|
||||||
|
('website_id', '=', request.website.id),
|
||||||
|
]
|
||||||
|
|
||||||
|
searchbar_sortings = {
|
||||||
|
'date': {'label': _('Order Date'), 'order': 'date_order desc'},
|
||||||
|
'name': {'label': _('Reference'), 'order': 'name'},
|
||||||
|
'stage': {'label': _('Stage'), 'order': 'state'},
|
||||||
|
}
|
||||||
|
# default sortby order
|
||||||
|
if not sortby:
|
||||||
|
sortby = 'date'
|
||||||
|
sort_order = searchbar_sortings[sortby]['order']
|
||||||
|
|
||||||
|
archive_groups = self._get_archive_groups('sale.order', domain)
|
||||||
|
if date_begin and date_end:
|
||||||
|
domain += [('create_date', '>', date_begin),
|
||||||
|
('create_date', '<=', date_end)]
|
||||||
|
|
||||||
|
# count for pager
|
||||||
|
order_count = SaleOrder.search_count(domain)
|
||||||
|
# pager
|
||||||
|
pager = request.website.pager(
|
||||||
|
url="/my/orders",
|
||||||
|
url_args={'date_begin': date_begin, 'date_end': date_end,
|
||||||
|
'sortby': sortby},
|
||||||
|
total=order_count,
|
||||||
|
page=page,
|
||||||
|
step=self._items_per_page
|
||||||
|
)
|
||||||
|
# content according to pager and archive selected
|
||||||
|
orders = SaleOrder.search(domain, order=sort_order,
|
||||||
|
limit=self._items_per_page,
|
||||||
|
offset=pager['offset'])
|
||||||
|
request.session['my_orders_history'] = orders.ids[:100]
|
||||||
|
|
||||||
|
values.update({
|
||||||
|
'date': date_begin,
|
||||||
|
'orders': orders.sudo(),
|
||||||
|
'page_name': 'order',
|
||||||
|
'pager': pager,
|
||||||
|
'archive_groups': archive_groups,
|
||||||
|
'default_url': '/my/orders',
|
||||||
|
'searchbar_sortings': searchbar_sortings,
|
||||||
|
'sortby': sortby,
|
||||||
|
})
|
||||||
|
return request.render("sale.portal_my_orders", values)
|
||||||
|
|
||||||
|
@http.route()
|
||||||
|
def portal_order_page(self, order=None, access_token=None, **kw):
|
||||||
|
order = request.env['sale.order'].browse([order])
|
||||||
|
try:
|
||||||
|
if order.website_id != request.website:
|
||||||
|
raise AccessError('Invalid Order !!')
|
||||||
|
except AccessError:
|
||||||
|
return request.render("website.403")
|
||||||
|
|
||||||
|
return super(SaleCustomerPortal, self).portal_order_page(order.id,
|
||||||
|
access_token, **kw)
|
||||||
|
|
||||||
|
@http.route()
|
||||||
|
def portal_order_report(self, order_id, access_token=None, **kw):
|
||||||
|
order = request.env['sale.order'].browse([order_id])
|
||||||
|
try:
|
||||||
|
if order.website_id != request.website:
|
||||||
|
raise AccessError('Invalid Order !!')
|
||||||
|
except AccessError:
|
||||||
|
return request.render("website.403")
|
||||||
|
|
||||||
|
return super(SaleCustomerPortal, self).portal_order_report(order_id,
|
||||||
|
access_token,
|
||||||
|
**kw)
|
||||||
|
|
||||||
|
|
||||||
|
class AccountCustomerPortal(PortalAccount):
|
||||||
|
|
||||||
|
def _prepare_portal_layout_values(self):
|
||||||
|
values = super(AccountCustomerPortal, self)._prepare_portal_layout_values()
|
||||||
|
partner = request.env.user.partner_id
|
||||||
|
|
||||||
|
invoice_count = request.env['account.invoice'].search_count([
|
||||||
|
('type', 'in', ['out_invoice', 'out_refund']),
|
||||||
|
('message_partner_ids', 'child_of',
|
||||||
|
[partner.commercial_partner_id.id]),
|
||||||
|
('state', 'in', ['open', 'paid', 'cancel']),
|
||||||
|
('website_id', '=', request.website.id),
|
||||||
|
])
|
||||||
|
|
||||||
|
values['invoice_count'] = invoice_count
|
||||||
|
return values
|
||||||
|
|
||||||
|
@http.route()
|
||||||
|
def portal_my_invoices(self, page=1, date_begin=None, date_end=None,
|
||||||
|
sortby=None, **kw):
|
||||||
|
values = self._prepare_portal_layout_values()
|
||||||
|
partner = request.env.user.partner_id
|
||||||
|
AccountInvoice = request.env['account.invoice']
|
||||||
|
|
||||||
|
domain = [
|
||||||
|
('type', 'in', ['out_invoice', 'out_refund']),
|
||||||
|
('message_partner_ids', 'child_of',
|
||||||
|
[partner.commercial_partner_id.id]),
|
||||||
|
('state', 'in', ['open', 'paid', 'cancelled']),
|
||||||
|
('website_id', '=', request.website.id),
|
||||||
|
]
|
||||||
|
|
||||||
|
searchbar_sortings = {
|
||||||
|
'date': {'label': _('Invoice Date'), 'order': 'date_invoice desc'},
|
||||||
|
'duedate': {'label': _('Due Date'), 'order': 'date_due desc'},
|
||||||
|
'name': {'label': _('Reference'), 'order': 'name desc'},
|
||||||
|
'state': {'label': _('Status'), 'order': 'state'},
|
||||||
|
}
|
||||||
|
# default sort by order
|
||||||
|
if not sortby:
|
||||||
|
sortby = 'date'
|
||||||
|
order = searchbar_sortings[sortby]['order']
|
||||||
|
|
||||||
|
archive_groups = self._get_archive_groups('account.invoice', domain)
|
||||||
|
if date_begin and date_end:
|
||||||
|
domain += [('create_date', '>', date_begin),
|
||||||
|
('create_date', '<=', date_end)]
|
||||||
|
|
||||||
|
# count for pager
|
||||||
|
invoice_count = AccountInvoice.search_count(domain)
|
||||||
|
# pager
|
||||||
|
pager = request.website.pager(
|
||||||
|
url="/my/invoices",
|
||||||
|
url_args={'date_begin': date_begin,
|
||||||
|
'date_end': date_end,
|
||||||
|
'sortby': sortby},
|
||||||
|
total=invoice_count,
|
||||||
|
page=page,
|
||||||
|
step=self._items_per_page
|
||||||
|
)
|
||||||
|
# content according to pager and archive selected
|
||||||
|
invoices = AccountInvoice.search(domain, order=order,
|
||||||
|
limit=self._items_per_page,
|
||||||
|
offset=pager['offset'])
|
||||||
|
values.update({
|
||||||
|
'date': date_begin,
|
||||||
|
'invoices': invoices,
|
||||||
|
'page_name': 'invoice',
|
||||||
|
'pager': pager,
|
||||||
|
'archive_groups': archive_groups,
|
||||||
|
'default_url': '/my/invoices',
|
||||||
|
'searchbar_sortings': searchbar_sortings,
|
||||||
|
'sortby': sortby,
|
||||||
|
})
|
||||||
|
return request.render("account.portal_my_invoices", values)
|
||||||
|
|
||||||
|
@http.route()
|
||||||
|
def portal_my_invoice_detail(self, invoice_id, access_token=None, **kw):
|
||||||
|
invoice = request.env['account.invoice'].browse(invoice_id)
|
||||||
|
try:
|
||||||
|
if invoice.website_id != request.website:
|
||||||
|
raise AccessError('Invalid Invoice !!')
|
||||||
|
except AccessError:
|
||||||
|
return request.render("website.403")
|
||||||
|
|
||||||
|
return super(PortalAccount, self).portal_my_invoice_detail(invoice_id, access_token,**kw)
|
||||||
|
|
||||||
|
@http.route()
|
||||||
|
def portal_my_invoice_report(self, invoice_id, **kw):
|
||||||
|
invoice = request.env['account.invoice'].browse(invoice_id)
|
||||||
|
try:
|
||||||
|
if invoice.website_id != request.website:
|
||||||
|
raise AccessError('Invalid Invoice !!')
|
||||||
|
except AccessError:
|
||||||
|
return request.render("website.403")
|
||||||
|
|
||||||
|
return super(PortalAccount, self).portal_my_invoices_report(invoice_id,
|
||||||
|
**kw)
|
@ -38,10 +38,6 @@
|
|||||||
<field name="salesteam_id" ref="sales_team.salesteam_website_sales"/>
|
<field name="salesteam_id" ref="sales_team.salesteam_website_sales"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="product.pricelist" id="product.list0">
|
|
||||||
<field name="selectable" eval="False" />
|
|
||||||
<field name="website_id" ref="website.default_website" />
|
|
||||||
</record>
|
|
||||||
</data>
|
</data>
|
||||||
<data>
|
<data>
|
||||||
<record id="sale.model_sale_order" model="ir.model">
|
<record id="sale.model_sale_order" model="ir.model">
|
||||||
|
@ -713,8 +713,7 @@ Weight: 31 grams</field>
|
|||||||
|
|
||||||
<record model="product.pricelist" id="product.list0">
|
<record model="product.pricelist" id="product.list0">
|
||||||
<field name="name">USD</field>
|
<field name="name">USD</field>
|
||||||
<field name="selectable" eval="True" />
|
<!--<field name="website_id" eval="[(6, 0, [ref('website.default_website').id])]"/>-->
|
||||||
<field name="website_id" ref="website.default_website" />
|
|
||||||
<field name="sequence">3</field>
|
<field name="sequence">3</field>
|
||||||
<field name="currency_id" ref="base.USD"/>
|
<field name="currency_id" ref="base.USD"/>
|
||||||
</record>
|
</record>
|
||||||
@ -727,8 +726,7 @@ Weight: 31 grams</field>
|
|||||||
|
|
||||||
<record id="list_christmas" model="product.pricelist">
|
<record id="list_christmas" model="product.pricelist">
|
||||||
<field name="name">Christmas</field>
|
<field name="name">Christmas</field>
|
||||||
<field name="selectable" eval="False" />
|
<!--<field name="website_id" eval="[(6, 0, [ref('website.default_website').id])]"/>-->
|
||||||
<field name="website_id" ref="website.default_website" />
|
|
||||||
<field name="country_group_ids" eval="[(6,0,[ref('base.europe')])]" />
|
<field name="country_group_ids" eval="[(6,0,[ref('base.europe')])]" />
|
||||||
<field name="sequence">20</field>
|
<field name="sequence">20</field>
|
||||||
</record>
|
</record>
|
||||||
@ -741,8 +739,7 @@ Weight: 31 grams</field>
|
|||||||
|
|
||||||
<record id="list_benelux" model="product.pricelist">
|
<record id="list_benelux" model="product.pricelist">
|
||||||
<field name="name">Benelux</field>
|
<field name="name">Benelux</field>
|
||||||
<field name="selectable" eval="False" />
|
<!--<field name="website_id" eval="[(6, 0, [ref('website.default_website').id])]"/>-->
|
||||||
<field name="website_id" ref="website.default_website" />
|
|
||||||
<field name="country_group_ids" eval="[(6,0,[ref('benelux')])]" />
|
<field name="country_group_ids" eval="[(6,0,[ref('benelux')])]" />
|
||||||
<field name="sequence">2</field>
|
<field name="sequence">2</field>
|
||||||
</record>
|
</record>
|
||||||
@ -757,8 +754,7 @@ Weight: 31 grams</field>
|
|||||||
|
|
||||||
<record id="list_europe" model="product.pricelist">
|
<record id="list_europe" model="product.pricelist">
|
||||||
<field name="name">EUR</field>
|
<field name="name">EUR</field>
|
||||||
<field name="selectable" eval="True" />
|
<!--<field name="website_id" eval="[(6, 0, [ref('website.default_website').id])]"/>-->
|
||||||
<field name="website_id" ref="website.default_website" />
|
|
||||||
<field name="country_group_ids" eval="[(6,0,[ref('base.europe')])]" />
|
<field name="country_group_ids" eval="[(6,0,[ref('base.europe')])]" />
|
||||||
<field name="sequence">3</field>
|
<field name="sequence">3</field>
|
||||||
<field name="currency_id" ref="base.EUR"/>
|
<field name="currency_id" ref="base.EUR"/>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
|
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
|
||||||
|
|
||||||
|
from . import account_invoice
|
||||||
from . import crm_team
|
from . import crm_team
|
||||||
from . import ir_http
|
from . import ir_http
|
||||||
from . import mail_compose_message
|
from . import mail_compose_message
|
||||||
@ -8,6 +9,7 @@ from . import product
|
|||||||
from . import res_country
|
from . import res_country
|
||||||
from . import res_partner
|
from . import res_partner
|
||||||
from . import sale_order
|
from . import sale_order
|
||||||
|
from . import sale_report
|
||||||
from . import ir_model_fields
|
from . import ir_model_fields
|
||||||
from . import website
|
from . import website
|
||||||
from . import res_config_settings
|
from . import res_config_settings
|
||||||
|
24
addons/website_sale/models/account_invoice.py
Normal file
24
addons/website_sale/models/account_invoice.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Part of Flectra. See LICENSE file for full copyright and licensing details.
|
||||||
|
|
||||||
|
from flectra import api, fields, models, _
|
||||||
|
|
||||||
|
|
||||||
|
class AccountInvoice(models.Model):
|
||||||
|
_inherit = 'account.invoice'
|
||||||
|
|
||||||
|
website_id = fields.Many2one('website', string="Website")
|
||||||
|
|
||||||
|
|
||||||
|
class SaleAdvancePaymentInv(models.TransientModel):
|
||||||
|
_inherit = "sale.advance.payment.inv"
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def _create_invoice(self, order, so_line, amount):
|
||||||
|
res = super(SaleAdvancePaymentInv, self)._create_invoice(order,
|
||||||
|
so_line,
|
||||||
|
amount)
|
||||||
|
|
||||||
|
res.website_id = order.website_id
|
||||||
|
|
||||||
|
return res
|
@ -15,15 +15,23 @@ class ProductStyle(models.Model):
|
|||||||
html_class = fields.Char(string='HTML Classes')
|
html_class = fields.Char(string='HTML Classes')
|
||||||
|
|
||||||
|
|
||||||
|
class WebsitePriceList(models.Model):
|
||||||
|
_name = "website.product.pricelist"
|
||||||
|
|
||||||
|
pricelist_id = fields.Many2one('product.pricelist',
|
||||||
|
string='Website Pricelist')
|
||||||
|
website_id = fields.Many2one('website', string='Website')
|
||||||
|
selectable = fields.Boolean(string="selectable", default=True)
|
||||||
|
|
||||||
|
|
||||||
class ProductPricelist(models.Model):
|
class ProductPricelist(models.Model):
|
||||||
_inherit = "product.pricelist"
|
_inherit = "product.pricelist"
|
||||||
|
|
||||||
def _default_website(self):
|
def _default_website(self):
|
||||||
return self.env['website'].search([], limit=1)
|
return self.env['website'].search([], limit=1)
|
||||||
|
|
||||||
website_id = fields.Many2one('website', string="website", default=_default_website)
|
website_id = fields.One2many('website.product.pricelist', 'pricelist_id', string='Website')
|
||||||
code = fields.Char(string='E-commerce Promotional Code', groups="base.group_user")
|
code = fields.Char(string='E-commerce Promotional Code', groups="base.group_user")
|
||||||
selectable = fields.Boolean(help="Allow the end user to choose this price list")
|
|
||||||
|
|
||||||
def clear_cache(self):
|
def clear_cache(self):
|
||||||
# website._get_pl() is cached to avoid to recompute at each request the
|
# website._get_pl() is cached to avoid to recompute at each request the
|
||||||
@ -75,16 +83,40 @@ class ProductPublicCategory(models.Model):
|
|||||||
help="Small-sized image of the category. It is automatically "
|
help="Small-sized image of the category. It is automatically "
|
||||||
"resized as a 64x64px image, with aspect ratio preserved. "
|
"resized as a 64x64px image, with aspect ratio preserved. "
|
||||||
"Use this field anywhere a small image is required.")
|
"Use this field anywhere a small image is required.")
|
||||||
|
website_ids = fields.Many2many('website', 'website_prod_public_categ_rel',
|
||||||
|
'website_id', 'category_id',
|
||||||
|
string='Websites', copy=False,
|
||||||
|
help='List of websites in which '
|
||||||
|
'category is published.')
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def create(self, vals):
|
def create(self, vals):
|
||||||
tools.image_resize_images(vals)
|
tools.image_resize_images(vals)
|
||||||
return super(ProductPublicCategory, self).create(vals)
|
res = super(ProductPublicCategory, self).create(vals)
|
||||||
|
# @todo Check different test-case: child & parent category
|
||||||
|
if res.parent_id:
|
||||||
|
res.parent_id.write({
|
||||||
|
'website_ids': [(4, website_id.id) for website_id in res.website_ids]
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def write(self, vals):
|
def write(self, vals):
|
||||||
tools.image_resize_images(vals)
|
tools.image_resize_images(vals)
|
||||||
return super(ProductPublicCategory, self).write(vals)
|
res = super(ProductPublicCategory, self).write(vals)
|
||||||
|
# @todo Check different test-case: child & parent category
|
||||||
|
if self.parent_id and self.website_ids.ids:
|
||||||
|
self.parent_id.write({
|
||||||
|
'website_ids': [(4, website_id.id) for website_id in self.website_ids]
|
||||||
|
})
|
||||||
|
if self.child_id:
|
||||||
|
for child_id in self.child_id:
|
||||||
|
for website_id in child_id.website_ids:
|
||||||
|
if website_id not in self.website_ids:
|
||||||
|
child_id.write({
|
||||||
|
'website_ids': [(3, website_id.id)]
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
|
||||||
@api.constrains('parent_id')
|
@api.constrains('parent_id')
|
||||||
def check_parent_id(self):
|
def check_parent_id(self):
|
||||||
@ -132,6 +164,11 @@ class ProductTemplate(models.Model):
|
|||||||
website_price = fields.Float('Website price', compute='_website_price', digits=dp.get_precision('Product Price'))
|
website_price = fields.Float('Website price', compute='_website_price', digits=dp.get_precision('Product Price'))
|
||||||
website_public_price = fields.Float('Website public price', compute='_website_price', digits=dp.get_precision('Product Price'))
|
website_public_price = fields.Float('Website public price', compute='_website_price', digits=dp.get_precision('Product Price'))
|
||||||
website_price_difference = fields.Boolean('Website price difference', compute='_website_price')
|
website_price_difference = fields.Boolean('Website price difference', compute='_website_price')
|
||||||
|
website_ids = fields.Many2many('website', 'website_prod_pub_rel',
|
||||||
|
'website_id', 'product_id',
|
||||||
|
string='Websites', copy=False,
|
||||||
|
help='List of websites in which '
|
||||||
|
'Product is published.')
|
||||||
|
|
||||||
def _website_price(self):
|
def _website_price(self):
|
||||||
# First filter out the ones that have no variant:
|
# First filter out the ones that have no variant:
|
||||||
@ -180,6 +217,11 @@ class ProductTemplate(models.Model):
|
|||||||
class Product(models.Model):
|
class Product(models.Model):
|
||||||
_inherit = "product.product"
|
_inherit = "product.product"
|
||||||
|
|
||||||
|
def _get_default_website_ids(self):
|
||||||
|
default_website_id = self.env.ref('website.default_website')
|
||||||
|
return [default_website_id.id] if default_website_id else None
|
||||||
|
|
||||||
|
website_ids = fields.Many2many('website', string="Publish Product On Website", default=_get_default_website_ids)
|
||||||
website_price = fields.Float('Website price', compute='_website_price', digits=dp.get_precision('Product Price'))
|
website_price = fields.Float('Website price', compute='_website_price', digits=dp.get_precision('Product Price'))
|
||||||
website_public_price = fields.Float('Website public price', compute='_website_price', digits=dp.get_precision('Product Price'))
|
website_public_price = fields.Float('Website public price', compute='_website_price', digits=dp.get_precision('Product Price'))
|
||||||
website_price_difference = fields.Boolean('Website price difference', compute='_website_price')
|
website_price_difference = fields.Boolean('Website price difference', compute='_website_price')
|
||||||
|
@ -21,6 +21,8 @@ class SaleOrder(models.Model):
|
|||||||
string='Order Lines displayed on Website', readonly=True,
|
string='Order Lines displayed on Website', readonly=True,
|
||||||
help='Order Lines to be displayed on the website. They should not be used for computation purpose.',
|
help='Order Lines to be displayed on the website. They should not be used for computation purpose.',
|
||||||
)
|
)
|
||||||
|
website_id = fields.Many2one('website', string='Website',
|
||||||
|
help='Website reference for quotation/order.')
|
||||||
cart_quantity = fields.Integer(compute='_compute_cart_info', string='Cart Quantity')
|
cart_quantity = fields.Integer(compute='_compute_cart_info', string='Cart Quantity')
|
||||||
only_services = fields.Boolean(compute='_compute_cart_info', string='Only Services')
|
only_services = fields.Boolean(compute='_compute_cart_info', string='Only Services')
|
||||||
can_directly_mark_as_paid = fields.Boolean(compute='_compute_can_directly_mark_as_paid',
|
can_directly_mark_as_paid = fields.Boolean(compute='_compute_can_directly_mark_as_paid',
|
||||||
@ -256,3 +258,9 @@ class SaleOrder(models.Model):
|
|||||||
self.payment_tx_id.state = 'done'
|
self.payment_tx_id.state = 'done'
|
||||||
else:
|
else:
|
||||||
raise ValidationError(_("The quote should be sent and the payment acquirer type should be manual or wire transfer"))
|
raise ValidationError(_("The quote should be sent and the payment acquirer type should be manual or wire transfer"))
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def _prepare_invoice(self):
|
||||||
|
res = super(SaleOrder, self)._prepare_invoice()
|
||||||
|
res['website_id'] = self.website_id.id
|
||||||
|
return res
|
||||||
|
49
addons/website_sale/models/sale_report.py
Normal file
49
addons/website_sale/models/sale_report.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Part of flectra. See LICENSE file for full copyright and licensing details.
|
||||||
|
|
||||||
|
from flectra import api, fields, models
|
||||||
|
|
||||||
|
|
||||||
|
class SaleReport(models.Model):
|
||||||
|
_inherit = "sale.report"
|
||||||
|
website_id = fields.Many2one('website', 'Website', readonly=True)
|
||||||
|
|
||||||
|
def _select(self):
|
||||||
|
select_str = """
|
||||||
|
WITH currency_rate as (%s)
|
||||||
|
SELECT min(l.id) as id,
|
||||||
|
l.product_id as product_id,
|
||||||
|
t.uom_id as product_uom,
|
||||||
|
sum(l.product_uom_qty / u.factor * u2.factor) as product_uom_qty,
|
||||||
|
sum(l.qty_delivered / u.factor * u2.factor) as qty_delivered,
|
||||||
|
sum(l.qty_invoiced / u.factor * u2.factor) as qty_invoiced,
|
||||||
|
sum(l.qty_to_invoice / u.factor * u2.factor) as qty_to_invoice,
|
||||||
|
sum(l.price_total / COALESCE(cr.rate, 1.0)) as price_total,
|
||||||
|
sum(l.price_subtotal / COALESCE(cr.rate, 1.0)) as price_subtotal,
|
||||||
|
sum(l.amt_to_invoice / COALESCE(cr.rate, 1.0)) as amt_to_invoice,
|
||||||
|
sum(l.amt_invoiced / COALESCE(cr.rate, 1.0)) as amt_invoiced,
|
||||||
|
count(*) as nbr,
|
||||||
|
s.name as name,
|
||||||
|
s.date_order as date,
|
||||||
|
s.confirmation_date as confirmation_date,
|
||||||
|
s.state as state,
|
||||||
|
s.partner_id as partner_id,
|
||||||
|
s.user_id as user_id,
|
||||||
|
s.company_id as company_id,
|
||||||
|
extract(epoch from avg(date_trunc('day',s.date_order)-date_trunc('day',s.create_date)))/(24*60*60)::decimal(16,2) as delay,
|
||||||
|
t.categ_id as categ_id,
|
||||||
|
s.pricelist_id as pricelist_id,
|
||||||
|
s.analytic_account_id as analytic_account_id,
|
||||||
|
s.team_id as team_id,
|
||||||
|
s.website_id as website_id,
|
||||||
|
p.product_tmpl_id,
|
||||||
|
partner.country_id as country_id,
|
||||||
|
partner.commercial_partner_id as commercial_partner_id,
|
||||||
|
sum(p.weight * l.product_uom_qty / u.factor * u2.factor) as weight,
|
||||||
|
sum(p.volume * l.product_uom_qty / u.factor * u2.factor) as volume
|
||||||
|
""" % self.env['res.currency']._select_companies_rates()
|
||||||
|
return select_str
|
||||||
|
|
||||||
|
def _group_by(self):
|
||||||
|
res = super(SaleReport, self)._group_by()
|
||||||
|
return res + ',s.website_id'
|
@ -17,12 +17,14 @@ class Website(models.Model):
|
|||||||
currency_id = fields.Many2one('res.currency', related='pricelist_id.currency_id', string='Default Currency')
|
currency_id = fields.Many2one('res.currency', related='pricelist_id.currency_id', string='Default Currency')
|
||||||
salesperson_id = fields.Many2one('res.users', string='Salesperson')
|
salesperson_id = fields.Many2one('res.users', string='Salesperson')
|
||||||
salesteam_id = fields.Many2one('crm.team', string='Sales Channel')
|
salesteam_id = fields.Many2one('crm.team', string='Sales Channel')
|
||||||
pricelist_ids = fields.One2many('product.pricelist', compute="_compute_pricelist_ids",
|
pricelist_ids = fields.One2many('website.product.pricelist', compute="_compute_pricelist_ids",
|
||||||
string='Price list available for this Ecommerce/Website')
|
string='Price list available for this Ecommerce/Website')
|
||||||
|
|
||||||
@api.one
|
@api.one
|
||||||
def _compute_pricelist_ids(self):
|
def _compute_pricelist_ids(self):
|
||||||
self.pricelist_ids = self.env["product.pricelist"].search([("website_id", "=", self.id)])
|
for website in self:
|
||||||
|
website.pricelist_ids = website.env["website.product.pricelist"].search([("website_id", "=", website.id)])
|
||||||
|
# self.pricelist_ids = self.env["product.pricelist"].search([("website_id", "=", self.id)])
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def _compute_pricelist_id(self):
|
def _compute_pricelist_id(self):
|
||||||
@ -32,8 +34,8 @@ class Website(models.Model):
|
|||||||
website.pricelist_id = website.get_current_pricelist()
|
website.pricelist_id = website.get_current_pricelist()
|
||||||
|
|
||||||
# This method is cached, must not return records! See also #8795
|
# This method is cached, must not return records! See also #8795
|
||||||
@tools.ormcache('self.env.uid', 'country_code', 'show_visible', 'website_pl', 'current_pl', 'all_pl', 'partner_pl', 'order_pl')
|
@tools.ormcache('self.env.uid', 'country_code', 'show_visible', 'website_pl', 'current_pl', 'all_pls', 'partner_pl', 'order_pl')
|
||||||
def _get_pl_partner_order(self, country_code, show_visible, website_pl, current_pl, all_pl, partner_pl=False, order_pl=False):
|
def _get_pl_partner_order(self, country_code, show_visible, website_pl, current_pl, all_pls, partner_pl=False, order_pl=False):
|
||||||
""" Return the list of pricelists that can be used on website for the current user.
|
""" Return the list of pricelists that can be used on website for the current user.
|
||||||
:param str country_code: code iso or False, If set, we search only price list available for this country
|
:param str country_code: code iso or False, If set, we search only price list available for this country
|
||||||
:param bool show_visible: if True, we don't display pricelist where selectable is False (Eg: Code promo)
|
:param bool show_visible: if True, we don't display pricelist where selectable is False (Eg: Code promo)
|
||||||
@ -49,7 +51,7 @@ class Website(models.Model):
|
|||||||
if country_code:
|
if country_code:
|
||||||
for cgroup in self.env['res.country.group'].search([('country_ids.code', '=', country_code)]):
|
for cgroup in self.env['res.country.group'].search([('country_ids.code', '=', country_code)]):
|
||||||
for group_pricelists in cgroup.pricelist_ids:
|
for group_pricelists in cgroup.pricelist_ids:
|
||||||
if not show_visible or group_pricelists.selectable or group_pricelists.id in (current_pl, order_pl):
|
if not show_visible or group_pricelists.website_id.filtered(lambda web_pl: web_pl.website_id == self.get_current_website() and web_pl.selectable) or group_pricelists.id in (current_pl, order_pl):
|
||||||
pricelists |= group_pricelists
|
pricelists |= group_pricelists
|
||||||
|
|
||||||
partner = self.env.user.partner_id
|
partner = self.env.user.partner_id
|
||||||
@ -59,9 +61,11 @@ class Website(models.Model):
|
|||||||
pricelists |= partner.property_product_pricelist
|
pricelists |= partner.property_product_pricelist
|
||||||
|
|
||||||
if not pricelists: # no pricelist for this country, or no GeoIP
|
if not pricelists: # no pricelist for this country, or no GeoIP
|
||||||
pricelists |= all_pl.filtered(lambda pl: not show_visible or pl.selectable or pl.id in (current_pl, order_pl))
|
for all_pl in all_pls:
|
||||||
|
pricelists |= all_pl.pricelist_id.filtered(lambda pl: not show_visible or (all_pl.pricelist_id == pl and all_pl.selectable) or pl.id in (current_pl, order_pl))
|
||||||
else:
|
else:
|
||||||
pricelists |= all_pl.filtered(lambda pl: not show_visible and pl.sudo().code)
|
for all_pl in all_pls:
|
||||||
|
pricelists |= all_pl.pricelist_id.filtered(lambda pl: not show_visible and pl.sudo().code)
|
||||||
|
|
||||||
# This method is cached, must not return records! See also #8795
|
# This method is cached, must not return records! See also #8795
|
||||||
return pricelists.ids
|
return pricelists.ids
|
||||||
@ -167,6 +171,7 @@ class Website(models.Model):
|
|||||||
'partner_invoice_id': addr['invoice'],
|
'partner_invoice_id': addr['invoice'],
|
||||||
'partner_shipping_id': addr['delivery'],
|
'partner_shipping_id': addr['delivery'],
|
||||||
'user_id': salesperson_id or self.salesperson_id.id or default_user_id,
|
'user_id': salesperson_id or self.salesperson_id.id or default_user_id,
|
||||||
|
'website_id': request.website.id,
|
||||||
}
|
}
|
||||||
company = self.company_id or pricelist.company_id
|
company = self.company_id or pricelist.company_id
|
||||||
if company:
|
if company:
|
||||||
|
@ -19,3 +19,4 @@ access_account_tax_user,account.tax,account.model_account_tax,base.group_public,
|
|||||||
access_product_image_public,product.image public,model_product_image,,1,0,0,0
|
access_product_image_public,product.image public,model_product_image,,1,0,0,0
|
||||||
access_product_image_publisher,product.image wbesite publisher,model_product_image,website.group_website_publisher,1,1,1,1
|
access_product_image_publisher,product.image wbesite publisher,model_product_image,website.group_website_publisher,1,1,1,1
|
||||||
access_product_image_sale,product.image sale,model_product_image,sales_team.group_sale_manager,1,1,1,1
|
access_product_image_sale,product.image sale,model_product_image,sales_team.group_sale_manager,1,1,1,1
|
||||||
|
access_website_product_pricelist,access_website_product_pricelist,model_website_product_pricelist,,1,0,0,0
|
||||||
|
|
@ -22,22 +22,30 @@ class TestWebsitePriceList(TransactionCase):
|
|||||||
self.env['product.pricelist'].search([]).write({'website_id': False})
|
self.env['product.pricelist'].search([]).write({'website_id': False})
|
||||||
website_pls = ('list_benelux', 'list_christmas', 'list_europe')
|
website_pls = ('list_benelux', 'list_christmas', 'list_europe')
|
||||||
for pl in website_pls:
|
for pl in website_pls:
|
||||||
self.env.ref('website_sale.' + pl).website_id = self.website.id
|
self.env['website.product.pricelist'].create({
|
||||||
self.env.ref('product.list0').website_id = self.website.id
|
'pricelist_id': self.env.ref('website_sale.' + pl).id,
|
||||||
self.env.ref('website_sale.list_benelux').selectable = True
|
'website_id': self.website.id,
|
||||||
|
'selectable': False if pl == 'list_christmas' else True
|
||||||
|
})
|
||||||
|
self.env['website.product.pricelist'].create({
|
||||||
|
'pricelist_id': self.env.ref('product.list0').id,
|
||||||
|
'website_id': self.website.id
|
||||||
|
})
|
||||||
self.website.pricelist_id = self.ref('product.list0')
|
self.website.pricelist_id = self.ref('product.list0')
|
||||||
|
|
||||||
ca_group = self.env['res.country.group'].create({
|
ca_group = self.env['res.country.group'].create({
|
||||||
'name': 'Canada',
|
'name': 'Canada',
|
||||||
'country_ids': [(6, 0, [self.ref('base.ca')])]
|
'country_ids': [(6, 0, [self.ref('base.ca')])]
|
||||||
})
|
})
|
||||||
self.env['product.pricelist'].create({
|
ppl = self.env['product.pricelist'].create({
|
||||||
'name': 'Canada',
|
'name': 'Canada',
|
||||||
'selectable': True,
|
|
||||||
'website_id': self.website.id,
|
|
||||||
'country_group_ids': [(6, 0, [ca_group.id])],
|
'country_group_ids': [(6, 0, [ca_group.id])],
|
||||||
'sequence': 10
|
'sequence': 10
|
||||||
})
|
})
|
||||||
|
self.env['website.product.pricelist'].create({
|
||||||
|
'pricelist_id': ppl.id,
|
||||||
|
'website_id': self.website.id
|
||||||
|
})
|
||||||
patcher = patch('flectra.addons.website_sale.models.website.Website.get_pricelist_available', wraps=self._get_pricelist_available)
|
patcher = patch('flectra.addons.website_sale.models.website.Website.get_pricelist_available', wraps=self._get_pricelist_available)
|
||||||
patcher.start()
|
patcher.start()
|
||||||
self.addCleanup(patcher.stop)
|
self.addCleanup(patcher.stop)
|
||||||
|
@ -21,4 +21,15 @@
|
|||||||
<field name="search_view_id" ref="product.product_pricelist_view_search" />
|
<field name="search_view_id" ref="product.product_pricelist_view_search" />
|
||||||
<field name="context">{"default_base":'list_price'}</field>
|
<field name="context">{"default_base":'list_price'}</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<record id="view_invoice_form_inherit" model="ir.ui.view">
|
||||||
|
<field name="name">account.invoice.form.inherit</field>
|
||||||
|
<field name="model">account.invoice</field>
|
||||||
|
<field name="inherit_id" ref="account.invoice_form"/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<field name='fiscal_position_id' position="after">
|
||||||
|
<field name="website_id"/>
|
||||||
|
</field>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
</flectra>
|
</flectra>
|
@ -21,4 +21,24 @@
|
|||||||
<field name="view_id" ref="payment.transaction"/>
|
<field name="view_id" ref="payment.transaction"/>
|
||||||
<field name="help">You don't have any payments to capture from the website.</field>
|
<field name="help">You don't have any payments to capture from the website.</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<record id="product_template_only_form_view_inherit" model="ir.ui.view">
|
||||||
|
<field name="name">product.template.product.form.inherit</field>
|
||||||
|
<field name="model">product.template</field>
|
||||||
|
<field name="inherit_id" ref="product.product_template_only_form_view"/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//field[@name='attribute_line_ids']"
|
||||||
|
position="after">
|
||||||
|
<field name="product_variant_ids">
|
||||||
|
<tree editable='bottom' delete="false" create="false">
|
||||||
|
<field name = 'name' readonly="1"/>
|
||||||
|
<field name = 'attribute_value_ids'
|
||||||
|
widget="many2many_tags" readonly="1"/>
|
||||||
|
<field name = 'lst_price' readonly="1"/>
|
||||||
|
<field name = 'website_ids' widget="many2many_tags" />
|
||||||
|
</tree>
|
||||||
|
</field>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
</flectra>
|
</flectra>
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
<field name="accessory_product_ids" widget="many2many_tags"/>
|
<field name="accessory_product_ids" widget="many2many_tags"/>
|
||||||
<field name="website_style_ids" widget="many2many_tags" groups="base.group_no_one"/>
|
<field name="website_style_ids" widget="many2many_tags" groups="base.group_no_one"/>
|
||||||
</group>
|
</group>
|
||||||
|
<field name="website_ids"/>
|
||||||
</group>
|
</group>
|
||||||
<button name="toggle_active" position="before">
|
<button name="toggle_active" position="before">
|
||||||
<button class="oe_stat_button" name="website_publish_button"
|
<button class="oe_stat_button" name="website_publish_button"
|
||||||
@ -153,6 +154,7 @@
|
|||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="parent_id"/>
|
<field name="parent_id"/>
|
||||||
<field name="sequence"/>
|
<field name="sequence"/>
|
||||||
|
<field name="website_ids" widget="many2many_tags"/>
|
||||||
</group>
|
</group>
|
||||||
</div>
|
</div>
|
||||||
</sheet>
|
</sheet>
|
||||||
@ -193,19 +195,12 @@
|
|||||||
<field name="model">product.pricelist</field>
|
<field name="model">product.pricelist</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<field name='currency_id' position='after'>
|
<field name='currency_id' position='after'>
|
||||||
<field name="selectable"/>
|
<field name="website_id" string='Allow to use on '>
|
||||||
<field name="website_id" string='Allow to use on ' placeholder="None website" />
|
<tree editable='bottom' string="Website Store">
|
||||||
</field>
|
<field name="website_id"/>
|
||||||
</field>
|
<field name="selectable"/>
|
||||||
</record>
|
</tree>
|
||||||
|
</field>
|
||||||
<record id="website_sale_pricelist_tree_view" model="ir.ui.view">
|
|
||||||
<field name="name">product.pricelist.tree.inherit.product</field>
|
|
||||||
<field name="model">product.pricelist</field>
|
|
||||||
<field name="inherit_id" ref="product.product_pricelist_view_tree"/>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<field name="currency_id" position="after">
|
|
||||||
<field name="selectable" />
|
|
||||||
</field>
|
</field>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
@ -365,7 +365,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-12 col-md-6 o_setting_box" id="checkout_assignation_setting" groups="base.group_no_one">
|
<div class="col-xs-12 col-md-6 o_setting_box" id="checkout_assignation_setting">
|
||||||
<div class="o_setting_right_pane">
|
<div class="o_setting_right_pane">
|
||||||
<label string="Assignation"/>
|
<label string="Assignation"/>
|
||||||
<div class="text-muted">
|
<div class="text-muted">
|
||||||
@ -374,7 +374,7 @@
|
|||||||
<div class="content-group">
|
<div class="content-group">
|
||||||
<div class="row mt16">
|
<div class="row mt16">
|
||||||
<label class="o_light_label col-md-3" string="Sales Channel" for="salesteam_id"/>
|
<label class="o_light_label col-md-3" string="Sales Channel" for="salesteam_id"/>
|
||||||
<field name="salesteam_id" context="{'default_team_type': 'website'}"/>
|
<field name="salesteam_id" context="{'default_team_type': 'website'}" required="True"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label class="o_light_label col-md-3" for="salesperson_id"/>
|
<label class="o_light_label col-md-3" for="salesperson_id"/>
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
<filter string="From Website" name="from_website" domain="[('team_id.team_type', '=', 'website')]"/>
|
<filter string="From Website" name="from_website" domain="[('team_id.team_type', '=', 'website')]"/>
|
||||||
<separator/>
|
<separator/>
|
||||||
<filter string="Recovery Email to Send" name="recovery_email" domain="[('cart_recovery_email_sent', '=', False)]" />
|
<filter string="Recovery Email to Send" name="recovery_email" domain="[('cart_recovery_email_sent', '=', False)]" />
|
||||||
|
<separator/>
|
||||||
|
<filter name="website_id" string="Website" context="{'group_by':'website_id'}"/>
|
||||||
</search>
|
</search>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
@ -35,6 +37,9 @@
|
|||||||
class="btn-primary"
|
class="btn-primary"
|
||||||
attrs="{'invisible': ['|', ('is_abandoned_cart', '=', False), ('cart_recovery_email_sent', '=', True)]}"/>
|
attrs="{'invisible': ['|', ('is_abandoned_cart', '=', False), ('cart_recovery_email_sent', '=', True)]}"/>
|
||||||
</xpath>
|
</xpath>
|
||||||
|
<xpath expr="//group[@name='sales_person']" position="inside">
|
||||||
|
<field name="website_id"/>
|
||||||
|
</xpath>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
@ -193,7 +193,7 @@
|
|||||||
<t t-if="td_product">
|
<t t-if="td_product">
|
||||||
<t t-set="product" t-value="td_product['product']" />
|
<t t-set="product" t-value="td_product['product']" />
|
||||||
<td t-att-colspan="td_product['x'] != 1 and td_product['x']" t-att-rowspan="td_product['y'] != 1 and td_product['y']" t-attf-class="oe_product oe_grid oe-height-#{td_product['y']*2} #{ td_product['class'] }">
|
<td t-att-colspan="td_product['x'] != 1 and td_product['x']" t-att-rowspan="td_product['y'] != 1 and td_product['y']" t-attf-class="oe_product oe_grid oe-height-#{td_product['y']*2} #{ td_product['class'] }">
|
||||||
<div class="oe_product_cart" t-att-data-publish="product.website_published and 'on' or 'off'">
|
<div class="oe_product_cart" t-att-data-publish="website in product.website_ids and 'on' or 'off'">
|
||||||
<t t-set="product_image_big" t-value="td_product['x']+td_product['y'] > 2" />
|
<t t-set="product_image_big" t-value="td_product['x']+td_product['y'] > 2" />
|
||||||
<t t-call="website_sale.products_item" />
|
<t t-call="website_sale.products_item" />
|
||||||
</div>
|
</div>
|
||||||
@ -258,7 +258,7 @@
|
|||||||
|
|
||||||
<!-- Add to cart button-->
|
<!-- Add to cart button-->
|
||||||
<template id="categories_recursive" name="Category list">
|
<template id="categories_recursive" name="Category list">
|
||||||
<li t-att-class="'active' if c.id == int(category or 0) else None">
|
<li t-att-class="'active' if c.id == int(category or 0) else None" t-if="website in c.website_ids">
|
||||||
<a t-att-href="keep('/shop/category/' + slug(c), category=0)" t-field="c.name"></a>
|
<a t-att-href="keep('/shop/category/' + slug(c), category=0)" t-field="c.name"></a>
|
||||||
<ul t-if="c.child_id" class="nav nav-pills nav-stacked nav-hierarchy">
|
<ul t-if="c.child_id" class="nav nav-pills nav-stacked nav-hierarchy">
|
||||||
<t t-foreach="c.child_id" t-as="c">
|
<t t-foreach="c.child_id" t-as="c">
|
||||||
@ -365,7 +365,7 @@
|
|||||||
<template id="products_list_view" inherit_id="website_sale.products" active="False" customize_show="True" name="List View">
|
<template id="products_list_view" inherit_id="website_sale.products" active="False" customize_show="True" name="List View">
|
||||||
<xpath expr="//div[@id='products_grid']//table" position="replace">
|
<xpath expr="//div[@id='products_grid']//table" position="replace">
|
||||||
<t t-foreach="products" t-as="product">
|
<t t-foreach="products" t-as="product">
|
||||||
<div class="oe_product oe_list oe_product_cart" t-att-data-publish="product.website_published and 'on' or 'off'">
|
<div class="oe_product oe_list oe_product_cart" t-att-data-publish="website in product.website_ids and 'on' or 'off'">
|
||||||
<t t-call="website_sale.products_item">
|
<t t-call="website_sale.products_item">
|
||||||
<t t-set="show_publish" t-value="True" />
|
<t t-set="show_publish" t-value="True" />
|
||||||
</t>
|
</t>
|
||||||
|
Loading…
Reference in New Issue
Block a user