mirror of
https://gitlab.com/flectra-hq/flectra.git
synced 2025-02-25 18:55:21 -06:00
[PATCH] Upstream patch - 04022022
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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.'})
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
Reference in New Issue
Block a user