[PATCH] Upstream patch - 04022022

This commit is contained in:
Parthiv Patel
2022-02-04 10:53:42 +00:00
parent 7620a4466c
commit a5403bf50c
14 changed files with 100 additions and 24 deletions

View File

@@ -558,6 +558,7 @@ class AccountMove(models.Model):
'analytic_account_id': tax_line.tax_line_id.analytic and tax_line.analytic_account_id.id,
'tax_ids': [(6, 0, tax_line.tax_ids.ids)],
'tax_tag_ids': [(6, 0, tax_line.tax_tag_ids.ids)],
'partner_id': tax_line.partner_id.id,
}
@api.model
@@ -578,6 +579,7 @@ class AccountMove(models.Model):
'analytic_account_id': tax_vals['analytic'] and base_line.analytic_account_id.id,
'tax_ids': [(6, 0, tax_vals['tax_ids'])],
'tax_tag_ids': [(6, 0, tax_vals['tag_ids'])],
'partner_id': base_line.partner_id.id,
}
def _get_tax_force_sign(self):
@@ -766,7 +768,6 @@ class AccountMove(models.Model):
**to_write_on_line,
'name': tax.name,
'move_id': self.id,
'partner_id': line.partner_id.id,
'company_id': line.company_id.id,
'company_currency_id': line.company_currency_id.id,
'tax_base_amount': tax_base_amount,
@@ -1843,7 +1844,7 @@ class AccountMove(models.Model):
'''
self.ensure_one()
for line in self.line_ids:
for line in self.line_ids.filtered(lambda l: not l.display_type):
analytic_account = line._cache.get('analytic_account_id')
# Do something only on invoice lines.
@@ -1853,7 +1854,7 @@ class AccountMove(models.Model):
# Shortcut to load the demo data.
# Doing line.account_id triggers a default_get(['account_id']) that could returns a result.
# A section / note must not have an account_id set.
if not line._cache.get('account_id') and not line.display_type and not line._origin:
if not line._cache.get('account_id') and not line._origin:
line.account_id = line._get_computed_account() or self.journal_id.default_account_id
if line.product_id and not line._cache.get('name'):
line.name = line._get_computed_name()

View File

@@ -3166,3 +3166,29 @@ class TestAccountMoveOutInvoiceOnchanges(AccountTestInvoicingCommon):
})],
})
self.assertRecordValues(invoice.invoice_line_ids, [{'account_id': other_income_account.id}])
def test_out_invoice_note_and_tax_partner_is_set(self):
# Make sure that, when creating an invoice by giving a list of lines with the last one being a note,
# the partner_id of the tax line is properly set.
invoice_vals_list = [{
'move_type': 'out_invoice',
'currency_id': self.currency_data['currency'].id,
'partner_id': self.partner_a.id,
'journal_id': self.company_data['default_journal_sale'].id,
'invoice_line_ids': [
(0, 0, {
'name': 'My super product.',
'quantity': 1.0,
'price_unit': 750.0,
'tax_ids': [(6, 0, self.product_a.taxes_id.ids)],
}),
(0, 0, {
'display_type': 'line_note',
'name': 'This is a note',
'account_id': False,
}),
],
}]
moves = self.env['account.move'].create(invoice_vals_list)
tax_line = moves.line_ids.filtered('tax_line_id')
self.assertEqual(tax_line.partner_id.id, self.partner_a.id)

View File

@@ -41,12 +41,12 @@ class AccountPayment(models.Model):
@api.constrains('check_number', 'journal_id')
def _constrains_check_number(self):
if not self:
payment_checks = self.filtered('check_number')
if not payment_checks:
return
try:
self.mapped(lambda p: str(int(p.check_number)))
except ValueError:
raise ValidationError(_('Check numbers can only consist of digits'))
for payment_check in payment_checks:
if not payment_check.check_number.isdecimal():
raise ValidationError(_('Check numbers can only consist of digits'))
self.flush()
self.env.cr.execute("""
SELECT payment.check_number, move.journal_id
@@ -61,8 +61,10 @@ class AccountPayment(models.Model):
AND payment.id IN %(ids)s
AND move.state = 'posted'
AND other_move.state = 'posted'
AND payment.check_number IS NOT NULL
AND other_payment.check_number IS NOT NULL
""", {
'ids': tuple(self.ids),
'ids': tuple(payment_checks.ids),
})
res = self.env.cr.dictfetchall()
if res:

View File

@@ -44,7 +44,7 @@
<ram:NetPriceProductTradePrice>
<ram:ChargeAmount
t-att-currencyID="currency.name"
t-esc="format_monetary(line.price_subtotal/line.quantity, currency)"/>
t-esc="format_monetary(line.price_subtotal/line.quantity if line.quantity else 0, currency)"/>
</ram:NetPriceProductTradePrice>
</ram:SpecifiedLineTradeAgreement>

View File

@@ -35,11 +35,18 @@ class Users(models.Model):
type(self).SELF_READABLE_FIELDS = self.SELF_READABLE_FIELDS + ['totp_enabled', 'totp_trusted_device_ids']
return init_res
def _mfa_type(self):
r = super()._mfa_type()
if r is not None:
return r
if self.totp_enabled:
return 'totp'
def _mfa_url(self):
r = super()._mfa_url()
if r is not None:
return r
if self.totp_enabled:
if self._mfa_type() == 'totp':
return '/web/login/totp'
@api.depends('totp_secret')

View File

@@ -81,7 +81,7 @@ class HolidaysRequest(models.Model):
if 'state' in fields_list and not defaults.get('state'):
lt = self.env['hr.leave.type'].browse(defaults.get('holiday_status_id'))
defaults['state'] = 'confirm' if lt and lt.leave_validation_type != 'no_validation' else 'draft'
defaults['state'] = 'confirm'
now = fields.Datetime.now()
if 'date_from' not in defaults:

View File

@@ -247,6 +247,7 @@
<!--Not used anymore since Q3 2021; replaced by grids 120, 122, 123 and 124-->
<field name="name">mod303[61]</field>
<field name="applicability">taxes</field>
<field name="active" eval="False"/>
<field name="country_id" ref="base.es"/>
</record>
<record id="mod_303_120" model="account.account.tag">

View File

@@ -3,17 +3,19 @@
import base64
from datetime import timedelta
from freezegun import freeze_time
from flectra.addons.account.tests.common import AccountTestInvoicingCommon
from flectra.tests import tagged
from flectra import fields
@freeze_time('2021-05-02')
@tagged('post_install', '-at_install')
class TestAccountFrFec(AccountTestInvoicingCommon):
@classmethod
def setUpClass(cls, chart_template_ref=None):
def setUpClass(cls, chart_template_ref='l10n_fr.l10n_fr_pcg_chart_template'):
super().setUpClass(chart_template_ref=chart_template_ref)
company = cls.company_data['company']
@@ -47,14 +49,13 @@ class TestAccountFrFec(AccountTestInvoicingCommon):
def test_generate_fec_sanitize_pieceref(self):
self.wizard.generate_fec()
today = fields.Date.today().strftime('%Y%m%d')
expected_content = (
"JournalCode|JournalLib|EcritureNum|EcritureDate|CompteNum|CompteLib|CompAuxNum|CompAuxLib|PieceRef|PieceDate|EcritureLib|Debit|Credit|EcritureLet|DateLet|ValidDate|Montantdevise|Idevise\r\n"
f"INV|Customer Invoices|INV/2021/11/0001|{today}|400000|Product Sales|||-|{today}|Hello Darkness|0,00| 000000000001437,12|||{today}|-000000000001437,12|USD\r\n"
f"INV|Customer Invoices|INV/2021/11/0001|{today}|400000|Product Sales|||-|{today}|my old friend|0,00| 000000000001676,64|||{today}|-000000000001676,64|USD\r\n"
f"INV|Customer Invoices|INV/2021/11/0001|{today}|400000|Product Sales|||-|{today}|/|0,00| 000000000003353,28|||{today}|-000000000003353,28|USD\r\n"
f"INV|Customer Invoices|INV/2021/11/0001|{today}|251000|Tax Received|||-|{today}|Tax 15.00%|0,00| 000000000000970,06|||{today}|-000000000000970,06|USD\r\n"
f"INV|Customer Invoices|INV/2021/11/0001|{today}|121000|Account Receivable|{self.partner_a.id}|partner_a|-|{today}|INV/2021/11/0001| 000000000007437,10|0,00|||{today}| 000000000007437,10|USD"
"INV|Customer Invoices|INV/2021/05/0001|20210502|701100|Ventes de produits finis (ou groupe) A|||-|20210502|Hello Darkness|0,00| 000000000001437,12|||20210502|-000000000001437,12|EUR\r\n"
"INV|Customer Invoices|INV/2021/05/0001|20210502|701100|Ventes de produits finis (ou groupe) A|||-|20210502|my old friend|0,00| 000000000001676,64|||20210502|-000000000001676,64|EUR\r\n"
"INV|Customer Invoices|INV/2021/05/0001|20210502|701100|Ventes de produits finis (ou groupe) A|||-|20210502|/|0,00| 000000000003353,28|||20210502|-000000000003353,28|EUR\r\n"
"INV|Customer Invoices|INV/2021/05/0001|20210502|445710|TVA collectée|||-|20210502|TVA collectée (vente) 20,0%|0,00| 000000000001293,41|||20210502|-000000000001293,41|EUR\r\n"
f"INV|Customer Invoices|INV/2021/05/0001|20210502|411100|Clients - Ventes de biens ou de prestations de services|{self.partner_a.id}|partner_a|-|20210502|INV/2021/05/0001| 000000000007760,45|0,00|||20210502| 000000000007760,45|EUR"
)
content = base64.b64decode(self.wizard.fec_data).decode()
self.assertEqual(expected_content, content)

View File

@@ -1764,6 +1764,7 @@ class SaleOrderLine(models.Model):
args or [],
['|', ('order_id.name', operator, name), ('name', operator, name)]
])
return self._search(args, limit=limit, access_rights_uid=name_get_uid)
return super(SaleOrderLine, self)._name_search(name, args=args, operator=operator, limit=limit, name_get_uid=name_get_uid)
def _check_line_unlink(self):

View File

@@ -103,7 +103,12 @@ class CouponProgram(models.Model):
return self.filtered(lambda program: program.promo_code_usage == 'code_needed' and program.promo_code != order.promo_code)
def _filter_unexpired_programs(self, order):
return self.filtered(lambda program: program.maximum_use_number == 0 or program.order_count < program.maximum_use_number)
return self.filtered(
lambda program: program.maximum_use_number == 0
or program.order_count < program.maximum_use_number
or program
in (order.code_promo_program_id + order.no_code_promo_program_ids)
)
def _filter_programs_on_partners(self, order):
return self.filtered(lambda program: program._is_valid_partner(order.partner_id))

View File

@@ -1200,3 +1200,28 @@ class TestSaleCouponProgramNumbers(TestSaleCouponCommon):
order2.recompute_coupon_lines()
self.assertEqual(order2.amount_total, 22.5, "10% discount should be applied")
self.assertEqual(len(order2.order_line.ids), 2, "discount should be applied")
def test_program_maximum_use_number_last_order(self):
# reuse p1 with a different promo code and a maximum_use_number of 1
self.p1.promo_code = 'promo1'
self.p1.maximum_use_number = 1
# check that the discount is applied on the first order
order = self.empty_order
self.env['sale.order.line'].create({
'product_id': self.drawerBlack.id,
'product_uom_qty': 1.0,
'order_id': order.id,
})
self.env['sale.coupon.apply.code'].sudo().apply_coupon(order, 'promo1')
order.recompute_coupon_lines()
self.assertEqual(order.amount_total, 22.5, "10% discount should be applied")
self.assertEqual(len(order.order_line.ids), 2, "discount should be applied")
# duplicating to mimic website behavior (each refresh to /shop/cart
# recompute coupon lines if website_sale_coupon is installed)
order.recompute_coupon_lines()
self.assertEqual(order.amount_total, 22.5, "10% discount should be applied")
self.assertEqual(len(order.order_line.ids), 2, "discount should be applied")
# applying the code again should return that it has been expired.
self.assertDictEqual(self.env['sale.coupon.apply.code'].sudo().apply_coupon(order, 'promo1'), {'error': 'Promo code promo1 has been expired.'})

View File

@@ -29,7 +29,7 @@
<!-- add needaction_menu_ref to reload quotation needaction when opportunity needaction is reloaded -->
<record id="crm.crm_lead_opportunities" model="ir.actions.act_window">
<field name="context">{'default_move_type': 'opportunity', 'default_user_id': uid}</field>
<field name="context">{'default_type': 'opportunity', 'default_user_id': uid}</field>
</record>
<record id="sales_team.mail_activity_type_action_config_sales" model="ir.actions.act_window">

View File

@@ -81,6 +81,9 @@ class StockLandedCost(models.Model):
@api.depends('company_id')
def _compute_allowed_picking_ids(self):
# Backport of f329de26: allowed_picking_ids is useless, view_stock_landed_cost_form no longer uses it,
# the field and its compute are kept since this is a stable version. Still, this compute has been made
# more resilient to MemoryErrors.
valued_picking_ids_per_company = defaultdict(list)
if self.company_id:
self.env.cr.execute("""SELECT sm.picking_id, sm.company_id
@@ -91,7 +94,10 @@ class StockLandedCost(models.Model):
for res in self.env.cr.fetchall():
valued_picking_ids_per_company[res[1]].append(res[0])
for cost in self:
cost.allowed_picking_ids = valued_picking_ids_per_company[cost.company_id.id]
n = 5000
cost.allowed_picking_ids = valued_picking_ids_per_company[cost.company_id.id][:n]
for ids_chunk in tools.split_every(n, valued_picking_ids_per_company[cost.company_id.id][n:]):
cost.allowed_picking_ids = tuple((4, id_) for id_ in ids_chunk)
@api.onchange('target_model')
def _onchange_target_model(self):

View File

@@ -29,9 +29,10 @@
<group>
<group>
<field name="date"/>
<field name="allowed_picking_ids" invisible="1"/>
<field name="target_model" widget="radio" invisible="1"/>
<field name="picking_ids" widget="many2many_tags" options="{'no_create_edit': True}" domain="[('id', 'in', allowed_picking_ids)]" attrs="{'invisible': [('target_model', '!=', 'picking')]}"/>
<field name="picking_ids" widget="many2many_tags"
options="{'no_create_edit': True}" attrs="{'invisible': [('target_model', '!=', 'picking')]}"
domain="[('company_id', '=', company_id), ('move_lines.stock_valuation_layer_ids', '!=', False)]"/>
</group>
<group>
<label for="account_journal_id" string="Journal"/>