mirror of
https://gitlab.com/flectra-hq/flectra.git
synced 2025-02-25 18:55:21 -06:00
[PATCH] Upstream patch - 13012023
This commit is contained in:
@@ -1406,6 +1406,30 @@ class AccountMove(models.Model):
|
||||
'line_ids.payment_id.state',
|
||||
'line_ids.full_reconcile_id')
|
||||
def _compute_amount(self):
|
||||
in_invoices = self.filtered(lambda m: m.move_type == 'in_invoice')
|
||||
out_invoices = self.filtered(lambda m: m.move_type == 'out_invoice')
|
||||
others = self.filtered(lambda m: m.move_type not in ('in_invoice', 'out_invoice'))
|
||||
reversed_mapping = defaultdict(lambda: self.env['account.move'])
|
||||
for reverse_move in self.env['account.move'].search([
|
||||
('state', '=', 'posted'),
|
||||
'|', '|',
|
||||
'&', ('reversed_entry_id', 'in', in_invoices.ids), ('move_type', '=', 'in_refund'),
|
||||
'&', ('reversed_entry_id', 'in', out_invoices.ids), ('move_type', '=', 'out_refund'),
|
||||
'&', ('reversed_entry_id', 'in', others.ids), ('move_type', '=', 'entry'),
|
||||
]):
|
||||
reversed_mapping[reverse_move.reversed_entry_id] += reverse_move
|
||||
|
||||
caba_mapping = defaultdict(lambda: self.env['account.move'])
|
||||
caba_company_ids = self.company_id.filtered(lambda c: c.tax_exigibility)
|
||||
reverse_moves_ids = [move.id for moves in reversed_mapping.values() for move in moves]
|
||||
for caba_move in self.env['account.move'].search([
|
||||
('tax_cash_basis_move_id', 'in', self.ids + reverse_moves_ids),
|
||||
('state', '=', 'posted'),
|
||||
('move_type', '=', 'entry'),
|
||||
('company_id', 'in', caba_company_ids.ids)
|
||||
]):
|
||||
caba_mapping[caba_move.tax_cash_basis_move_id] += caba_move
|
||||
|
||||
for move in self:
|
||||
|
||||
if move.payment_state == 'invoicing_legacy':
|
||||
@@ -1484,17 +1508,10 @@ class AccountMove(models.Model):
|
||||
new_pmt_state = 'partial'
|
||||
|
||||
if new_pmt_state == 'paid' and move.move_type in ('in_invoice', 'out_invoice', 'entry'):
|
||||
reverse_type = move.move_type == 'in_invoice' and 'in_refund' or move.move_type == 'out_invoice' and 'out_refund' or 'entry'
|
||||
reverse_moves = self.env['account.move'].search([('reversed_entry_id', '=', move.id), ('state', '=', 'posted'), ('move_type', '=', reverse_type)])
|
||||
if self.env.company.tax_exigibility:
|
||||
domain = [
|
||||
('tax_cash_basis_move_id', 'in', move.ids + reverse_moves.ids),
|
||||
('state', '=', 'posted'),
|
||||
('move_type', '=', 'entry')
|
||||
]
|
||||
caba_moves = self.env['account.move'].search(domain)
|
||||
else:
|
||||
caba_moves = self.env['account.move']
|
||||
reverse_moves = reversed_mapping[move]
|
||||
caba_moves = caba_mapping[move]
|
||||
for reverse_move in reverse_moves:
|
||||
caba_moves |= caba_mapping[reverse_move]
|
||||
|
||||
# We only set 'reversed' state in cas of 1 to 1 full reconciliation with a reverse entry; otherwise, we use the regular 'paid' state
|
||||
# We ignore potentials cash basis moves reconciled because the transition account of the tax is reconcilable
|
||||
@@ -4049,6 +4066,18 @@ class AccountMoveLine(models.Model):
|
||||
if line.reconciled:
|
||||
raise UserError(_('Lines from "Off-Balance Sheet" accounts cannot be reconciled'))
|
||||
|
||||
@api.constrains('product_uom_id')
|
||||
def _check_product_uom_category_id(self):
|
||||
for line in self:
|
||||
if line.product_uom_id and line.product_id and line.product_uom_id.category_id != line.product_id.product_tmpl_id.uom_id.category_id:
|
||||
raise UserError(_(
|
||||
"The Unit of Measure (UoM) '%s' you have selected for product '%s', "
|
||||
"is incompatible with its category : %s.",
|
||||
line.product_uom_id.name,
|
||||
line.product_id.name,
|
||||
line.product_id.product_tmpl_id.uom_id.category_id.name
|
||||
))
|
||||
|
||||
def _affect_tax_report(self):
|
||||
self.ensure_one()
|
||||
return self.tax_ids or self.tax_line_id or self.tax_tag_ids.filtered(lambda x: x.applicability == "taxes")
|
||||
|
||||
@@ -56,13 +56,26 @@ class ProductTemplate(models.Model):
|
||||
|
||||
@api.constrains('uom_id')
|
||||
def _check_uom_not_in_invoice(self):
|
||||
for template in self:
|
||||
aml_domain = [('product_id.product_tmpl_id.id', '=', template.id),
|
||||
('product_uom_id.category_id.id', '!=', template.uom_id.category_id.id),
|
||||
]
|
||||
if self.env['account.move.line'].sudo().search(aml_domain, limit=1):
|
||||
raise ValidationError(_("This product is already being used in posted Journal Entries.\n"
|
||||
"If you want to change its Unit of Measure, please archive this product and create a new one."))
|
||||
self.env['product.template'].flush(['uom_id'])
|
||||
self._cr.execute("""
|
||||
SELECT prod_template.id
|
||||
FROM account_move_line line
|
||||
JOIN product_product prod_variant ON line.product_id = prod_variant.id
|
||||
JOIN product_template prod_template ON prod_variant.product_tmpl_id = prod_template.id
|
||||
JOIN uom_uom template_uom ON prod_template.uom_id = template_uom.id
|
||||
JOIN uom_category template_uom_cat ON template_uom.category_id = template_uom_cat.id
|
||||
JOIN uom_uom line_uom ON line.product_uom_id = line_uom.id
|
||||
JOIN uom_category line_uom_cat ON line_uom.category_id = line_uom_cat.id
|
||||
WHERE prod_template.id IN %s
|
||||
AND line.parent_state = 'posted'
|
||||
AND template_uom_cat.id != line_uom_cat.id
|
||||
LIMIT 1
|
||||
""", [tuple(self.ids)])
|
||||
if self._cr.fetchall():
|
||||
raise ValidationError(_(
|
||||
"This product is already being used in posted Journal Entries.\n"
|
||||
"If you want to change its Unit of Measure, please archive this product and create a new one."
|
||||
))
|
||||
|
||||
|
||||
class ProductProduct(models.Model):
|
||||
|
||||
@@ -677,6 +677,7 @@
|
||||
<tree decoration-danger="is_refused" editable="bottom">
|
||||
<field name="date" optional="show"/>
|
||||
<field name="name"/>
|
||||
<field name="employee_id" invisible="1"/>
|
||||
<field name="state" invisible="1"/>
|
||||
<field name="reference" optional="hide"/>
|
||||
<field name="analytic_account_id" optional="show" domain="['|', ('company_id', '=', parent.company_id), ('company_id', '=', False)]" groups="analytic.group_analytic_accounting"/>
|
||||
|
||||
@@ -43,6 +43,7 @@ Here is how it works:
|
||||
'report/swissqr_report.xml',
|
||||
'views/res_bank_view.xml',
|
||||
'views/account_invoice_view.xml',
|
||||
'views/account_invoice.xml',
|
||||
'views/res_config_settings_views.xml',
|
||||
'views/setup_wizard_views.xml',
|
||||
],
|
||||
|
||||
@@ -304,6 +304,8 @@ class ResPartnerBank(models.Model):
|
||||
# see https://github.com/arthurdejong/python-stdnum/blob/master/stdnum/iso11649.py
|
||||
|
||||
def _eligible_for_qr_code(self, qr_method, debtor_partner, currency):
|
||||
if qr_method == 'sct_qr' and debtor_partner.country_id.code == 'CH' and self.journal_id.country_code == 'CH':
|
||||
return False
|
||||
if qr_method == 'ch_qr':
|
||||
|
||||
return self.acc_type == 'iban' and \
|
||||
|
||||
8
addons/l10n_ch/views/account_invoice.xml
Normal file
8
addons/l10n_ch/views/account_invoice.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0"?>
|
||||
<flectra>
|
||||
<template id="l10n_ch_report_invoice_document" inherit_id="account.report_invoice_document">
|
||||
<xpath expr="//div[@id='qrcode']" position="attributes">
|
||||
<attribute name="t-if" add="and o.qr_code_method != 'ch_qr'" separator=" "/>
|
||||
</xpath>
|
||||
</template>
|
||||
</flectra>
|
||||
@@ -119,8 +119,7 @@
|
||||
<IdPaese t-esc="buyer.country_id.code"/>
|
||||
<IdCodice t-esc="'0000000'"/>
|
||||
</IdFiscaleIVA>
|
||||
<CodiceFiscale t-if="not buyer.vat and buyer.l10n_it_codice_fiscale" t-esc="normalize_codice_fiscale(buyer.l10n_it_codice_fiscale)"/>
|
||||
<CodiceFiscale t-elif="not buyer.vat and not buyer.l10n_it_codice_fiscale" t-esc="99999999999"/>
|
||||
<CodiceFiscale t-if="buyer.l10n_it_codice_fiscale" t-esc="normalize_codice_fiscale(buyer.l10n_it_codice_fiscale)"/>
|
||||
<Anagrafica>
|
||||
<t t-if="buyer_is_company">
|
||||
<Denominazione t-esc="format_alphanumeric(buyer.display_name[:80])"/>
|
||||
|
||||
@@ -371,6 +371,17 @@ class AccountEdiFormat(models.Model):
|
||||
return self._import_fattura_pa(decoded_content, invoice)
|
||||
return super()._update_invoice_from_binary(filename, content, extension, invoice)
|
||||
|
||||
def _convert_date_from_xml(self, xsdate_str):
|
||||
""" Dates in FatturaPA are ISO 8601 date format, pattern '[-]CCYY-MM-DD[Z|(+|-)hh:mm]' """
|
||||
xsdate_str = xsdate_str.strip()
|
||||
xsdate_pattern = r"^-?(?P<date>-?\d{4}-\d{2}-\d{2})(?P<tz>[zZ]|[+-]\d{2}:\d{2})?$"
|
||||
try:
|
||||
match = re.match(xsdate_pattern, xsdate_str)
|
||||
converted_date = datetime.strptime(match.group("date"), DEFAULT_FACTUR_ITALIAN_DATE_FORMAT).date()
|
||||
except Exception:
|
||||
converted_date = False
|
||||
return converted_date
|
||||
|
||||
def _import_fattura_pa(self, tree, invoice):
|
||||
""" Decodes a fattura_pa invoice into an invoice.
|
||||
|
||||
@@ -473,9 +484,14 @@ class AccountEdiFormat(models.Model):
|
||||
# Date. <2.1.1.3>
|
||||
elements = body_tree.xpath('.//DatiGeneraliDocumento/Data')
|
||||
if elements:
|
||||
date_str = elements[0].text
|
||||
date_obj = datetime.strptime(date_str, DEFAULT_FACTUR_ITALIAN_DATE_FORMAT)
|
||||
invoice_form.invoice_date = date_obj
|
||||
document_date = self._convert_date_from_xml(elements[0].text)
|
||||
if document_date:
|
||||
invoice_form.invoice_date = document_date
|
||||
else:
|
||||
message_to_log.append("%s<br/>%s" % (
|
||||
_("Document date invalid in XML file:"),
|
||||
invoice._compose_info_message(elements[0], '.')
|
||||
))
|
||||
|
||||
# Dati Bollo. <2.1.1.6>
|
||||
elements = body_tree.xpath('.//DatiGeneraliDocumento/DatiBollo/ImportoBollo')
|
||||
@@ -508,9 +524,16 @@ class AccountEdiFormat(models.Model):
|
||||
# Due date. <2.4.2.5>
|
||||
elements = body_tree.xpath('.//DatiPagamento/DettaglioPagamento/DataScadenzaPagamento')
|
||||
if elements:
|
||||
date_str = elements[0].text
|
||||
date_obj = datetime.strptime(date_str, DEFAULT_FACTUR_ITALIAN_DATE_FORMAT)
|
||||
invoice_form.invoice_date_due = fields.Date.to_string(date_obj)
|
||||
date_str = elements[0].text.strip()
|
||||
if date_str:
|
||||
due_date = self._convert_date_from_xml(date_str)
|
||||
if due_date:
|
||||
invoice_form.invoice_date_due = fields.Date.to_string(due_date)
|
||||
else:
|
||||
message_to_log.append("%s<br/>%s" % (
|
||||
_("Payment due date invalid in XML file:"),
|
||||
invoice._compose_info_message(elements[0], '.')
|
||||
))
|
||||
|
||||
# Total amount. <2.4.2.6>
|
||||
elements = body_tree.xpath('.//ImportoPagamento')
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
<IdPaese>IT</IdPaese>
|
||||
<IdCodice>00465840031</IdCodice>
|
||||
</IdFiscaleIVA>
|
||||
<CodiceFiscale>93026890017</CodiceFiscale>
|
||||
<Anagrafica>
|
||||
<Denominazione>Alessi</Denominazione>
|
||||
</Anagrafica>
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
<IdPaese>IT</IdPaese>
|
||||
<IdCodice>01234560157</IdCodice>
|
||||
</IdFiscaleIVA>
|
||||
<CodiceFiscale>01234560157</CodiceFiscale>
|
||||
<Anagrafica>
|
||||
<Denominazione>company_2_data</Denominazione>
|
||||
</Anagrafica>
|
||||
|
||||
@@ -80,7 +80,7 @@ class TestItEdi(AccountEdiTestCommon):
|
||||
cls.italian_partner_a = cls.env['res.partner'].create({
|
||||
'name': 'Alessi',
|
||||
'vat': 'IT00465840031',
|
||||
'l10n_it_codice_fiscale': '00465840031',
|
||||
'l10n_it_codice_fiscale': '93026890017',
|
||||
'country_id': cls.env.ref('base.it').id,
|
||||
'street': 'Via Privata Alessi 6',
|
||||
'zip': '28887',
|
||||
|
||||
@@ -464,11 +464,7 @@ class TestPointOfSaleHttpCommon(flectra.tests.HttpCase):
|
||||
|
||||
# Change the default sale pricelist of customers,
|
||||
# so the js tests can expect deterministically this pricelist when selecting a customer.
|
||||
env['ir.property']._set_default(
|
||||
"property_product_pricelist",
|
||||
"res.partner",
|
||||
public_pricelist,
|
||||
)
|
||||
env['ir.property']._set_default("property_product_pricelist", "res.partner", public_pricelist, main_company)
|
||||
|
||||
|
||||
@flectra.tests.tagged('post_install', '-at_install')
|
||||
|
||||
@@ -107,7 +107,8 @@ class SaleReport(models.Model):
|
||||
if not fields:
|
||||
fields = {}
|
||||
res = super()._query(with_clause, fields, groupby, from_clause)
|
||||
sale_fields = self._select_additional_fields(fields)
|
||||
current = '(SELECT %s FROM %s GROUP BY %s)' % \
|
||||
(self._select_pos(fields), self._from_pos(), self._group_by_pos())
|
||||
(self._select_pos(sale_fields), self._from_pos(), self._group_by_pos())
|
||||
|
||||
return '%s UNION ALL %s' % (res, current)
|
||||
|
||||
@@ -212,26 +212,25 @@ class Pricelist(models.Model):
|
||||
continue
|
||||
|
||||
if rule.base == 'pricelist' and rule.base_pricelist_id:
|
||||
price_tmp = rule.base_pricelist_id._compute_price_rule([(product, qty, partner)], date, uom_id)[product.id][0] # TDE: 0 = price, 1 = rule
|
||||
price = rule.base_pricelist_id.currency_id._convert(price_tmp, self.currency_id, self.env.company, date, round=False)
|
||||
price = rule.base_pricelist_id._compute_price_rule([(product, qty, partner)], date, uom_id)[product.id][0] # TDE: 0 = price, 1 = rule
|
||||
src_currency = rule.base_pricelist_id.currency_id
|
||||
else:
|
||||
# if base option is public price take sale price else cost price of product
|
||||
# price_compute returns the price in the context UoM, i.e. qty_uom_id
|
||||
price = product.price_compute(rule.base)[product.id]
|
||||
if rule.base == 'standard_price':
|
||||
src_currency = product.cost_currency_id
|
||||
else:
|
||||
src_currency = product.currency_id
|
||||
|
||||
if src_currency != self.currency_id:
|
||||
price = src_currency._convert(
|
||||
price, self.currency_id, self.env.company, date, round=False)
|
||||
|
||||
if price is not False:
|
||||
# pass the date through the context for further currency conversions
|
||||
rule_with_date_context = rule.with_context(date=date)
|
||||
price = rule_with_date_context._compute_price(price, price_uom, product, quantity=qty, partner=partner)
|
||||
price = rule._compute_price(price, price_uom, product, quantity=qty, partner=partner)
|
||||
suitable_rule = rule
|
||||
break
|
||||
# Final price conversion into pricelist currency
|
||||
if suitable_rule and suitable_rule.compute_price != 'fixed' and suitable_rule.base != 'pricelist':
|
||||
if suitable_rule.base == 'standard_price':
|
||||
cur = product.cost_currency_id
|
||||
else:
|
||||
cur = product.currency_id
|
||||
price = cur._convert(price, self.currency_id, self.env.company, date, round=False)
|
||||
|
||||
if not suitable_rule:
|
||||
cur = product.currency_id
|
||||
@@ -582,7 +581,6 @@ class PricelistItem(models.Model):
|
||||
The unused parameters are there to make the full context available for overrides.
|
||||
"""
|
||||
self.ensure_one()
|
||||
date = self.env.context.get('date') or fields.Date.today()
|
||||
convert_to_price_uom = (lambda price: product.uom_id._compute_price(price, price_uom))
|
||||
if self.compute_price == 'fixed':
|
||||
price = convert_to_price_uom(self.fixed_price)
|
||||
@@ -592,30 +590,19 @@ class PricelistItem(models.Model):
|
||||
# complete formula
|
||||
price_limit = price
|
||||
price = (price - (price * (self.price_discount / 100))) or 0.0
|
||||
if self.base == 'standard_price':
|
||||
price_currency = product.cost_currency_id
|
||||
elif self.base == 'pricelist':
|
||||
price_currency = self.currency_id # Already converted before to the pricelist currency
|
||||
else:
|
||||
price_currency = product.currency_id
|
||||
|
||||
if self.price_round:
|
||||
price = tools.float_round(price, precision_rounding=self.price_round)
|
||||
|
||||
def convert_to_base_price_currency(amount):
|
||||
return self.currency_id._convert(amount, price_currency, self.env.company, date, round=False)
|
||||
|
||||
if self.price_surcharge:
|
||||
price_surcharge = convert_to_base_price_currency(self.price_surcharge)
|
||||
price_surcharge = convert_to_price_uom(price_surcharge)
|
||||
price += price_surcharge
|
||||
price += convert_to_price_uom(self.price_surcharge)
|
||||
|
||||
if self.price_min_margin:
|
||||
price_min_margin = convert_to_base_price_currency(self.price_min_margin)
|
||||
price_min_margin = convert_to_price_uom(price_min_margin)
|
||||
price_min_margin = convert_to_price_uom(self.price_min_margin)
|
||||
price = max(price, price_limit + price_min_margin)
|
||||
|
||||
if self.price_max_margin:
|
||||
price_max_margin = convert_to_base_price_currency(self.price_max_margin)
|
||||
price_max_margin = convert_to_price_uom(price_max_margin)
|
||||
price_max_margin = convert_to_price_uom(self.price_max_margin)
|
||||
price = min(price, price_limit + price_max_margin)
|
||||
|
||||
return price
|
||||
|
||||
@@ -257,3 +257,24 @@ class TestProductPricelist(TransactionCase):
|
||||
})
|
||||
# product price use the currency of the pricelist
|
||||
self.assertEqual(product.price, 10090)
|
||||
|
||||
def test_23_diff_curr_rounding(self):
|
||||
""" Make sure rounding is applied after the currency conversion"""
|
||||
pricelist = self.ProductPricelist.create({
|
||||
'name': 'Currency Pricelist',
|
||||
'currency_id': self.new_currency.id,
|
||||
'item_ids': [(0, 0, {
|
||||
'compute_price': 'formula',
|
||||
'base': 'list_price',
|
||||
'price_discount': 42.328745867,
|
||||
'price_round': 1.00,
|
||||
})]
|
||||
})
|
||||
|
||||
product = self.computer_SC234
|
||||
product.lst_price = 450.0
|
||||
product = product.with_context({
|
||||
'pricelist': pricelist.id, 'quantity': 1
|
||||
})
|
||||
|
||||
self.assertEqual(product.price, 2595)
|
||||
|
||||
@@ -144,12 +144,23 @@ class SaleReport(models.Model):
|
||||
""" % (groupby)
|
||||
return groupby_
|
||||
|
||||
def _select_additional_fields(self, fields):
|
||||
"""Hook to return additional fields SQL specification for select part of the table query.
|
||||
|
||||
:param dict fields: additional fields info provided by _query overrides (old API), prefer overriding
|
||||
_select_additional_fields instead.
|
||||
:returns: mapping field -> SQL computation of the field
|
||||
:rtype: dict
|
||||
"""
|
||||
return fields
|
||||
|
||||
def _query(self, with_clause='', fields=None, groupby='', from_clause=''):
|
||||
if not fields:
|
||||
fields = {}
|
||||
sale_report_fields = self._select_additional_fields(fields)
|
||||
with_ = ("WITH %s" % with_clause) if with_clause else ""
|
||||
return '%s (SELECT %s FROM %s WHERE l.display_type IS NULL GROUP BY %s)' % \
|
||||
(with_, self._select_sale(fields), self._from_sale(from_clause), self._group_by_sale(groupby))
|
||||
(with_, self._select_sale(sale_report_fields), self._from_sale(from_clause), self._group_by_sale(groupby))
|
||||
|
||||
def init(self):
|
||||
# self._table = sale_report
|
||||
|
||||
@@ -9,6 +9,6 @@ class SaleReport(models.Model):
|
||||
|
||||
margin = fields.Float('Margin')
|
||||
|
||||
def _query(self, with_clause='', fields={}, groupby='', from_clause=''):
|
||||
def _select_additional_fields(self, fields):
|
||||
fields['margin'] = ", SUM(l.margin / CASE COALESCE(s.currency_rate, 0) WHEN 0 THEN 1.0 ELSE s.currency_rate END) AS margin"
|
||||
return super(SaleReport, self)._query(with_clause, fields, groupby, from_clause)
|
||||
return super()._select_additional_fields(fields)
|
||||
|
||||
@@ -9,7 +9,11 @@ class SaleReport(models.Model):
|
||||
|
||||
warehouse_id = fields.Many2one('stock.warehouse', 'Warehouse', readonly=True)
|
||||
|
||||
def _query(self, with_clause='', fields={}, groupby='', from_clause=''):
|
||||
def _group_by_sale(self, groupby=''):
|
||||
res = super()._group_by_sale(groupby)
|
||||
res += """, s.warehouse_id"""
|
||||
return res
|
||||
|
||||
def _select_additional_fields(self, fields):
|
||||
fields['warehouse_id'] = ", s.warehouse_id as warehouse_id"
|
||||
groupby += ', s.warehouse_id'
|
||||
return super(SaleReport, self)._query(with_clause, fields, groupby, from_clause)
|
||||
return super()._select_additional_fields(fields)
|
||||
|
||||
@@ -361,7 +361,9 @@ class Survey(http.Controller):
|
||||
'page_number': page_ids.index(survey_data['page'].id) + (1 if survey_sudo.progression_mode == 'number' else 0)
|
||||
})
|
||||
elif survey_sudo.questions_layout == 'page_per_question':
|
||||
page_ids = survey_sudo.question_ids.ids
|
||||
page_ids = (answer_sudo.predefined_question_ids.ids
|
||||
if not answer_sudo.is_session_answer
|
||||
else survey_sudo.question_ids.ids)
|
||||
survey_progress = request.env.ref('survey.survey_progression')._render({
|
||||
'survey': survey_sudo,
|
||||
'page_ids': page_ids,
|
||||
|
||||
@@ -30,7 +30,12 @@
|
||||
<t t-set="page_number" t-value="page_ids.index(page.id) + (1 if survey.progression_mode == 'number' else 0)"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<t t-set="page_ids" t-value="survey.question_ids.ids"/>
|
||||
<t t-if="not answer.is_session_answer">
|
||||
<t t-set="page_ids" t-value="answer.predefined_question_ids.ids"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<t t-set="page_ids" t-value="survey.question_ids.ids"/>
|
||||
</t>
|
||||
<t t-set="page_number" t-value="page_ids.index(question.id)"/>
|
||||
</t>
|
||||
</t>
|
||||
@@ -53,7 +58,6 @@
|
||||
<t t-if="answer.test_entry" t-call="survey.survey_button_form_view" />
|
||||
<div class="wrap o_survey_wrap d-flex">
|
||||
<div class="container o_survey_form d-flex flex-column mb-5">
|
||||
|
||||
<t t-call="survey.survey_fill_header" />
|
||||
<t t-call="survey.survey_fill_form" />
|
||||
</div>
|
||||
|
||||
@@ -300,7 +300,7 @@ class Post(models.Model):
|
||||
is_correct = fields.Boolean('Correct', help='Correct answer or answer accepted')
|
||||
parent_id = fields.Many2one('forum.post', string='Question', ondelete='cascade', readonly=True, index=True)
|
||||
self_reply = fields.Boolean('Reply to own question', compute='_is_self_reply', store=True)
|
||||
child_ids = fields.One2many('forum.post', 'parent_id', string='Post Answers', domain=lambda self: [('forum_id', '=', self.forum_id.id)])
|
||||
child_ids = fields.One2many('forum.post', 'parent_id', string='Post Answers', domain=lambda self: [('forum_id', 'in', self.forum_id.ids)])
|
||||
child_count = fields.Integer('Answers', compute='_get_child_count', store=True)
|
||||
uid_has_answered = fields.Boolean('Has Answered', compute='_get_uid_has_answered')
|
||||
has_validated_answer = fields.Boolean('Is answered', compute='_get_has_validated_answer', store=True)
|
||||
|
||||
@@ -8,7 +8,11 @@ class SaleReport(models.Model):
|
||||
|
||||
website_id = fields.Many2one('website', readonly=True)
|
||||
|
||||
def _query(self, with_clause='', fields={}, groupby='', from_clause=''):
|
||||
def _group_by_sale(self, groupby=''):
|
||||
res = super()._group_by_sale(groupby)
|
||||
res += """,s.website_id"""
|
||||
return res
|
||||
|
||||
def _select_additional_fields(self, fields):
|
||||
fields['website_id'] = ", s.website_id as website_id"
|
||||
groupby += ', s.website_id'
|
||||
return super(SaleReport, self)._query(with_clause, fields, groupby, from_clause)
|
||||
return super()._select_additional_fields(fields)
|
||||
|
||||
Reference in New Issue
Block a user