[MERGE] forward port branch saas-12 up to 13765b5
This commit is contained in:
+1
-1
@@ -317,7 +317,7 @@ file_filter = addons/im_livechat/i18n/<lang>.po
|
||||
source_file = addons/im_livechat/i18n/im_livechat.pot
|
||||
source_lang = en
|
||||
|
||||
[odoo-master.l10n_multilang]
|
||||
[odoo-10.l10n_multilang]
|
||||
file_filter = addons/l10n_multilang/i18n/<lang>.po
|
||||
source_file = addons/l10n_multilang/i18n/l10n_multilang.pot
|
||||
source_lang = en
|
||||
|
||||
@@ -1343,9 +1343,10 @@ class AccountInvoiceTax(models.Model):
|
||||
base = 0.0
|
||||
for line in tax.invoice_id.invoice_line_ids:
|
||||
if tax.tax_id in line.invoice_line_tax_ids:
|
||||
base += line.price_subtotal
|
||||
# To add include base amount taxes
|
||||
base += sum((line.invoice_line_tax_ids.filtered(lambda t: t.include_base_amount) - tax.tax_id).mapped('amount'))
|
||||
price_unit = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
|
||||
base += (line.invoice_line_tax_ids - tax.tax_id).compute_all(
|
||||
price_unit, line.invoice_id.currency_id, line.quantity, line.product_id, line.invoice_id.partner_id
|
||||
)['base']
|
||||
tax.base = base
|
||||
|
||||
invoice_id = fields.Many2one('account.invoice', string='Invoice', ondelete='cascade', index=True)
|
||||
|
||||
@@ -280,7 +280,7 @@ class HrExpense(models.Model):
|
||||
if help_message:
|
||||
alias_record = self.env.ref('hr_expense.mail_alias_expense')
|
||||
if alias_record and alias_record.alias_domain and alias_record.alias_name:
|
||||
link = "<a id='o_mail_test' href='mailto:%(email)s&subject=Lunch+with+customer%%3A+%%2412.32'>%(email)s</a>" % {
|
||||
link = "<a id='o_mail_test' href='mailto:%(email)s?subject=Lunch%%20with%%20customer%%3A%%20%%2412.32'>%(email)s</a>" % {
|
||||
'email': '%s@%s' % (alias_record.alias_name, alias_record.alias_domain)
|
||||
}
|
||||
return '<p class="oe_view_nocontent_create">%s<br/>%s</p>%s' % (
|
||||
|
||||
@@ -62,7 +62,7 @@ class PaypalController(http.Controller):
|
||||
self.paypal_validate_data(**post)
|
||||
return ''
|
||||
|
||||
@http.route('/payment/paypal/dpn', type='http', auth="none", methods=['POST'], csrf=False)
|
||||
@http.route('/payment/paypal/dpn', type='http', auth="none", methods=['POST', 'GET'], csrf=False)
|
||||
def paypal_dpn(self, **post):
|
||||
""" Paypal DPN """
|
||||
_logger.info('Beginning Paypal DPN form_feedback with post data %s', pprint.pformat(post)) # debug
|
||||
|
||||
@@ -71,7 +71,7 @@ class PosConfig(models.Model):
|
||||
iface_invoicing = fields.Boolean(string='Invoicing', help='Enables invoice generation from the Point of Sale', default=True)
|
||||
iface_big_scrollbars = fields.Boolean('Large Scrollbars', help='For imprecise industrial touchscreens')
|
||||
iface_print_auto = fields.Boolean(string='Automatic Receipt Printing', default=False,
|
||||
help='The receipt will automatically be p-rinted at the end of each order')
|
||||
help='The receipt will automatically be printed at the end of each order')
|
||||
iface_print_skip_screen = fields.Boolean(string='Skip Receipt Screen', default=True,
|
||||
help='The receipt screen will be skipped if the receipt can be printed automatically.')
|
||||
iface_precompute_cash = fields.Boolean(string='Prefill Cash Payment',
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
<section class="oe_container">
|
||||
<div class="oe_row oe_spaced">
|
||||
<h2 class="oe_slogan" style="color:#A24689;">An interface designed for productivity</h2>
|
||||
<h3 class="oe_slogan oe_mb32">The Point of Sales that keeps everything where you need it</h3>
|
||||
<h3 class="oe_slogan oe_mb32">The point of sale that keeps everything where you need it</h3>
|
||||
<div class="oe_span4 text-center">
|
||||
<span class="fa fa-paint-brush fa-2x"/>
|
||||
<h4 class="oe_mt16 oe_mb8">
|
||||
@@ -80,7 +80,7 @@
|
||||
While an Internet connection is required to start the Point of Sale, it will stay operational even after complete disconnection. Because it's extremely flexible, you can configure Odoo POS to meet your precise needs.
|
||||
</p>
|
||||
<p class="oe_mt8">
|
||||
No installation and no specific hardware is required to use Odoo POS. Our solution for point of sales is compatible with desktop PCs, iPads and other tablet computers, laptops and industrial POS machines.
|
||||
No installation and no specific hardware is required to use Odoo POS. Our solution for points of sale is compatible with desktop PCs, iPads and other tablet computers, laptops and industrial POS machines.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -128,7 +128,7 @@
|
||||
<div class="oe_row oe_spaced">
|
||||
<div class="lead text-center">
|
||||
<p>
|
||||
Odoo Point of Sales is more than an ordinary POS.
|
||||
Odoo Point of Sale is more than an ordinary POS.
|
||||
<br/>
|
||||
Our app provides extra features to deliver awesome customer service.
|
||||
</p>
|
||||
@@ -145,7 +145,7 @@
|
||||
</div>
|
||||
<div class='oe_span6'>
|
||||
<p class="oe_mt32 text-justify">
|
||||
Give your shopper a positive experience by improving your services. Handle refunds, track warranties, follow customer claims, plan order deliveries, etc... in one interface. Bring your sales at the next level. Odoo POS can produce customer invoices in just a few clicks and synchronize with Odoo Accounting. Your accounting will be easier and more accurate. Our Point of Sales helps you to control sales and cash in real time but also to keep your whole operations under control.
|
||||
Give your shopper a positive experience by improving your services. Handle refunds, track warranties, follow customer claims, plan order deliveries, etc... in one interface. Bring your sales at the next level. Odoo POS can produce customer invoices in just a few clicks and synchronize with Odoo Accounting. Your accounting will be easier and more accurate. Our Point of Sale helps you to control sales and cash in real time but also to keep your whole operations under control.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<button string="Apply" type="object" name="execute" class="oe_highlight"/>
|
||||
<button string="Cancel" type="object" name="cancel" class="oe_link"/>
|
||||
</header>
|
||||
<group string="Importable Point of Sales Data">
|
||||
<group string="Importable Point of Sale Data">
|
||||
<label for="div" string="Beverages"/>
|
||||
<div>
|
||||
<div>
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
'version': '1.0',
|
||||
'category': 'Point of Sale',
|
||||
'sequence': 99,
|
||||
'summary': 'Common Drinks data for point of sales',
|
||||
'summary': 'Common Drinks data for points of sale',
|
||||
'description': """
|
||||
Common drinks data for point of sales
|
||||
Common drinks data for points of sale
|
||||
""",
|
||||
'depends': ['point_of_sale'],
|
||||
'data': [
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
<!-- Salesteam-related subtypes for messaging / Chatter -->
|
||||
<record id="mt_salesteam_order_sent" model="mail.message.subtype">
|
||||
<field name="name">Quotation Send</field>
|
||||
<field name="name">Quotation sent</field>
|
||||
<field name="sequence">20</field>
|
||||
<field name="res_model">crm.team</field>
|
||||
<field name="parent_id" eval="ref('sale.mt_order_sent')"/>
|
||||
|
||||
@@ -67,7 +67,7 @@ var ControlPanel = Widget.extend({
|
||||
};
|
||||
|
||||
// Prevent the search dropdowns to close when clicking inside them
|
||||
this.$el.on('click.bs.dropdown', '.oe-search-options .dropdown-menu', function (e) {
|
||||
this.$el.on('click.bs.dropdown', '.o_search_options .dropdown-menu', function (e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
|
||||
@@ -58,10 +58,10 @@ return AbstractWebClient.extend({
|
||||
toggle_bars: function(value) {
|
||||
this.$('tr:has(td.navbar),.oe_leftbar').toggle(value);
|
||||
},
|
||||
update_logo: function() {
|
||||
update_logo: function(reload) {
|
||||
var company = session.company_id;
|
||||
var img = session.url('/web/binary/company_logo' + '?db=' + session.db + (company ? '&company=' + company : ''));
|
||||
this.$('.oe_logo img').attr('src', '').attr('src', img);
|
||||
this.$('.o_sub_menu_logo img').attr('src', '').attr('src', img + (reload ? "#" + Date.now() : ''));
|
||||
this.$('.oe_logo_edit').toggleClass('oe_logo_edit_admin', session.is_superuser);
|
||||
},
|
||||
logo_edit: function(ev) {
|
||||
@@ -76,12 +76,13 @@ return AbstractWebClient.extend({
|
||||
action_buttons: true,
|
||||
headless: true,
|
||||
};
|
||||
self.action_manager.do_action(result);
|
||||
var form = self.action_manager.dialog_widget.views.form.controller;
|
||||
form.on("on_button_cancel", self.action_manager, self.action_manager.dialog_stop);
|
||||
form.on('record_saved', self, function() {
|
||||
self.action_manager.dialog_stop();
|
||||
self.update_logo();
|
||||
self.action_manager.do_action(result).then(function () {
|
||||
var form = self.action_manager.dialog_widget.views.form.controller;
|
||||
form.on("on_button_cancel", self.action_manager, self.action_manager.dialog_stop);
|
||||
form.on('record_saved', self, function() {
|
||||
self.action_manager.dialog_stop();
|
||||
self.update_logo();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -562,7 +562,7 @@ data.Class = Widget.extend({
|
||||
animation.start(true, $target);
|
||||
|
||||
self.call_for_all_snippets($target, function (editor, $snippet) {
|
||||
editor.drop_and_build_snippet();
|
||||
_.defer(function () { editor.drop_and_build_snippet(); });
|
||||
});
|
||||
self.create_snippet_editor($target);
|
||||
self.cover_target($target.data('overlay'), $target);
|
||||
@@ -582,12 +582,10 @@ data.Class = Widget.extend({
|
||||
var self = this;
|
||||
$snippet.add(data.globalSelector.all($snippet)).each(function () {
|
||||
var $snippet = $(this);
|
||||
setTimeout(function () {
|
||||
self.create_snippet_editor($snippet);
|
||||
if ($snippet.data("snippet-editor")) {
|
||||
callback.call(self, $snippet.data("snippet-editor"), $snippet);
|
||||
}
|
||||
});
|
||||
self.create_snippet_editor($snippet);
|
||||
if ($snippet.data("snippet-editor")) {
|
||||
callback.call(self, $snippet.data("snippet-editor"), $snippet);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@@ -884,17 +882,25 @@ data.Editor = Class.extend({
|
||||
},
|
||||
_drag_and_drop_stop: function () {
|
||||
var self = this;
|
||||
var $dropzone = this.$target.prev();
|
||||
var prev = $dropzone.length && $dropzone[0].previousSibling;
|
||||
|
||||
$(".oe_drop_zone").droppable('destroy').remove();
|
||||
|
||||
var prev = this.$target.first()[0].previousSibling;
|
||||
var next = this.$target.last()[0].nextSibling;
|
||||
var $parent = this.$target.parent();
|
||||
|
||||
$(".oe_drop_clone").after(this.$target);
|
||||
var $clone = $(".oe_drop_clone");
|
||||
if (prev === $clone[0]) {
|
||||
prev = $clone[0].previousSibling;
|
||||
} else if (next === $clone[0]) {
|
||||
next = $clone[0].nextSibling;
|
||||
}
|
||||
$clone.after(this.$target);
|
||||
|
||||
this.$overlay.removeClass("hidden");
|
||||
$("body").removeClass('move-important');
|
||||
$('.oe_drop_zone').droppable('destroy').remove();
|
||||
$(".oe_drop_clone, .oe_drop_to_remove").remove();
|
||||
$clone.remove();
|
||||
$(".oe_drop_to_remove").remove();
|
||||
|
||||
if (this.dropped) {
|
||||
this.buildingBlock.getParent().rte.historyRecordUndo(this.$target);
|
||||
|
||||
@@ -18,17 +18,23 @@ from odoo.addons.website_portal.controllers.main import website_account
|
||||
|
||||
class WebsiteAccount(website_account):
|
||||
|
||||
@http.route()
|
||||
def account(self):
|
||||
response = super(WebsiteAccount, self).account()
|
||||
lead_count = request.env['crm.lead'].search_count([
|
||||
('partner_assigned_id', '=', request.env.user.partner_id.id),
|
||||
def get_domain_my_lead(self, user):
|
||||
return [
|
||||
('partner_assigned_id', 'child_of', user.commercial_partner_id.id),
|
||||
('type', '=', 'lead')
|
||||
])
|
||||
opp_count = request.env['crm.lead'].search_count([
|
||||
('partner_assigned_id', '=', request.env.user.partner_id.id),
|
||||
]
|
||||
|
||||
def get_domain_my_opp(self, user):
|
||||
return [
|
||||
('partner_assigned_id', 'child_of', user.commercial_partner_id.id),
|
||||
('type', '=', 'opportunity')
|
||||
])
|
||||
]
|
||||
|
||||
@http.route()
|
||||
def account(self, **kw):
|
||||
response = super(WebsiteAccount, self).account(**kw)
|
||||
lead_count = request.env['crm.lead'].search_count(self.get_domain_my_lead(request.env.user))
|
||||
opp_count = request.env['crm.lead'].search_count(self.get_domain_my_opp(request.env.user))
|
||||
response.qcontext.update({'lead_count': lead_count, 'opp_count': opp_count})
|
||||
return response
|
||||
|
||||
@@ -36,7 +42,7 @@ class WebsiteAccount(website_account):
|
||||
def portal_my_leads(self, page=1, date_begin=None, date_end=None, lead=None, sortby=None, **kw):
|
||||
values = self._prepare_portal_layout_values()
|
||||
CrmLead = request.env['crm.lead']
|
||||
domain = [('partner_assigned_id', '=', request.env.user.partner_id.id), ('type', '=', 'lead')]
|
||||
domain = self.get_domain_my_lead(request.env.user)
|
||||
|
||||
sortings = {
|
||||
'date': {'label': _('Newest'), 'order': 'create_date desc'},
|
||||
@@ -79,7 +85,7 @@ class WebsiteAccount(website_account):
|
||||
def portal_my_opportunities(self, page=1, date_begin=None, date_end=None, opportunity=None, sortby=None, **kw):
|
||||
values = self._prepare_portal_layout_values()
|
||||
CrmLead = request.env['crm.lead']
|
||||
domain = [('partner_assigned_id', '=', request.env.user.partner_id.id), ('type', '=', 'opportunity')]
|
||||
domain = self.get_domain_my_opp(request.env.user)
|
||||
|
||||
today = fields.Date.today()
|
||||
this_week_end_date = fields.Date.to_string(fields.Date.from_string(today) + datetime.timedelta(days=7))
|
||||
@@ -185,9 +191,7 @@ class WebsiteCrmPartnerAssign(WebsitePartnerPage):
|
||||
if not country and not country_all:
|
||||
country_code = request.session['geoip'].get('country_code')
|
||||
if country_code:
|
||||
country_ids = country_obj.search([('code', '=', country_code)])
|
||||
if country_ids:
|
||||
country = country_obj.browse(country_ids[0])
|
||||
country = country_obj.search([('code', '=', country_code)], limit=1)
|
||||
if country:
|
||||
grade_domain += [('country_id', '=', country.id)]
|
||||
grades = partner_obj.sudo().read_group(
|
||||
|
||||
@@ -170,7 +170,7 @@ class CrmLead(models.Model):
|
||||
ORDER BY distance LIMIT 1""", (longitude, latitude, lead.id))
|
||||
res = self._cr.dictfetchone()
|
||||
if res:
|
||||
partner_ids.append(res['id'])
|
||||
partner_ids = Partner.browse([res['id']])
|
||||
|
||||
total_weight = 0
|
||||
toassign = []
|
||||
|
||||
@@ -194,7 +194,7 @@
|
||||
</template>
|
||||
<template id="portal_my_home_menu_lead" name="Portal layout : lead menu entry" inherit_id="website_portal.portal_layout" priority="22">
|
||||
<xpath expr="//ul[contains(@class,'o_portal_submenu')]" position="inside">
|
||||
<t t-if="user.partner_id.grade_id.id != False">
|
||||
<t t-if="user.commercial_partner_id.grade_id">
|
||||
<li t-att-class="page_name == 'lead' and 'active'">
|
||||
<a href="/my/leads">Leads</a>
|
||||
</li>
|
||||
@@ -207,7 +207,7 @@
|
||||
|
||||
<template id="portal_my_home_lead" name="Portal My Home : lead entries" inherit_id="website_portal.portal_my_home" priority="22">
|
||||
<xpath expr="//div[contains(@class,'o_my_home_content')]" position="inside">
|
||||
<t t-if="user.partner_id.grade_id.id != False">
|
||||
<t t-if="user.commercial_partner_id.grade_id">
|
||||
<h3 class="page-header">
|
||||
<a href="/my/leads">Your Leads
|
||||
<small class="ml8">
|
||||
@@ -259,20 +259,18 @@
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr class="active">
|
||||
<th class="col-md-5">Name</th>
|
||||
<th class="col-xs-2">Date</th>
|
||||
<th class="col-xs-5">Name</th>
|
||||
<th>Contact Name</th>
|
||||
<th>Stage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr t-foreach="leads" t-as="lead">
|
||||
<td><span t-field="lead.create_date" t-field-options='{"widget": "date"}' /></td>
|
||||
<td>
|
||||
<a t-attf-href="/my/lead/#{lead.id}"><span t-field="lead.name"/></a>
|
||||
</td>
|
||||
<td><span t-field="lead.contact_name" /></td>
|
||||
<td>
|
||||
<span class="label label-primary" title="Current stage of the lead" t-esc="lead.stage_id.name" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -12,13 +12,14 @@
|
||||
</template>
|
||||
|
||||
<template id="share_page_menu" inherit_id="website.user_navbar">
|
||||
<xpath expr="//li[@groups='website.group_website_designer']//ul" position="inside">
|
||||
<xpath expr="//li/a[@data-action='promote-current-page']/.." position="after">
|
||||
<li>
|
||||
<a href="/r" id="o_website_links_share_page">
|
||||
<span title="Track this page to count clicks">Share this Page</span>
|
||||
<span title="Track this page to count clicks">Track this Page</span>
|
||||
</a>
|
||||
</li>
|
||||
</xpath>
|
||||
|
||||
</template>
|
||||
|
||||
<template id="asset_website_links_menu" inherit_id="website.assets_editor">
|
||||
|
||||
@@ -50,7 +50,7 @@ class website_account(http.Controller):
|
||||
})
|
||||
return groups
|
||||
|
||||
@http.route(['/my', '/my/home'], type='http', auth="public", website=True)
|
||||
@http.route(['/my', '/my/home'], type='http', auth="user", website=True)
|
||||
def account(self, **kw):
|
||||
values = self._prepare_portal_layout_values()
|
||||
return request.render("website_portal.portal_my_home", values)
|
||||
|
||||
@@ -11,9 +11,9 @@ from odoo.addons.website_portal.controllers.main import website_account
|
||||
class website_account(website_account):
|
||||
|
||||
@http.route()
|
||||
def account(self):
|
||||
def account(self, **kw):
|
||||
""" Add sales documents to main account page """
|
||||
response = super(website_account, self).account()
|
||||
response = super(website_account, self).account(**kw)
|
||||
partner = request.env.user.partner_id
|
||||
|
||||
SaleOrder = request.env['sale.order']
|
||||
|
||||
@@ -13,7 +13,9 @@ class WebsiteAccount(website_account):
|
||||
def _prepare_portal_layout_values(self):
|
||||
values = super(WebsiteAccount, self)._prepare_portal_layout_values()
|
||||
# domain is needed to hide non portal project for employee
|
||||
issue_count = request.env['project.issue'].search_count([('project_id.privacy_visibility','=','portal')])
|
||||
# portal users can't see the privacy_visibility, fetch the domain for them in sudo
|
||||
portal_projects = request.env['project.project'].sudo().search([('privacy_visibility', '=', 'portal')])
|
||||
issue_count = request.env['project.issue'].search_count([('project_id', 'in', portal_projects.ids)])
|
||||
values.update({
|
||||
'issue_count': issue_count,
|
||||
})
|
||||
@@ -41,7 +43,9 @@ class WebsiteAccount(website_account):
|
||||
str(proj.id): {'label': proj.name, 'domain': [('project_id', '=', proj.id)]}
|
||||
})
|
||||
|
||||
domain = [('project_id.privacy_visibility','=','portal')]
|
||||
# portal users can't see the privacy_visibility, fetch the domain for them in sudo
|
||||
portal_projects = request.env['project.project'].sudo().search([('privacy_visibility', '=', 'portal')])
|
||||
domain = [('project_id', 'in', portal_projects.ids)]
|
||||
domain += project_filters.get(project, project_filters['all'])['domain']
|
||||
order = sortings.get(sortby, sortings['date'])['order']
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
Slovenia, 2016-09-05
|
||||
|
||||
GoOpen, računalniške storitve, Aleš Ferlan s.p. agrees to the terms of the
|
||||
Odoo Corporate Contributor License Agreement v1.0.
|
||||
|
||||
I declare that I am authorized and able to make this agreement and sign this
|
||||
declaration.
|
||||
|
||||
Signed,
|
||||
|
||||
Aleš Ferlan alefer89@protonmail.com
|
||||
|
||||
List of contributors:
|
||||
|
||||
Aleš Ferlan alefer89@protonmail.com
|
||||
@@ -233,15 +233,15 @@ connections to the secure port
|
||||
|
||||
.. warning::
|
||||
|
||||
In case you are using the Point of Sale module in combinaison with a `POSBox`_,
|
||||
In case you are using the Point of Sale module in combination with a `POSBox`_,
|
||||
you must disable the HTTPS configuration for the route ``/pos/web`` to avoid
|
||||
mix-content errors.
|
||||
mixed-content errors.
|
||||
|
||||
Configuration sample
|
||||
--------------------
|
||||
|
||||
* redirect http requests to https
|
||||
* proxiing requests to odoo
|
||||
* proxy requests to odoo
|
||||
|
||||
in ``/etc/odoo.conf`` set:
|
||||
|
||||
@@ -440,4 +440,4 @@ of the supported browsers by Odoo version is the following:
|
||||
.. _use an SSH tunnel:
|
||||
http://www.postgresql.org/docs/9.3/static/ssh-tunnels.html
|
||||
.. _WSGI: http://wsgi.readthedocs.org/
|
||||
.. _POSBox: https://www.odoo.com/page/point-of-sale-hardware#part_2
|
||||
.. _POSBox: https://www.odoo.com/page/point-of-sale-hardware#part_2
|
||||
|
||||
@@ -141,7 +141,7 @@
|
||||
|
||||
<record model="ir.module.category" id="module_category_point_of_sale">
|
||||
<field name="name">Point of Sale</field>
|
||||
<field name="description">Helps you get the most out of your points of sales with fast sale encoding, simplified payment mode encoding, automatic picking lists generation and more.</field>
|
||||
<field name="description">Helps you get the most out of your points of sale with fast sale encoding, simplified payment mode encoding, automatic picking lists generation and more.</field>
|
||||
<field name="sequence">21</field>
|
||||
</record>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user