[IMP] "website_sale" compatible for multi website

This commit is contained in:
Kaushal Prajapati 2017-12-22 19:47:53 +05:30 committed by Siddharth Bhalgami
parent d00801d466
commit 23e5ea0865
19 changed files with 510 additions and 56 deletions

View File

@ -12,8 +12,10 @@ from flectra.http import request
class WebsiteSaleBackend(WebsiteBackend):
@http.route()
def fetch_dashboard_data(self, date_from, date_to):
results = super(WebsiteSaleBackend, self).fetch_dashboard_data(date_from, date_to)
def fetch_dashboard_data(self, date_from, date_to, website_id=None):
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(
graph=[],
@ -44,6 +46,7 @@ class WebsiteSaleBackend(WebsiteBackend):
('team_id.team_type', '=', 'website'),
('state', 'in', ['sale', 'done']),
('date', '>=', date_from),
('website_id.id', '=', website_id),
('date', '<=', date_to)],
fields=['product_id', 'product_uom_qty', 'price_subtotal'],
groupby='product_id', orderby='product_uom_qty desc', limit=5)
@ -60,7 +63,8 @@ class WebsiteSaleBackend(WebsiteBackend):
sale_order_domain = [
('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_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')
for res in so_group_data:
if res.get('state') == 'sent':
@ -74,7 +78,8 @@ class WebsiteSaleBackend(WebsiteBackend):
('team_id.team_type', '=', 'website'),
('state', 'in', ['sale', 'done']),
('date', '>=', date_from),
('date', '<=', date_to)],
('date', '<=', date_to),
('website_id.id', '=', website_id)],
fields=['team_id', 'price_subtotal'],
groupby=['team_id'],
)
@ -114,7 +119,8 @@ class WebsiteSaleBackend(WebsiteBackend):
('team_id.team_type', '=', 'website'),
('state', 'in', ['sale', 'done']),
('date', '>=', date_from),
('date', '<=', date_to)
('date', '<=', date_to),
('website_id.id', '=', website_id)
]
sales_values['graph'] += [{
'values': self._compute_sale_graph(date_date_from, date_date_to, sales_domain),

View File

@ -135,7 +135,7 @@ class WebsiteSale(http.Controller):
def get_attribute_value_ids(self, 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)
"""
# product attributes with at least two choices
@ -185,6 +185,8 @@ class WebsiteSale(http.Controller):
ids = [value[1]]
if attrib:
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
@ -222,11 +224,16 @@ class WebsiteSale(http.Controller):
post["search"] = search
if 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)
if 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']
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)
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):
request.session['website_sale_current_pl'] = pl_id.id
request.website.sale_get_order(force_pricelist=pl_id.id)

View 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)

View File

@ -38,10 +38,6 @@
<field name="salesteam_id" ref="sales_team.salesteam_website_sales"/>
</record>
<record model="product.pricelist" id="product.list0">
<field name="selectable" eval="False" />
<field name="website_id" ref="website.default_website" />
</record>
</data>
<data>
<record id="sale.model_sale_order" model="ir.model">

View File

@ -713,8 +713,7 @@ Weight: 31 grams</field>
<record model="product.pricelist" id="product.list0">
<field name="name">USD</field>
<field name="selectable" eval="True" />
<field name="website_id" ref="website.default_website" />
<!--<field name="website_id" eval="[(6, 0, [ref('website.default_website').id])]"/>-->
<field name="sequence">3</field>
<field name="currency_id" ref="base.USD"/>
</record>
@ -727,8 +726,7 @@ Weight: 31 grams</field>
<record id="list_christmas" model="product.pricelist">
<field name="name">Christmas</field>
<field name="selectable" eval="False" />
<field name="website_id" ref="website.default_website" />
<!--<field name="website_id" eval="[(6, 0, [ref('website.default_website').id])]"/>-->
<field name="country_group_ids" eval="[(6,0,[ref('base.europe')])]" />
<field name="sequence">20</field>
</record>
@ -741,8 +739,7 @@ Weight: 31 grams</field>
<record id="list_benelux" model="product.pricelist">
<field name="name">Benelux</field>
<field name="selectable" eval="False" />
<field name="website_id" ref="website.default_website" />
<!--<field name="website_id" eval="[(6, 0, [ref('website.default_website').id])]"/>-->
<field name="country_group_ids" eval="[(6,0,[ref('benelux')])]" />
<field name="sequence">2</field>
</record>
@ -757,8 +754,7 @@ Weight: 31 grams</field>
<record id="list_europe" model="product.pricelist">
<field name="name">EUR</field>
<field name="selectable" eval="True" />
<field name="website_id" ref="website.default_website" />
<!--<field name="website_id" eval="[(6, 0, [ref('website.default_website').id])]"/>-->
<field name="country_group_ids" eval="[(6,0,[ref('base.europe')])]" />
<field name="sequence">3</field>
<field name="currency_id" ref="base.EUR"/>

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import account_invoice
from . import crm_team
from . import ir_http
from . import mail_compose_message
@ -8,6 +9,7 @@ from . import product
from . import res_country
from . import res_partner
from . import sale_order
from . import sale_report
from . import ir_model_fields
from . import website
from . import res_config_settings

View 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

View File

@ -15,15 +15,23 @@ class ProductStyle(models.Model):
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):
_inherit = "product.pricelist"
def _default_website(self):
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")
selectable = fields.Boolean(help="Allow the end user to choose this price list")
def clear_cache(self):
# 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 "
"resized as a 64x64px image, with aspect ratio preserved. "
"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
def create(self, 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
def write(self, 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')
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_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_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):
# First filter out the ones that have no variant:
@ -180,6 +217,11 @@ class ProductTemplate(models.Model):
class Product(models.Model):
_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_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')

View File

@ -21,6 +21,8 @@ class SaleOrder(models.Model):
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.',
)
website_id = fields.Many2one('website', string='Website',
help='Website reference for quotation/order.')
cart_quantity = fields.Integer(compute='_compute_cart_info', string='Cart Quantity')
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',
@ -256,3 +258,9 @@ class SaleOrder(models.Model):
self.payment_tx_id.state = 'done'
else:
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

View 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'

View File

@ -17,12 +17,14 @@ class Website(models.Model):
currency_id = fields.Many2one('res.currency', related='pricelist_id.currency_id', string='Default Currency')
salesperson_id = fields.Many2one('res.users', string='Salesperson')
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')
@api.one
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
def _compute_pricelist_id(self):
@ -32,8 +34,8 @@ class Website(models.Model):
website.pricelist_id = website.get_current_pricelist()
# 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')
def _get_pl_partner_order(self, country_code, show_visible, website_pl, current_pl, all_pl, partner_pl=False, order_pl=False):
@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_pls, partner_pl=False, order_pl=False):
""" 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 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:
for cgroup in self.env['res.country.group'].search([('country_ids.code', '=', country_code)]):
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
partner = self.env.user.partner_id
@ -59,9 +61,11 @@ class Website(models.Model):
pricelists |= partner.property_product_pricelist
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:
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
return pricelists.ids
@ -167,6 +171,7 @@ class Website(models.Model):
'partner_invoice_id': addr['invoice'],
'partner_shipping_id': addr['delivery'],
'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
if company:

View File

@ -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_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_website_product_pricelist,access_website_product_pricelist,model_website_product_pricelist,,1,0,0,0

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
19 access_product_image_public product.image public model_product_image 1 0 0 0
20 access_product_image_publisher product.image wbesite publisher model_product_image website.group_website_publisher 1 1 1 1
21 access_product_image_sale product.image sale model_product_image sales_team.group_sale_manager 1 1 1 1
22 access_website_product_pricelist access_website_product_pricelist model_website_product_pricelist 1 0 0 0

View File

@ -22,22 +22,30 @@ class TestWebsitePriceList(TransactionCase):
self.env['product.pricelist'].search([]).write({'website_id': False})
website_pls = ('list_benelux', 'list_christmas', 'list_europe')
for pl in website_pls:
self.env.ref('website_sale.' + pl).website_id = self.website.id
self.env.ref('product.list0').website_id = self.website.id
self.env.ref('website_sale.list_benelux').selectable = True
self.env['website.product.pricelist'].create({
'pricelist_id': self.env.ref('website_sale.' + pl).id,
'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')
ca_group = self.env['res.country.group'].create({
'name': 'Canada',
'country_ids': [(6, 0, [self.ref('base.ca')])]
})
self.env['product.pricelist'].create({
ppl = self.env['product.pricelist'].create({
'name': 'Canada',
'selectable': True,
'website_id': self.website.id,
'country_group_ids': [(6, 0, [ca_group.id])],
'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.start()
self.addCleanup(patcher.stop)

View File

@ -21,4 +21,15 @@
<field name="search_view_id" ref="product.product_pricelist_view_search" />
<field name="context">{"default_base":'list_price'}</field>
</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>

View File

@ -21,4 +21,24 @@
<field name="view_id" ref="payment.transaction"/>
<field name="help">You don't have any payments to capture from the website.</field>
</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>

View File

@ -74,6 +74,7 @@
<field name="accessory_product_ids" widget="many2many_tags"/>
<field name="website_style_ids" widget="many2many_tags" groups="base.group_no_one"/>
</group>
<field name="website_ids"/>
</group>
<button name="toggle_active" position="before">
<button class="oe_stat_button" name="website_publish_button"
@ -153,6 +154,7 @@
<field name="name"/>
<field name="parent_id"/>
<field name="sequence"/>
<field name="website_ids" widget="many2many_tags"/>
</group>
</div>
</sheet>
@ -193,20 +195,13 @@
<field name="model">product.pricelist</field>
<field name="arch" type="xml">
<field name='currency_id' position='after'>
<field name="website_id" string='Allow to use on '>
<tree editable='bottom' string="Website Store">
<field name="website_id"/>
<field name="selectable"/>
<field name="website_id" string='Allow to use on ' placeholder="None website" />
</tree>
</field>
</field>
</record>
<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>
</record>

View File

@ -365,7 +365,7 @@
</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">
<label string="Assignation"/>
<div class="text-muted">
@ -374,7 +374,7 @@
<div class="content-group">
<div class="row mt16">
<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 class="row">
<label class="o_light_label col-md-3" for="salesperson_id"/>

View File

@ -11,6 +11,8 @@
<filter string="From Website" name="from_website" domain="[('team_id.team_type', '=', 'website')]"/>
<separator/>
<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>
</field>
</record>
@ -35,6 +37,9 @@
class="btn-primary"
attrs="{'invisible': ['|', ('is_abandoned_cart', '=', False), ('cart_recovery_email_sent', '=', True)]}"/>
</xpath>
<xpath expr="//group[@name='sales_person']" position="inside">
<field name="website_id"/>
</xpath>
</field>
</record>

View File

@ -193,7 +193,7 @@
<t t-if="td_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'] }">
<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'] &gt; 2" />
<t t-call="website_sale.products_item" />
</div>
@ -258,7 +258,7 @@
<!-- Add to cart button-->
<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>
<ul t-if="c.child_id" class="nav nav-pills nav-stacked nav-hierarchy">
<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">
<xpath expr="//div[@id='products_grid']//table" position="replace">
<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-set="show_publish" t-value="True" />
</t>