[PATCH] Upstream patch - 07062023

This commit is contained in:
Parthiv Patel committed 2023-06-07 08:34:38 +00:00
1 parent 42b9d4ca08
commit 1da1358d61
10 files changed
+275 -19

No files matched your search

@@ -272,18 +272,23 @@ class account_journal(models.Model):
query = '''
SELECT
(CASE WHEN move_type IN ('out_refund', 'in_refund') THEN -1 ELSE 1 END) * amount_residual AS amount_total,
%(sign)s * amount_residual_signed AS amount_total_company,
currency_id AS currency,
move_type,
invoice_date,
company_id
FROM account_move move
WHERE journal_id = %s
AND invoice_date_due <= %s
WHERE journal_id = %(journal_id)s
AND invoice_date_due <= %(date)s
AND state = 'posted'
AND payment_state in ('not_paid', 'partial')
AND move_type IN ('out_invoice', 'out_refund', 'in_invoice', 'in_refund', 'out_receipt', 'in_receipt');
'''
self.env.cr.execute(query, (self.id, today))
self.env.cr.execute(query, {
'sign': 1 if self.type == 'sale' else -1,
'journal_id': self.id,
'date': today,
})
late_query_results = self.env.cr.dictfetchall()
curr_cache = {}
(number_waiting, sum_waiting) = self._count_results_and_sum_amounts(query_results_to_pay, currency, curr_cache=curr_cache)
@@ -333,6 +338,7 @@ class account_journal(models.Model):
return ('''
SELECT
(CASE WHEN move.move_type IN ('out_refund', 'in_refund') THEN -1 ELSE 1 END) * move.amount_residual AS amount_total,
%(sign)s * amount_residual_signed AS amount_total_company,
move.currency_id AS currency,
move.move_type,
move.invoice_date,
@@ -342,7 +348,10 @@ class account_journal(models.Model):
AND move.state = 'posted'
AND move.payment_state in ('not_paid', 'partial')
AND move.move_type IN ('out_invoice', 'out_refund', 'in_invoice', 'in_refund', 'out_receipt', 'in_receipt');
''', {'journal_id': self.id})
''', {
'sign': 1 if self.type == 'sale' else -1,
'journal_id': self.id,
})
def _get_draft_bills_query(self):
"""
@@ -353,6 +362,7 @@ class account_journal(models.Model):
return ('''
SELECT
(CASE WHEN move.move_type IN ('out_refund', 'in_refund') THEN -1 ELSE 1 END) * move.amount_total AS amount_total,
%(sign)s * amount_residual_signed AS amount_total_company,
move.currency_id AS currency,
move.move_type,
move.invoice_date,
@@ -362,7 +372,10 @@ class account_journal(models.Model):
AND move.state = 'draft'
AND move.payment_state in ('not_paid', 'partial')
AND move.move_type IN ('out_invoice', 'out_refund', 'in_invoice', 'in_refund', 'out_receipt', 'in_receipt');
''', {'journal_id': self.id})
''', {
'sign': 1 if self.type == 'sale' else -1,
'journal_id': self.id,
})
def _count_results_and_sum_amounts(self, results_dict, target_currency, curr_cache=None):
""" Loops on a query result to count the total number of invoices and sum
@@ -381,14 +394,17 @@ class account_journal(models.Model):
rslt_count += 1
date = result.get('invoice_date') or fields.Date.context_today(self)
amount = result.get('amount_total', 0) or 0
if cur != target_currency:
if cur == target_currency:
amount = result.get('amount_total', 0) or 0
elif company.currency_id == target_currency and result.get('amount_total_company'):
amount = result.get('amount_total_company') or 0
else:
key = (cur, target_currency, company, date)
# Using setdefault will call _get_conversion_rate, so we explicitly check the
# existence of the key in the cache instead.
if key not in curr_cache:
curr_cache[key] = self.env['res.currency']._get_conversion_rate(*key)
amount *= curr_cache[key]
amount = curr_cache[key] * result.get('amount_total', 0) or 0
rslt_sum += target_currency.round(amount)
return (rslt_count, rslt_sum)
@@ -3,6 +3,7 @@ from freezegun import freeze_time
from flectra.addons.account.tests.common import AccountTestInvoicingCommon
from flectra.tests import tagged
from flectra.tools.misc import format_amount
@tagged('post_install', '-at_install')
class TestAccountJournalDashboard(AccountTestInvoicingCommon):
@@ -195,3 +196,71 @@ class TestAccountJournalDashboard(AccountTestInvoicingCommon):
dashboard = bank_journal.get_journal_dashboard_datas()
self.assertTrue(dashboard['last_balance'] == dashboard['account_balance'])
def test_sale_purchase_journal_for_multi_currency_purchase(self):
currency = self.currency_data['currency']
company_currency = self.company_data['currency']
invoice = self.env['account.move'].create({
'move_type': 'in_invoice',
'invoice_date': '2017-01-01',
'date': '2017-01-01',
'partner_id': self.partner_a.id,
'currency_id': currency.id,
'invoice_line_ids': [
(0, 0, {'name': 'test', 'price_unit': 200})
],
})
invoice.action_post()
payment = self.env['account.payment'].create({
'amount': 90.0,
'date': '2016-01-01',
'payment_type': 'outbound',
'partner_type': 'supplier',
'partner_id': self.partner_a.id,
'currency_id': currency.id,
})
payment.action_post()
(invoice + payment.move_id).line_ids.filtered_domain([
('account_id', '=', self.company_data['default_account_payable'].id)
]).reconcile()
dashboard_data = self.company_data['default_journal_purchase'].get_journal_dashboard_datas()
self.assertEqual(format_amount(self.env, 70, company_currency), dashboard_data['sum_waiting'])
self.assertEqual(format_amount(self.env, 70, company_currency), dashboard_data['sum_late'])
def test_sale_purchase_journal_for_multi_currency_sale(self):
currency = self.currency_data['currency']
company_currency = self.company_data['currency']
invoice = self.env['account.move'].create({
'move_type': 'out_invoice',
'invoice_date': '2017-01-01',
'date': '2017-01-01',
'partner_id': self.partner_a.id,
'currency_id': currency.id,
'invoice_line_ids': [
(0, 0, {'name': 'test', 'price_unit': 200})
],
})
invoice.action_post()
payment = self.env['account.payment'].create({
'amount': 90.0,
'date': '2016-01-01',
'payment_type': 'inbound',
'partner_type': 'customer',
'partner_id': self.partner_a.id,
'currency_id': currency.id,
})
payment.action_post()
(invoice + payment.move_id).line_ids.filtered_domain([
('account_id', '=', self.company_data['default_account_receivable'].id)
]).reconcile()
dashboard_data = self.company_data['default_journal_sale'].get_journal_dashboard_datas()
self.assertEqual(format_amount(self.env, 70, company_currency), dashboard_data['sum_waiting'])
self.assertEqual(format_amount(self.env, 70, company_currency), dashboard_data['sum_late'])
+16 -2
View File
@@ -130,6 +130,16 @@ var BoardRenderer = FormRenderer.extend({
this._boardSubcontrollers = []; // for board: controllers of subviews
this._boardFormViewIDs = {}; // for board: mapping subview controller to form view id
},
/**
* @override
* @return {Promise<void>}
*/
async start() {
await this._super.apply(this, arguments);
if (config.device.isMobile) {
this.changeLayout("1");
}
},
/**
* Call `on_attach_callback` for each subview
*
@@ -386,7 +396,9 @@ var BoardRenderer = FormRenderer.extend({
Dialog.confirm(this, (_t("Are you sure you want to remove this item?")), {
confirm_callback: function () {
$container.remove();
self.trigger_up('save_dashboard');
if (!config.device.isMobile) {
self.trigger_up('save_dashboard');
}
},
});
},
@@ -407,7 +419,9 @@ var BoardRenderer = FormRenderer.extend({
}
$e.toggleClass('oe_minimize oe_maximize');
$action.find('.oe_content').toggle();
this.trigger_up('save_dashboard');
if (!config.device.isMobile) {
this.trigger_up('save_dashboard');
}
},
/**
* Let FormController know which form view it should display based on the
-3
View File
@@ -1,9 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<template>
<t t-name="DashBoard">
<t t-if="isMobile">
<t t-set="node.attrs.layout" t-value="1"/>
</t>
<t t-if="!isMobile">
<div class="oe_dashboard_links">
<button type="button" class="button oe_dashboard_link_change_layout btn btn-secondary"
@@ -0,0 +1,116 @@
flectra.define("board.dashboard_tests", function (require) {
"use strict";
var BoardView = require("board.BoardView");
var testUtils = require("web.test_utils");
var createView = testUtils.createView;
QUnit.module("Board view", {
beforeEach: function () {
this.data = {
board: {
fields: {},
records: [],
},
partner: {
fields: {
foo: {
string: "Foo",
type: "char",
default: "My little Foo Value",
searchable: true,
},
},
records: [
{
id: 1,
foo: "yop",
},
],
},
};
},
});
QUnit.test("can't switch views in the dashboard", async function (assert) {
assert.expect(3);
var target = await createView({
View: BoardView,
model: "board",
data: this.data,
arch: `<form string="My Dashboard">
<board style="2-1">
<column>
<action context="{}" domain="[]" view_mode="list" string="ABC" name="51"/>
</column>
</board>
</form>`,
mockRPC: function (route) {
if (route === "/web/action/load") {
return Promise.resolve({
res_model: "partner",
views: [
[4, "list"],
[5, "form"],
],
});
}
return this._super.apply(this, arguments);
},
archs: {
"partner,4,list": `<tree string="Partner"><field name="foo"/></tree>`,
},
});
assert.containsNone(target, ".oe_dashboard_links", "Couldn't allow user to Change layout");
assert.containsOnce(target, ".oe_dashboard_layout_1", "The display layout is force to 1");
assert.containsNone(
target,
".o_action .o_control_panel",
"views in the dashboard do not have a control panel"
);
target.destroy();
});
QUnit.test("Correctly soft switch to '1' layout on small screen", async function (assert) {
assert.expect(2);
var target = await createView({
View: BoardView,
model: "board",
data: this.data,
arch: `<form>
<board style="2-1">
<column>
<action context="{}" domain="[]" view_mode="list" string="ABC" name="51"/>
</column>
<column>
<action context="{}" domain="[]" view_mode="list" string="ABC" name="51"/>
</column>
</board>
</form>`,
mockRPC: function (route) {
if (route === "/web/action/load") {
return Promise.resolve({
res_model: "partner",
views: [
[4, "list"],
[5, "form"],
],
});
}
return this._super.apply(this, arguments);
},
archs: {
"partner,4,list": '<tree string="Partner"><field name="foo"/></tree>',
},
});
assert.containsOnce(target, ".oe_dashboard_layout_1", "The display layout is force to 1");
assert.containsN(target, ".oe_action", 2, "The display should contains the 2 actions");
target.destroy();
});
});
+6
View File
@@ -14,4 +14,10 @@
<script type="text/javascript" src="/board/static/tests/dashboard_tests.js"></script>
</xpath>
</template>
<template id="qunit_mobile_suite" name="dashboard_mobile_tests" inherit_id="web.qunit_mobile_suite_tests">
<xpath expr="." position="inside">
<script type="text/javascript" src="/board/static/tests/mobile/board_tests.js"></script>
</xpath>
</template>
</flectra>
@@ -5,7 +5,7 @@
<t t-if="ddt_dict and not record.l10n_it_ddt_id">
<t t-foreach="ddt_dict" t-as="picking">
<DatiDDT>
<NumeroDDT t-esc="picking.l10n_it_ddt_number"/>
<NumeroDDT t-esc="format_alphanumeric(picking.l10n_it_ddt_number[-20:])"/>
<DataDDT t-esc="format_date(picking.date)"/>
<t t-if="len(ddt_dict) > 1">
<t t-foreach="ddt_dict[picking]" t-as="line_ref">
@@ -1127,6 +1127,42 @@ registry.FooterSlideout = publicWidget.Widget.extend({
},
});
registry.TopMenuCollapse = publicWidget.Widget.extend({
selector: "header #top_menu_collapse",
/**
* @override
*/
async start() {
this.throttledResize = _.throttle(() => this._onResize(), 25);
window.addEventListener("resize", this.throttledResize);
return this._super(...arguments);
},
/**
* @override
*/
destroy() {
this._super(...arguments);
window.removeEventListener("resize", this.throttledResize);
},
//--------------------------------------------------------------------------
// Handlers
//--------------------------------------------------------------------------
/**
* @private
*/
_onResize() {
if (this.el.classList.contains("show")) {
const togglerEl = this.el.closest("nav").querySelector(".navbar-toggler");
if (getComputedStyle(togglerEl).display === "none") {
this.$el.collapse("hide");
}
}
},
});
registry.HeaderHamburgerFull = publicWidget.Widget.extend({
selector: 'header:has(.o_header_hamburger_full_toggler):not(:has(.o_offcanvas_menu_toggler))',
events: {
@@ -2010,10 +2010,11 @@ options.registry.HeaderNavbar = options.Class.extend({
*/
async updateUI() {
await this._super(...arguments);
// For all header templates except those of the following selector,
// change the label of the option to "Mobile Alignment" (instead of
// For all header templates except those in the following array, change
// the label of the option to "Mobile Alignment" (instead of
// "Alignment") because it only impacts the mobile view.
if (!this.$target[0].querySelector('#oe_structure_header_default_1, #oe_structure_header_hamburger_1, #oe_structure_header_sidebar_1')) {
if (!["'default'", "'hamburger'", "'sidebar'", "'magazine'", "'hamburger-full'"]
.includes(weUtils.getCSSVariableValue("header-template"))) {
const alignmentOptionTitleEl = this.el.querySelector('[data-name="header_alignment_opt"] we-title');
alignmentOptionTitleEl.textContent = _t("Mobile Alignment");
}
@@ -299,15 +299,16 @@ options.registry.WebsiteSaleGridLayout = options.Class.extend({
* @see this.selectClass for params
*/
setPpg: function (previewMode, widgetValue, params) {
const PPG_LIMIT = 10000;
const ppg = parseInt(widgetValue);
if (!ppg || ppg < 1) {
return false;
}
this.ppg = ppg;
this.ppg = Math.min(ppg, PPG_LIMIT);
return this._rpc({
route: '/shop/change_ppg',
params: {
'ppg': ppg,
'ppg': this.ppg,
},
}).then(() => reload());
},