Dear,
There are no more credits on your IAP OCR account.
+ You can charge your IAP OCR account in the settings page.
Best regards,
Exp S.A.
+Dear,
There are no more credits on your IAP OCR account.
\n"
+" You can charge your IAP OCR account in the settings page.
Best regards,
Odoo S.A.
\n" +"عزيزنا،
لم يتبق لديك رصيد في حساب عمليات الشراء داخل التطبيق (IAP) لـ OCR الخاص بحسابك.
\n"
+" حساب عمليات الشراء داخل التطبيق (IAP) لـ OCR الخاص بك في صفحة الإعدادات.
مع أطيب التحيات،
Odoo S.A.
\n" +"+ Use predefined format to import your data faster. +
++ Winbooks is an old school Belgian accounting software acquired by Exact. + Use the + + Account Winbooks Import module + + to import a Winbooks full back-up (Maintenance > Backup) to get the chart of accounts, contacts, taxes, history of journal entries, and documents. + Support versions: Winbooks Desktop 5.50, 6, 7, 8. +
++ Most accounting software in France support exporting FEC file for audit purposes. + Use the + + FEC Import module + + to import the FEC file. We will setup your charts of accounts and the history of journal entries. +
+
+ Most accounting software in Europe support exporting SAF-T file for audit purposes.
+ Use the
+
+ SAF-T Import module
+
+ to import the SAF-T file.
+ We will setup your charts of accounts and the history of journal entries, that will stay in draft.
+
+ The SIE standard file format is very common in Sweden for several purposes such as auditing, importing and exporting data + from and to other accounting applications. Odoo support importing data from both type 4 and 5 of SIE. +
+ Use templates to import CSV or Excel for your accounting setup. +
+Import customers or suppliers (partners) and their contacts using a + + template. + +
+ +Import the Chart of Accounts and initial balances using a + + template. + +
+ + or +Optional, but useful to import open receivables & payables using a + + template. + +
+ +Tip: we recommend importing your initial balances using the Chart of Account import. Only use the Journal Items import for unreconciled entries in your Payable and Receivable Accounts.
+Test
", + model: "discuss.channel", + res_id: channelId, + }); + await start(); + await openDiscuss(); + await contains("button.active", { text: "Inbox" }); + await click("button", { text: "Channel" }); + await click(".o-mail-NotificationItem", { text: "channel" }); + await click(".o-mail-AttachmentImage"); + await contains(".o-FileViewer"); + const backButtonEvent = new Event("backbutton"); + document.dispatchEvent(backButtonEvent); + await contains(".o-FileViewer", { count: 0 }); +}); + +test("[technical] attachment viewer should properly override the back button", async () => { + let overrideBackButton = false; + patchWithCleanup(methods, { + overrideBackButton({ enabled }) { + overrideBackButton = enabled; + }, + }); + + patchUiSize({ size: SIZES.SM }); + const pyEnv = await startServer(); + const partnerId = pyEnv["res.partner"].create({ name: "partner 1" }); + const messageAttachmentId = pyEnv["ir.attachment"].create({ + name: "test.png", + mimetype: "image/png", + }); + pyEnv["mail.message"].create({ + attachment_ids: [messageAttachmentId], + body: "Test
", + model: "res.partner", + res_id: partnerId, + }); + await start(); + await openFormView("res.partner", partnerId); + + await click(".o-mail-AttachmentImage"); + await contains(".o-FileViewer"); + expect(overrideBackButton).toBe(true); + + await click(".o-FileViewer div[aria-label='Close']"); + await contains(".o-FileViewer", { count: 0 }); + expect(overrideBackButton).toBe(false); +}); diff --git a/dev_odex30_accounting/odex30_mail/static/tests/chat_window_patch.test.js b/dev_odex30_accounting/odex30_mail/static/tests/chat_window_patch.test.js new file mode 100644 index 0000000..ce8ba01 --- /dev/null +++ b/dev_odex30_accounting/odex30_mail/static/tests/chat_window_patch.test.js @@ -0,0 +1,64 @@ +import { + click, + contains, + defineMailModels, + patchUiSize, + SIZES, + start, + startServer, +} from "@mail/../tests/mail_test_helpers"; +import { describe, expect, test } from "@odoo/hoot"; +import { Command, patchWithCleanup, serverState } from "@web/../tests/web_test_helpers"; +import { methods } from "@web_mobile/js/services/core"; + +describe.current.tags("desktop"); +defineMailModels(); + +test("'backbutton' event should close chat window", async () => { + patchWithCleanup(methods, { + overrideBackButton({ enabled }) {}, + }); + const pyEnv = await startServer(); + pyEnv["discuss.channel"].create({ + channel_member_ids: [ + Command.create({ + fold_state: "open", + partner_id: serverState.partnerId, + }), + ], + }); + await start(); + + await contains(".o-mail-ChatWindow"); + const backButtonEvent = new Event("backbutton"); + document.dispatchEvent(backButtonEvent); + await contains(".o-mail-ChatWindow", { count: 0 }); +}); + +test("[technical] chat window should properly override the back button", async () => { + let overrideBackButton = false; + patchWithCleanup(methods, { + overrideBackButton({ enabled }) { + overrideBackButton = enabled; + }, + }); + const pyEnv = await startServer(); + pyEnv["discuss.channel"].create({ name: "test" }); + patchUiSize({ size: SIZES.SM }); + await start(); + + await click(".o_menu_systray i[aria-label='Messages']"); + await contains(".o-mail-MessagingMenu"); + await click(".o-mail-NotificationItem", { text: "test" }); + await contains(".o-mail-ChatWindow"); + await contains(".o-mail-MessagingMenu", { count: 0 }); + expect(overrideBackButton).toBe(true); + + await click(".o-mail-ChatWindow [title*='Close']"); + await contains(".o-mail-MessagingMenu"); + + await click(".o_menu_systray i[aria-label='Messages']"); + await contains(".o-mail-ChatWindow", { count: 0 }); + await contains(".o-mail-MessagingMenu", { count: 0 }); + expect(overrideBackButton).toBe(false); +}); diff --git a/dev_odex30_accounting/odex30_mail/static/tests/chatter_patch.test.js b/dev_odex30_accounting/odex30_mail/static/tests/chatter_patch.test.js new file mode 100644 index 0000000..15e3645 --- /dev/null +++ b/dev_odex30_accounting/odex30_mail/static/tests/chatter_patch.test.js @@ -0,0 +1,97 @@ +import { + click, + contains, + defineMailModels, + insertText, + openFormView, + patchUiSize, + registerArchs, + scroll, + SIZES, + start, + startServer, +} from "@mail/../tests/mail_test_helpers"; +import { beforeEach, describe, test } from "@odoo/hoot"; + +describe.current.tags("desktop"); +defineMailModels(); +beforeEach(() => patchUiSize({ size: SIZES.XXL })); + +test("Message list loads new messages on scroll", async () => { + const pyEnv = await startServer(); + const partnerId = pyEnv["res.partner"].create({ + display_name: "Partner 11", + description: [...Array(61).keys()].join("\n"), + }); + for (let i = 0; i < 60; i++) { + pyEnv["mail.message"].create({ + body: "not empty
", + model: "res.partner", + res_id: partnerId, + }); + } + registerArchs({ + "res.partner,false,form": ` + `, + }); + + await start(); + await openFormView("res.partner", partnerId); + await contains(".o-mail-Message", { count: 30 }); + await scroll(".o-mail-Chatter", "bottom"); + await contains(".o-mail-Message", { count: 60 }); +}); + +test("Message list is scrolled to new message after posting a message", async () => { + const pyEnv = await startServer(); + const partnerId = pyEnv["res.partner"].create({ + activity_ids: [], + display_name: "Partner 11
", + description: [...Array(60).keys()].join("\n"), + message_ids: [], + message_follower_ids: [], + }); + for (let i = 0; i < 60; i++) { + pyEnv["mail.message"].create({ + body: "not empty
", + model: "res.partner", + res_id: partnerId, + }); + } + registerArchs({ + "res.partner,false,form": ` + `, + }); + await start(); + await openFormView("res.partner", partnerId); + await contains(".o-mail-Message", { count: 30 }); + await contains(".o-mail-Form-chatter.o-aside"); + await scroll(".o_content", 0); + await scroll(".o-mail-Chatter", 0); + await scroll(".o-mail-Chatter", "bottom"); + await contains(".o-mail-Message", { count: 60 }); + await scroll(".o_content", 0); + await click("button", { text: "Log note" }); + await insertText(".o-mail-Composer-input", "New Message"); + await click(".o-mail-Composer-send:enabled"); + await contains(".o-mail-Composer-input", { count: 0 }); + await contains(".o-mail-Message", { count: 61 }); + await contains(".o-mail-Message-content", { text: "New Message" }); + await scroll(".o_content", 0); + await scroll(".o-mail-Chatter", 0); +}); diff --git a/dev_odex30_accounting/odex30_mail/static/tests/messaging_menu_patch.test.js b/dev_odex30_accounting/odex30_mail/static/tests/messaging_menu_patch.test.js new file mode 100644 index 0000000..3a84af8 --- /dev/null +++ b/dev_odex30_accounting/odex30_mail/static/tests/messaging_menu_patch.test.js @@ -0,0 +1,48 @@ +import { + click, + contains, + defineMailModels, + patchUiSize, + SIZES, + start, +} from "@mail/../tests/mail_test_helpers"; +import { describe, expect, test } from "@odoo/hoot"; +import { patchWithCleanup } from "@web/../tests/web_test_helpers"; +import { methods } from "@web_mobile/js/services/core"; + +describe.current.tags("desktop"); +defineMailModels(); + +test("'backbutton' event should close messaging menu", async () => { + patchWithCleanup(methods, { + overrideBackButton({ enabled }) {}, + }); + await start(); + await click(".o_menu_systray i[aria-label='Messages']"); + + await contains(".o-mail-MessagingMenu"); + // simulate 'backbutton' event triggered by the mobile app + const backButtonEvent = new Event("backbutton"); + document.dispatchEvent(backButtonEvent); + await contains(".o-mail-MessagingMenu", { count: 0 }); +}); + +test("[technical] messaging menu should properly override the back button", async () => { + + let overrideBackButton = false; + patchWithCleanup(methods, { + overrideBackButton({ enabled }) { + overrideBackButton = enabled; + }, + }); + patchUiSize({ size: SIZES.SM }); + await start(); + + await click(".o_menu_systray i[aria-label='Messages']"); + await contains(".o-mail-MessagingMenu"); + expect(overrideBackButton).toBe(true); + + await click(".o_menu_systray i[aria-label='Messages']"); + await contains(".o-mail-MessagingMenu", { count: 0 }); + expect(overrideBackButton).toBe(false); +}); diff --git a/dev_odex30_accounting/odex30_mail/static/tests/thread_patch.test.js b/dev_odex30_accounting/odex30_mail/static/tests/thread_patch.test.js new file mode 100644 index 0000000..ace3740 --- /dev/null +++ b/dev_odex30_accounting/odex30_mail/static/tests/thread_patch.test.js @@ -0,0 +1,43 @@ +import { + contains, + defineMailModels, + openFormView, + patchUiSize, + scroll, + SIZES, + start, + startServer, +} from "@mail/../tests/mail_test_helpers"; +import { describe, expect, test } from "@odoo/hoot"; +import { waitFor } from "@odoo/hoot-dom"; + +describe.current.tags("desktop"); +defineMailModels(); + +test("message list desc order", async () => { + const pyEnv = await startServer(); + const partnerId = pyEnv["res.partner"].create({ name: "partner 1" }); + for (let i = 0; i <= 60; i++) { + pyEnv["mail.message"].create({ + body: "not empty", + model: "res.partner", + res_id: partnerId, + }); + } + patchUiSize({ size: SIZES.XXL }); + await start(); + await openFormView("res.partner", partnerId); + + const messageEl = await waitFor(".o-mail-Message"); + const loadMoreButton = await waitFor("button:contains(Load More)"); + const siblings = [...messageEl.parentElement.children]; + + expect(siblings.indexOf(messageEl)).toBeLessThan(siblings.indexOf(loadMoreButton), { + message: "load more link should be after messages", + }); + await contains(".o-mail-Message", { count: 30 }); + await scroll(".o-mail-Chatter", "bottom"); + await contains(".o-mail-Message", { count: 60 }); + await scroll(".o-mail-Chatter", 0); + await contains(".o-mail-Message", { count: 60 }); +}); diff --git a/dev_odex30_accounting/odex30_mail/static/tests/tours/discuss_channel_expand_test_tour.js b/dev_odex30_accounting/odex30_mail/static/tests/tours/discuss_channel_expand_test_tour.js new file mode 100644 index 0000000..ff4e89d --- /dev/null +++ b/dev_odex30_accounting/odex30_mail/static/tests/tours/discuss_channel_expand_test_tour.js @@ -0,0 +1,27 @@ +import { registry } from "@web/core/registry"; + + +registry + .category("web_tour.tours") + .add("odex30_mail/static/tests/tours/discuss_channel_expand_test_tour.js", { + steps: () => [ + { + content: + "Click on 'Open Actions Menu' in the chat window header to show expand button", + trigger: + '.o-mail-ChatWindow:contains("test-mail-channel-expand-tour") [title="Open Actions Menu"]', + run: "click", + }, + { + content: "Click on expand button to open channel in Discuss", + trigger: '.o-dropdown-item:contains("Open in Discuss")', + run: "click", + }, + { + content: + "Check that first message of #test-mail-channel-expand-tour is shown in Discuss app", + trigger: + '.o-mail-Discuss-content .o-mail-Message-body:contains("test-message-mail-channel-expand-tour")', + }, + ], + }); diff --git a/dev_odex30_accounting/odex30_mail/tests/__init__.py b/dev_odex30_accounting/odex30_mail/tests/__init__.py new file mode 100644 index 0000000..bafe5ea --- /dev/null +++ b/dev_odex30_accounting/odex30_mail/tests/__init__.py @@ -0,0 +1,3 @@ + +from . import odex30_test_discuss_channel_expand +from . import odex30_test_update_notification diff --git a/dev_odex30_accounting/odex30_mail/tests/odex30_test_discuss_channel_expand.py b/dev_odex30_accounting/odex30_mail/tests/odex30_test_discuss_channel_expand.py new file mode 100644 index 0000000..79e5d9d --- /dev/null +++ b/dev_odex30_accounting/odex30_mail/tests/odex30_test_discuss_channel_expand.py @@ -0,0 +1,29 @@ + +from markupsafe import Markup + +from odoo.tests.common import tagged, HttpCase +from odoo.addons.mail.tests.common import MailCommon + + +@tagged('-at_install', 'post_install') +class TestDiscussChannelExpand(HttpCase, MailCommon): + + def test_channel_expand_tour(self): + testuser = self.env['res.users'].create({ + 'email': 'testuser@testuser.com', + 'groups_id': [(6, 0, [self.ref('base.group_user')])], + 'name': 'Test User', + 'login': 'testuser', + 'password': 'testuser', + }) + DiscussChannelAsUser = self.env['discuss.channel'].with_user(testuser) + channel = DiscussChannelAsUser.channel_create(name="test-mail-channel-expand-tour", group_id=self.ref("base.group_user")) + channel.channel_member_ids.filtered(lambda m: m.is_self)._channel_fold(state='open', state_count=0) + channel.message_post( + body=Markup("test-message-mail-channel-expand-tour
"), + message_type='comment', + subtype_xmlid='mail.mt_comment' + ) + + self._reset_bus() + self.start_tour("/odoo", 'odex30_mail/static/tests/tours/discuss_channel_expand_test_tour.js', login='testuser') diff --git a/dev_odex30_accounting/odex30_mail/tests/odex30_test_update_notification.py b/dev_odex30_accounting/odex30_mail/tests/odex30_test_update_notification.py new file mode 100644 index 0000000..81aebc6 --- /dev/null +++ b/dev_odex30_accounting/odex30_mail/tests/odex30_test_update_notification.py @@ -0,0 +1,13 @@ + +from odoo.addons.base.tests.test_cloc import TestClocCustomization +from ast import literal_eval + + +class TestClocICP(TestClocCustomization): + + def test_check_cloc_result_in_icp(self): + self.create_field('x_invoice_count') + message = self.env["publisher_warranty.contract"]._get_message() + self.assertTrue('maintenance' in message) + store_cloc = self.env["ir.config_parameter"].get_param('publisher_warranty.cloc') + self.assertEqual(literal_eval(store_cloc)['modules']['odoo/studio'], 1)