[PATCH] Upstream patch - 11082023

This commit is contained in:
Parthiv Patel
2023-08-11 08:34:19 +00:00
parent 849676a1b4
commit c5105a39d2
13 changed files with 115 additions and 33 deletions
+4 -2
View File
@@ -3106,11 +3106,13 @@ class AccountMove(models.Model):
for ids in self._cr.split_for_in_conditions(records.ids, size=100):
moves = self.browse(ids)
try: # try posting in batch
moves._post()
with self.env.cr.savepoint():
moves._post()
except UserError: # if at least one move cannot be posted, handle moves one by one
for move in moves:
try:
move._post()
with self.env.cr.savepoint():
move._post()
except UserError as e:
move.to_check = True
msg = _('The move could not be posted for the following reason: %(error_message)s', error_message=e)
+7 -1
View File
@@ -766,7 +766,13 @@ class HrExpenseSheet(models.Model):
return self.env['account.journal'].search([('type', 'in', ['cash', 'bank']), ('company_id', '=', default_company_id)], limit=1)
name = fields.Char('Expense Report Summary', required=True, tracking=True)
expense_line_ids = fields.One2many('hr.expense', 'sheet_id', string='Expense Lines', copy=False)
expense_line_ids = fields.One2many(
comodel_name='hr.expense',
inverse_name='sheet_id',
string='Expense Lines',
copy=False,
states={'post': [('readonly', True)], 'done': [('readonly', True)], 'cancel': [('readonly', True)]}
)
state = fields.Selection([
('draft', 'Draft'),
('submit', 'Submitted'),
@@ -2,6 +2,7 @@
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from flectra import api, fields, models
from flectra.tools.sql import column_exists, create_column
class ProductTemplate(models.Model):
@@ -10,6 +11,18 @@ class ProductTemplate(models.Model):
can_be_expensed = fields.Boolean(string="Can be Expensed", compute='_compute_can_be_expensed',
store=True, readonly=False, help="Specify whether the product can be selected in an expense.")
def _auto_init(self):
if not column_exists(self.env.cr, "product_template", "can_be_expensed"):
create_column(self.env.cr, "product_template", "can_be_expensed", "boolean")
self.env.cr.execute(
"""
UPDATE product_template
SET can_be_expensed = false
WHERE type NOT IN ('consu', 'service')
"""
)
return super()._auto_init()
@api.model
def default_get(self, fields):
result = super(ProductTemplate, self).default_get(fields)
+1 -20
View File
@@ -1,6 +1,4 @@
from flectra import api, fields, models
from flectra.exceptions import UserError
from flectra.tools.translate import _
from flectra import fields, models
class AccountTaxTemplate(models.Model):
_inherit = 'account.tax.template'
@@ -18,23 +16,6 @@ class AccountTax(models.Model):
l10n_de_datev_code = fields.Char(size=4, help="4 digits code use by Datev")
class AccountMove(models.Model):
_inherit = 'account.move'
def _post(self, soft=True):
# OVERRIDE to check the invoice lines taxes.
for invoice in self.filtered(lambda move: move.is_invoice()):
for line in invoice.invoice_line_ids:
account_tax = line.account_id.tax_ids.ids
if account_tax and invoice.company_id.country_id.code == 'DE':
account_name = line.account_id.name
for tax in line.tax_ids:
if tax.id not in account_tax:
raise UserError(_('Account %s does not authorize to have tax %s specified on the line. \
Change the tax used in this invoice or remove all taxes from the account') % (account_name, tax.name))
return super()._post(soft)
class ProductTemplate(models.Model):
_inherit = "product.template"
+1 -1
View File
@@ -3574,7 +3574,7 @@
<record id="account_tax_template_s_irpf24_rdc" model="account.tax.template">
<field name="description">Retención 24% (Rendimientos del capital)</field>
<field name="type_tax_use">sale</field>
<field name="name">Retenciones a cuenta IRPF 24%</field>
<field name="name">Retenciones a cuenta IRPF 24% (Rendimientos del capital)</field>
<field name="chart_template_id" ref="l10n_es.account_chart_template_common"/>
<field name="amount" eval="-24"/>
<field name="amount_type">percent</field>
+1
View File
@@ -109,6 +109,7 @@ class Partner(models.Model):
invoice_vals_list.append({
'move_type': 'out_invoice',
'partner_id': partner.id,
'invoice_payment_term_id': partner.property_payment_term_id.id,
'invoice_line_ids': [
(0, None, {'product_id': product.id, 'quantity': 1, 'price_unit': amount, 'tax_ids': [(6, 0, product.taxes_id.ids)]})
]
@@ -158,3 +158,23 @@ class TestMembership(TestMembershipCommon):
self.partner_1._compute_membership_state()
self.assertEqual(invoice.state, 'cancel')
self.assertEqual(self.partner_1.membership_state, 'canceled')
def test_apply_payment_term(self):
"""
Check if the payment term defined on the partner is applied to the invoice
"""
pay_term_15_days_after_today = self.env['account.payment.term'].create({
'name': '15 days after today',
'line_ids': [
(0, 0, {
'value': 'balance',
'days': 15,
'option': 'day_after_invoice_date',
}),
],
})
self.partner_1.write({
'property_payment_term_id': pay_term_15_days_after_today.id,
})
invoice = self.partner_1.create_membership_invoice(self.membership_1, 100.0)
self.assertEqual(invoice.invoice_payment_term_id, pay_term_15_days_after_today)
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from datetime import datetime
from datetime import datetime, timedelta
from pytz import timezone, utc
from flectra import api, fields, models
@@ -73,7 +73,7 @@ class EventSponsor(models.Model):
for sponsor in self:
if not sponsor.event_id.is_ongoing:
sponsor.is_in_opening_hours = False
elif not sponsor.hour_from or not sponsor.hour_to:
elif sponsor.hour_from is False or sponsor.hour_to is False:
sponsor.is_in_opening_hours = True
else:
event_tz = timezone(sponsor.event_id.date_tz)
@@ -86,6 +86,9 @@ class EventSponsor(models.Model):
# compute opening hours
opening_from_tz = event_tz.localize(datetime.combine(now_tz.date(), float_to_time(sponsor.hour_from)))
opening_to_tz = event_tz.localize(datetime.combine(now_tz.date(), float_to_time(sponsor.hour_to)))
if sponsor.hour_to == 0:
# when closing 'at midnight', we consider it's at midnight the next day
opening_to_tz = opening_to_tz + timedelta(days=1)
opening_from = max([dt_begin, opening_from_tz])
opening_to = min([dt_end, opening_to_tz])
@@ -31,7 +31,7 @@ class TestSponsorData(TestEventTrackOnlineCommon):
@users('user_eventmanager')
def test_event_date_computation(self):
""" Test date computation. Pay attention that mocks returns UTC values, meaning
we have to take into account Europe/Brussels offset """
we have to take into account Europe/Brussels offset (+2 in July) """
event = self.env['event.event'].browse(self.event_0.id)
sponsor = self.env['event.sponsor'].browse(self.sponsor_0.id)
event.invalidate_cache(fnames=['is_ongoing'])
@@ -85,3 +85,36 @@ class TestSponsorData(TestEventTrackOnlineCommon):
sponsor.invalidate_cache(fnames=['is_in_opening_hours'])
self.assertFalse(sponsor.is_in_opening_hours)
self.assertFalse(event.is_ongoing)
# Use "00:00" as opening hours for sponsor -> should still work
event.invalidate_cache(fnames=['is_ongoing'])
sponsor.hour_from = 0.0 # 0 -> 18
# Inside opening hours (17 < 18)
self.mock_wevent_dt.now.return_value = datetime(2020, 7, 6, 15, 0, 1)
self.mock_wevent_exhib_dt.now.return_value = datetime(2020, 7, 6, 15, 0, 1)
sponsor.invalidate_cache(fnames=['is_in_opening_hours'])
self.assertTrue(sponsor.is_in_opening_hours)
# Outside opening hours (21 > 18)
self.mock_wevent_dt.now.return_value = datetime(2020, 7, 6, 19, 0, 1)
self.mock_wevent_exhib_dt.now.return_value = datetime(2020, 7, 6, 19, 0, 1)
sponsor.invalidate_cache(fnames=['is_in_opening_hours'])
self.assertFalse(sponsor.is_in_opening_hours)
# Use "00:00" as closing hours for sponsor -> should still work
# (considered 'at midnight the next day')
sponsor.hour_from = 10.0
sponsor.hour_to = 0.0
# Inside opening hours (11 > 10)
self.mock_wevent_dt.now.return_value = datetime(2020, 7, 6, 9, 0, 1)
self.mock_wevent_exhib_dt.now.return_value = datetime(2020, 7, 6, 9, 0, 1)
sponsor.invalidate_cache(fnames=['is_in_opening_hours'])
self.assertTrue(sponsor.is_in_opening_hours)
# Outside opening hours (7 < 10)
self.mock_wevent_dt.now.return_value = datetime(2020, 7, 6, 5, 0, 1)
self.mock_wevent_exhib_dt.now.return_value = datetime(2020, 7, 6, 5, 0, 1)
sponsor.invalidate_cache(fnames=['is_in_opening_hours'])
self.assertFalse(sponsor.is_in_opening_hours)
+4 -4
View File
@@ -9,10 +9,10 @@ from datetime import datetime
from psycopg2 import IntegrityError
from werkzeug.exceptions import BadRequest
from flectra import http, SUPERUSER_ID, _
from flectra import http, SUPERUSER_ID
from flectra.http import request
from flectra.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
from flectra.tools.translate import _
from flectra.tools.translate import _, _lt
from flectra.exceptions import ValidationError, UserError
from flectra.addons.base.models.ir_qweb_fields import nl2br
@@ -87,7 +87,7 @@ class WebsiteForm(http.Controller):
# Constants string to make metadata readable on a text field
_meta_label = "%s\n________\n\n" % _("Metadata") # Title for meta data
_meta_label = _lt("Metadata") # Title for meta data
# Dict of dynamically called filters following type of field to be fault tolerent
@@ -218,7 +218,7 @@ class WebsiteForm(http.Controller):
default_field_data = values.get(default_field.name, '')
custom_content = (default_field_data + "\n\n" if default_field_data else '') \
+ (_custom_label + custom + "\n\n" if custom else '') \
+ (self._meta_label + meta if meta else '')
+ (self._meta_label + "\n________\n\n" + meta if meta else '')
# If there is a default field configured for this model, use it.
# If there isn't, put the custom data in a message instead
+1 -1
View File
@@ -649,7 +649,7 @@ class WebsiteForum(WebsiteProfile):
down_votes = rec['vote_count']
# Votes which given by users on others questions and answers.
vote_ids = Vote.search([('user_id', '=', user.id)])
vote_ids = Vote.search([('user_id', '=', user.id), ('forum_id', 'in', forums.ids)])
# activity by user.
model, comment = Data.get_object_reference('mail', 'mt_comment')
+1 -1
View File
@@ -63,7 +63,6 @@
<record id="product.product_product_6" model="product.product">
<field name="is_published" eval="True"/>
<field name="website_sequence">10010</field>
</record>
<record id="product.product_product_7" model="product.product">
@@ -183,6 +182,7 @@
<field name="public_categ_ids" eval="[(6,0,[ref('public_category_cabinets')])]"/>
</record>
<record id="product.product_product_11_product_template" model="product.template">
<field name="website_sequence">9990</field>
<field name="public_categ_ids" eval="[(6,0,[ref('public_category_furnitures_chairs')])]"/>
</record>
<record id="product.product_product_12_product_template" model="product.template">
+23
View File
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
import logging
from flectra import api, fields, models, tools, _
from flectra.exceptions import ValidationError, UserError
@@ -7,6 +8,9 @@ from flectra.addons.http_routing.models.ir_http import slug
from flectra.addons.website.models import ir_http
from flectra.tools.translate import html_translate
from flectra.osv import expression
from psycopg2.extras import execute_values
_logger = logging.getLogger(__name__)
class ProductRibbon(models.Model):
@@ -339,6 +343,25 @@ class ProductTemplate(models.Model):
website = self.website_id or kwargs.get('website')
return website and website.company_id or res
def _init_column(self, column_name):
# to avoid generating a single default website_sequence when installing the module,
# we need to set the default row by row for this column
if column_name == "website_sequence":
_logger.debug("Table '%s': setting default value of new column %s to unique values for each row", self._table, column_name)
self.env.cr.execute("SELECT id FROM %s WHERE website_sequence IS NULL" % self._table)
prod_tmpl_ids = self.env.cr.dictfetchall()
max_seq = self._default_website_sequence()
query = """
UPDATE {table}
SET website_sequence = p.web_seq
FROM (VALUES %s) AS p(p_id, web_seq)
WHERE id = p.p_id
""".format(table=self._table)
values_args = [(prod_tmpl['id'], max_seq + i * 5) for i, prod_tmpl in enumerate(prod_tmpl_ids)]
execute_values(self.env.cr._obj, query, values_args)
else:
super(ProductTemplate, self)._init_column(column_name)
def _default_website_sequence(self):
''' We want new product to be the last (highest seq).
Every product should ideally have an unique sequence.