mirror of
https://github.com/bringout/oca-ocb-mail.git
synced 2026-04-21 05:42:09 +02:00
19.0 vanilla
This commit is contained in:
parent
5df8c07b59
commit
daa394e8b0
2114 changed files with 564841 additions and 299642 deletions
|
|
@ -1,6 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import controllers
|
||||
from . import models
|
||||
from . import tools
|
||||
from . import wizard
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
{
|
||||
'name': 'SMS gateway',
|
||||
'version': '2.4',
|
||||
'category': 'Hidden/Tools',
|
||||
'version': '3.0',
|
||||
'category': 'Sales/Sales',
|
||||
'summary': 'SMS Text Messaging',
|
||||
'description': """
|
||||
This module gives a framework for SMS text messaging
|
||||
|
|
@ -19,15 +19,19 @@ The service is provided by the In App Purchase Odoo platform.
|
|||
'phone_validation'
|
||||
],
|
||||
'data': [
|
||||
'data/iap_service_data.xml',
|
||||
'data/ir_cron_data.xml',
|
||||
'wizard/sms_account_code_views.xml',
|
||||
'wizard/sms_account_phone_views.xml',
|
||||
'wizard/sms_account_sender_views.xml',
|
||||
'wizard/sms_composer_views.xml',
|
||||
'wizard/sms_template_preview_views.xml',
|
||||
'wizard/sms_resend_views.xml',
|
||||
'wizard/sms_template_reset_views.xml',
|
||||
'views/ir_actions_server_views.xml',
|
||||
'views/mail_notification_views.xml',
|
||||
'views/res_config_settings_views.xml',
|
||||
'views/res_partner_views.xml',
|
||||
'views/iap_account_views.xml',
|
||||
'views/sms_sms_views.xml',
|
||||
'views/sms_template_views.xml',
|
||||
'security/ir.model.access.csv',
|
||||
|
|
@ -40,20 +44,13 @@ The service is provided by the In App Purchase Odoo platform.
|
|||
'installable': True,
|
||||
'auto_install': True,
|
||||
'assets': {
|
||||
'mail.assets_messaging': [
|
||||
'sms/static/src/models/*.js',
|
||||
],
|
||||
'mail.assets_discuss_public': [
|
||||
'sms/static/src/components/sms_button/*',
|
||||
],
|
||||
'web.assets_backend': [
|
||||
'sms/static/src/js/fields_phone_widget.js',
|
||||
'sms/static/src/components/*/*',
|
||||
'sms/static/src/**/*',
|
||||
],
|
||||
'web.qunit_suite_tests': [
|
||||
'sms/static/tests/sms_widget_test.js',
|
||||
'sms/static/tests/qunit_suite_tests/**/*.js',
|
||||
'web.assets_unit_tests': [
|
||||
'sms/static/tests/**/*',
|
||||
],
|
||||
},
|
||||
'author': 'Odoo S.A.',
|
||||
'license': 'LGPL-3',
|
||||
}
|
||||
|
|
|
|||
3
odoo-bringout-oca-ocb-sms/sms/controllers/__init__.py
Normal file
3
odoo-bringout-oca-ocb-sms/sms/controllers/__init__.py
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import main
|
||||
49
odoo-bringout-oca-ocb-sms/sms/controllers/main.py
Normal file
49
odoo-bringout-oca-ocb-sms/sms/controllers/main.py
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import logging
|
||||
import re
|
||||
|
||||
from odoo import _
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.http import Controller, request, route
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SmsController(Controller):
|
||||
|
||||
@route('/sms/status', type='jsonrpc', auth='public')
|
||||
def update_sms_status(self, message_statuses):
|
||||
"""Receive a batch of delivery reports from IAP
|
||||
|
||||
:param message_statuses:
|
||||
[
|
||||
{
|
||||
'sms_status': status0,
|
||||
'uuids': [uuid00, uuid01, ...],
|
||||
}, {
|
||||
'sms_status': status1,
|
||||
'uuids': [uuid10, uuid11, ...],
|
||||
},
|
||||
...
|
||||
]
|
||||
"""
|
||||
all_uuids = []
|
||||
for uuids, iap_status in ((status['uuids'], status['sms_status']) for status in message_statuses):
|
||||
self._check_status_values(uuids, iap_status, message_statuses)
|
||||
if sms_trackers_sudo := request.env['sms.tracker'].sudo().search([('sms_uuid', 'in', uuids)]):
|
||||
if state := request.env['sms.sms'].IAP_TO_SMS_STATE_SUCCESS.get(iap_status):
|
||||
sms_trackers_sudo._action_update_from_sms_state(state)
|
||||
else:
|
||||
sms_trackers_sudo._action_update_from_provider_error(iap_status)
|
||||
all_uuids += uuids
|
||||
request.env['sms.sms'].sudo().search([('uuid', 'in', all_uuids), ('to_delete', '=', False)]).to_delete = True
|
||||
return 'OK'
|
||||
|
||||
@staticmethod
|
||||
def _check_status_values(uuids, iap_status, message_statuses):
|
||||
"""Basic checks to avoid unnecessary queries and allow debugging."""
|
||||
if (not uuids or not iap_status or not re.match(r'^\w+$', iap_status)
|
||||
or any(not re.match(r'^[0-9a-f]{32}$', uuid) for uuid in uuids)):
|
||||
_logger.warning('Received ill-formatted SMS delivery report event: \n%s', message_statuses)
|
||||
raise UserError(_("Bad parameters"), status=400)
|
||||
12
odoo-bringout-oca-ocb-sms/sms/data/iap_service_data.xml
Normal file
12
odoo-bringout-oca-ocb-sms/sms/data/iap_service_data.xml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="iap_service_sms" model="iap.service">
|
||||
<field name="name">SMS</field>
|
||||
<field name="technical_name">sms</field>
|
||||
<field name="description">Send SMS to your contacts directly from your database.</field>
|
||||
<field name="unit_name">Credits</field>
|
||||
<field name="integer_balance">False</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -6,9 +6,7 @@
|
|||
<field name="state">code</field>
|
||||
<field name="code">model._process_queue()</field>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="interval_number">1</field>
|
||||
<field name="interval_number">24</field>
|
||||
<field name="interval_type">hours</field>
|
||||
<field name="numbercall">-1</field>
|
||||
<field eval="False" name="doall"/>
|
||||
</record>
|
||||
</data></odoo>
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
1934
odoo-bringout-oca-ocb-sms/sms/i18n/es_419.po
Normal file
1934
odoo-bringout-oca-ocb-sms/sms/i18n/es_419.po
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,22 +1,22 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * sms
|
||||
#
|
||||
#
|
||||
# Translators:
|
||||
# Qaidjohar Barbhaya, 2025
|
||||
#
|
||||
# Qaidjohar Barbhaya, 2023
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 16.0\n"
|
||||
"Project-Id-Version: Odoo Server 16.0beta\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-05-06 20:36+0000\n"
|
||||
"POT-Creation-Date: 2023-05-16 13:49+0000\n"
|
||||
"PO-Revision-Date: 2022-09-22 05:55+0000\n"
|
||||
"Last-Translator: Qaidjohar Barbhaya, 2025\n"
|
||||
"Last-Translator: Qaidjohar Barbhaya, 2023\n"
|
||||
"Language-Team: Gujarati (https://app.transifex.com/odoo/teams/41243/gu/)\n"
|
||||
"Language: gu\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Language: gu\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -32,30 +32,19 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_template.py:0
|
||||
#, python-format
|
||||
msgid "%s (copy)"
|
||||
msgstr "%s (copy)"
|
||||
|
||||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/wizard/sms_composer.py:0
|
||||
#, python-format
|
||||
msgid "%s invalid recipients"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_sms.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%s out of the %s selected SMS Text Messages have successfully been resent."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/sms_widget/fields_sms_widget.xml:0
|
||||
#, python-format
|
||||
msgid ", fits in"
|
||||
msgid "%s out of the %s selected SMS Text Messages have successfully been resent."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -65,6 +54,11 @@ msgid ""
|
|||
" <span class=\"o_stat_text\">Context Action</span>"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_view_form
|
||||
msgid "<span class=\"o_stat_text\">Preview</span>"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_view_form
|
||||
msgid ""
|
||||
|
|
@ -74,9 +68,7 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_preview_form
|
||||
msgid ""
|
||||
"<span class=\"text-warning\" attrs=\"{'invisible': [('no_record', '=', "
|
||||
"False)]}\">No records</span>"
|
||||
msgid "<span class=\"text-warning\" attrs=\"{'invisible': [('no_record', '=', False)]}\">No records</span>"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -105,16 +97,13 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_view_form
|
||||
msgid ""
|
||||
"Add a contextual action on the related model to open a sms composer with "
|
||||
"this template"
|
||||
msgid "Add a contextual action on the related model to open a sms composer with this template"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/notification_group/notification_group.xml:0
|
||||
#, python-format
|
||||
msgid "An error occurred when sending an SMS."
|
||||
#: code:addons/sms/static/src/core/notification_group_model_patch.js:0
|
||||
msgid "An error occurred when sending an SMS"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -125,9 +114,7 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_reset_view_form
|
||||
msgid ""
|
||||
"Are you sure you want to reset these sms templates to their original "
|
||||
"configuration? Changes and translations will be lost."
|
||||
msgid "Are you sure you want to reset these sms templates to their original configuration? Changes and translations will be lost."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -135,11 +122,6 @@ msgstr ""
|
|||
msgid "Attachment Count"
|
||||
msgstr "Attachment Count"
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model,name:sms.model_base
|
||||
msgid "Base"
|
||||
msgstr "Base"
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields.selection,name:sms.selection__sms_sms__failure_type__sms_blacklist
|
||||
msgid "Blacklisted"
|
||||
|
|
@ -170,7 +152,6 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_api.py:0
|
||||
#, python-format
|
||||
msgid "Buy credits."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -332,6 +313,12 @@ msgstr ""
|
|||
msgid "Email Thread"
|
||||
msgstr "Email Thread"
|
||||
|
||||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/phone_field/phone_field.js:0
|
||||
msgid "Enable SMS"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields.selection,name:sms.selection__sms_sms__state__error
|
||||
msgid "Error"
|
||||
|
|
@ -354,15 +341,12 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__phone_sanitized
|
||||
msgid ""
|
||||
"Field used to store sanitized phone number. Helps speeding up searches and "
|
||||
"comparisons."
|
||||
msgid "Field used to store sanitized phone number. Helps speeding up searches and comparisons."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_sms_template__template_fs
|
||||
msgid ""
|
||||
"File from where the template originates. Used to reset broken template."
|
||||
msgid "File from where the template originates. Used to reset broken template."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -378,7 +362,6 @@ msgstr "Followers (Partners)"
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/wizard/sms_composer.py:0
|
||||
#, python-format
|
||||
msgid "Following numbers are not correctly encoded: %s"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -424,6 +407,7 @@ msgstr "If checked, new messages require your attention."
|
|||
#: model:ir.model.fields,help:sms.field_calendar_event__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_crm_team__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_crm_team_member__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_discuss_channel__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_fleet_vehicle__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_fleet_vehicle_log_contract__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_fleet_vehicle_log_services__message_has_sms_error
|
||||
|
|
@ -435,13 +419,14 @@ msgstr "If checked, new messages require your attention."
|
|||
#: model:ir.model.fields,help:sms.field_hr_job__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_hr_leave__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_hr_leave_allocation__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_hr_plan_employee_activity__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_loyalty_card__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_lunch_supplier__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_mail_blacklist__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_mail_channel__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_mail_thread__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_mail_thread_blacklist__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_mail_thread_cc__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_mail_thread_main_attachment__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_mail_thread_phone__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_maintenance_equipment__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_maintenance_equipment_category__message_has_sms_error
|
||||
|
|
@ -450,6 +435,7 @@ msgstr "If checked, new messages require your attention."
|
|||
#: model:ir.model.fields,help:sms.field_phone_blacklist__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_product_product__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_product_template__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_rating_mixin__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__message_has_error
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_res_users__message_has_sms_error
|
||||
|
|
@ -458,9 +444,7 @@ msgstr "If checked, some messages have a delivery error."
|
|||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__phone_sanitized_blacklisted
|
||||
msgid ""
|
||||
"If the sanitized phone number is on the blacklist, the contact won't receive"
|
||||
" mass mailing sms anymore, from any list"
|
||||
msgid "If the sanitized phone number is on the blacklist, the contact won't receive mass mailing sms anymore, from any list"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -475,18 +459,12 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__mobile_blacklisted
|
||||
msgid ""
|
||||
"Indicates if a blacklisted sanitized phone number is a mobile number. Helps "
|
||||
"distinguish which number is blacklisted when there is both a "
|
||||
"mobile and phone field in a model."
|
||||
msgid "Indicates if a blacklisted sanitized phone number is a mobile number. Helps distinguish which number is blacklisted when there is both a mobile and phone field in a model."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__phone_blacklisted
|
||||
msgid ""
|
||||
"Indicates if a blacklisted sanitized phone number is a phone number. Helps "
|
||||
"distinguish which number is blacklisted when there is both a "
|
||||
"mobile and phone field in a model."
|
||||
msgid "Indicates if a blacklisted sanitized phone number is a phone number. Helps distinguish which number is blacklisted when there is both a mobile and phone field in a model."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -503,7 +481,6 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/wizard/sms_composer.py:0
|
||||
#, python-format
|
||||
msgid "Invalid recipient number. Please update it."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -527,17 +504,6 @@ msgstr ""
|
|||
msgid "Language"
|
||||
msgstr "Language"
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_composer____last_update
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_resend____last_update
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_resend_recipient____last_update
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_sms____last_update
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_template____last_update
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_template_preview____last_update
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_template_reset____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr "Last Modified on"
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_composer__write_uid
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_resend__write_uid
|
||||
|
|
@ -570,18 +536,13 @@ msgstr ""
|
|||
msgid "Mail Thread SMS"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_main_attachment_id
|
||||
msgid "Main Attachment"
|
||||
msgstr "Main Attachment"
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model,name:sms.model_mail_message
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_composer__body
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_resend__mail_message_id
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_tsms_view_form
|
||||
msgid "Message"
|
||||
msgstr ""
|
||||
msgstr "સંદેશ"
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_has_error
|
||||
|
|
@ -596,12 +557,8 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_mail_mail__message_type
|
||||
#: model:ir.model.fields,help:sms.field_mail_message__message_type
|
||||
msgid ""
|
||||
"Message type: email for email message, notification for system message, "
|
||||
"comment for other messages such as user replies"
|
||||
msgstr ""
|
||||
"Message type: email for email message, notification for system message, "
|
||||
"comment for other messages such as user replies"
|
||||
msgid "Message type: email for email message, notification for system message, comment for other messages such as user replies"
|
||||
msgstr "Message type: email for email message, notification for system message, comment for other messages such as user replies"
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_ids
|
||||
|
|
@ -661,8 +618,8 @@ msgstr "Number of errors"
|
|||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__message_needaction_counter
|
||||
msgid "Number of messages requiring action"
|
||||
msgstr ""
|
||||
msgid "Number of messages which requires an action"
|
||||
msgstr "Number of messages which requires an action"
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__message_has_error_counter
|
||||
|
|
@ -671,9 +628,7 @@ msgstr "Number of messages with delivery error"
|
|||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_sms_composer__res_ids_count
|
||||
msgid ""
|
||||
"Number of recipients that will receive the SMS if sent in mass mode, without"
|
||||
" applying the Active Domain value"
|
||||
msgid "Number of recipients that will receive the SMS if sent in mass mode, without applying the Active Domain value"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -683,16 +638,8 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_sms_template__lang
|
||||
msgid ""
|
||||
"Optional translation language (ISO code) to select when sending out an "
|
||||
"email. If not set, the english version will be used. This should usually be "
|
||||
"a placeholder expression that provides the appropriate language, e.g. {{ "
|
||||
"object.partner_id.lang }}."
|
||||
msgstr ""
|
||||
"Optional translation language (ISO code) to select when sending out an "
|
||||
"email. If not set, the english version will be used. This should usually be "
|
||||
"a placeholder expression that provides the appropriate language, e.g. {{ "
|
||||
"object.partner_id.lang }}."
|
||||
msgid "Optional translation language (ISO code) to select when sending out an email. If not set, the english version will be used. This should usually be a placeholder expression that provides the appropriate language, e.g. {{ object.partner_id.lang }}."
|
||||
msgstr "Optional translation language (ISO code) to select when sending out an email. If not set, the english version will be used. This should usually be a placeholder expression that provides the appropriate language, e.g. {{ object.partner_id.lang }}."
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model,name:sms.model_sms_sms
|
||||
|
|
@ -721,9 +668,7 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_sms_composer__recipient_single_number_itf
|
||||
msgid ""
|
||||
"Phone number of the recipient. If changed, it will be recorded on "
|
||||
"recipient's profile."
|
||||
msgid "Phone number of the recipient. If changed, it will be recorded on recipient's profile."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -746,11 +691,6 @@ msgstr ""
|
|||
msgid "Post on a document"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_view_form
|
||||
msgid "Preview"
|
||||
msgstr "Preview"
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_preview_form
|
||||
msgid "Preview of"
|
||||
|
|
@ -766,6 +706,11 @@ msgstr ""
|
|||
msgid "Put in queue"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__rating_ids
|
||||
msgid "Ratings"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.mail_resend_message_view_form
|
||||
msgid "Reason"
|
||||
|
|
@ -851,8 +796,7 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/sms_button/sms_button.xml:0
|
||||
#: code:addons/sms/static/src/models/message_view.js:0
|
||||
#: code:addons/sms/static/src/models/message_view.js:0
|
||||
#: code:addons/sms/static/src/core/notification_model_patch.js:0
|
||||
#: model:ir.actions.act_window,name:sms.sms_sms_action
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_notification__sms_id
|
||||
#: model:ir.model.fields.selection,name:sms.selection__ir_actions_server__sms_method__sms
|
||||
|
|
@ -860,14 +804,12 @@ msgstr ""
|
|||
#: model:ir.model.fields.selection,name:sms.selection__mail_notification__notification_type__sms
|
||||
#: model:ir.ui.menu,name:sms.sms_sms_menu
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_tsms_view_form
|
||||
#, python-format
|
||||
msgid "SMS"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/sms_widget/fields_sms_widget.xml:0
|
||||
#, python-format
|
||||
msgid "SMS ("
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -881,6 +823,7 @@ msgstr ""
|
|||
#: model:ir.model.fields,field_description:sms.field_calendar_event__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_crm_team__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_crm_team_member__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_discuss_channel__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_fleet_vehicle__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_fleet_vehicle_log_contract__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_fleet_vehicle_log_services__message_has_sms_error
|
||||
|
|
@ -892,13 +835,14 @@ msgstr ""
|
|||
#: model:ir.model.fields,field_description:sms.field_hr_job__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_hr_leave__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_hr_leave_allocation__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_hr_plan_employee_activity__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_loyalty_card__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_lunch_supplier__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_blacklist__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_channel__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_thread__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_thread_blacklist__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_thread_cc__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_thread_main_attachment__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_thread_phone__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_maintenance_equipment__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_maintenance_equipment_category__message_has_sms_error
|
||||
|
|
@ -907,6 +851,7 @@ msgstr ""
|
|||
#: model:ir.model.fields,field_description:sms.field_phone_blacklist__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_product_product__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_product_template__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_rating_mixin__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_res_users__message_has_sms_error
|
||||
msgid "SMS Delivery error"
|
||||
|
|
@ -914,8 +859,7 @@ msgstr "SMS Delivery error"
|
|||
|
||||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/models/notification_group.js:0
|
||||
#, python-format
|
||||
#: code:addons/sms/static/src/messaging_menu/messaging_menu_patch.js:0
|
||||
msgid "SMS Failures"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -932,8 +876,6 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/sms_widget/fields_sms_widget.xml:0
|
||||
#: code:addons/sms/static/src/components/sms_widget/fields_sms_widget.xml:0
|
||||
#, python-format
|
||||
msgid "SMS Pricing"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -977,7 +919,6 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/wizard/sms_template_reset.py:0
|
||||
#, python-format
|
||||
msgid "SMS Templates have been reset"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -988,7 +929,6 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#: model:ir.actions.server,name:sms.ir_cron_sms_scheduler_action_ir_actions_server
|
||||
#: model:ir.cron,cron_name:sms.ir_cron_sms_scheduler_action
|
||||
msgid "SMS: SMS Queue Manager"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -1024,20 +964,16 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_template.py:0
|
||||
#, python-format
|
||||
msgid "Send SMS (%s)"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/sms_button/sms_button.js:0
|
||||
#: code:addons/sms/static/src/js/fields_phone_widget.js:0
|
||||
#: code:addons/sms/static/src/js/fields_phone_widget.js:0
|
||||
#: model:ir.actions.act_window,name:sms.res_partner_act_window_sms_composer_multi
|
||||
#: model:ir.actions.act_window,name:sms.res_partner_act_window_sms_composer_single
|
||||
#: model:ir.actions.act_window,name:sms.sms_composer_action_form
|
||||
#: model:ir.model.fields.selection,name:sms.selection__ir_actions_server__state__sms
|
||||
#, python-format
|
||||
msgid "Send SMS Text Message"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -1086,8 +1022,7 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/ir_actions_server.py:0
|
||||
#, python-format
|
||||
msgid "Sending SMS can only be done on a not transient mail.thread model"
|
||||
msgid "Sending SMS can only be done on a mail.thread or a transient model"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -1118,9 +1053,7 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_sms_template__sidebar_action_id
|
||||
msgid ""
|
||||
"Sidebar action to make this template available on records of the related "
|
||||
"document model"
|
||||
msgid "Sidebar action to make this template available on records of the related document model"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -1146,7 +1079,6 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_sms.py:0
|
||||
#, python-format
|
||||
msgid "Success"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -1178,14 +1110,12 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_sms.py:0
|
||||
#, python-format
|
||||
msgid "The SMS Text Messages could not be resent."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_api.py:0
|
||||
#, python-format
|
||||
msgid "The number you're trying to reach is not correctly formatted."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -1198,14 +1128,12 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_sms.py:0
|
||||
#, python-format
|
||||
msgid "There are no SMS Text Messages to resend."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.res_partner_view_form
|
||||
msgid ""
|
||||
"This phone number is blacklisted for SMS Marketing. Click to unblacklist."
|
||||
msgid "This phone number is blacklisted for SMS Marketing. Click to unblacklist."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -1259,7 +1187,6 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_sms.py:0
|
||||
#, python-format
|
||||
msgid "Warning"
|
||||
msgstr "Warning"
|
||||
|
||||
|
|
@ -1287,37 +1214,31 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/wizard/sms_resend.py:0
|
||||
#, python-format
|
||||
msgid "You do not have access to the message and/or related document."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_api.py:0
|
||||
#, python-format
|
||||
msgid "You don't have an eligible IAP account."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_api.py:0
|
||||
#, python-format
|
||||
msgid "You don't have enough credits on your IAP account."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/sms_widget/fields_sms_widget.js:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Your SMS Text Message must include at least one non-whitespace character"
|
||||
msgid "Your SMS Text Message must include at least one non-whitespace character"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/sms_widget/fields_sms_widget.xml:0
|
||||
#, python-format
|
||||
msgid "characters"
|
||||
msgid "characters, fits in"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -1347,9 +1268,7 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_composer_view_form
|
||||
msgid ""
|
||||
"recipients have an invalid phone number and will not receive this text "
|
||||
"message."
|
||||
msgid "recipients have an invalid phone number and will not receive this text message."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,23 +1,18 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * sms
|
||||
#
|
||||
# Translators:
|
||||
# Kristófer Arnþórsson, 2024
|
||||
# jonasyngvi, 2025
|
||||
#
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 16.0\n"
|
||||
"Project-Id-Version: Odoo Server 16.0beta\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-05-06 20:36+0000\n"
|
||||
"POT-Creation-Date: 2023-05-16 13:49+0000\n"
|
||||
"PO-Revision-Date: 2022-09-22 05:55+0000\n"
|
||||
"Last-Translator: jonasyngvi, 2025\n"
|
||||
"Language-Team: Icelandic (https://app.transifex.com/odoo/teams/41243/is/)\n"
|
||||
"Language-Team: Icelandic (https://www.transifex.com/odoo/teams/41243/is/)\n"
|
||||
"Language: is\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Language: is\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);\n"
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -33,32 +28,19 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_template.py:0
|
||||
#, python-format
|
||||
msgid "%s (copy)"
|
||||
msgstr ""
|
||||
"%s (afrit)\n"
|
||||
" "
|
||||
|
||||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/wizard/sms_composer.py:0
|
||||
#, python-format
|
||||
msgid "%s invalid recipients"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_sms.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%s out of the %s selected SMS Text Messages have successfully been resent."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/sms_widget/fields_sms_widget.xml:0
|
||||
#, python-format
|
||||
msgid ", fits in"
|
||||
msgid "%s out of the %s selected SMS Text Messages have successfully been resent."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -68,6 +50,11 @@ msgid ""
|
|||
" <span class=\"o_stat_text\">Context Action</span>"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_view_form
|
||||
msgid "<span class=\"o_stat_text\">Preview</span>"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_view_form
|
||||
msgid ""
|
||||
|
|
@ -77,9 +64,7 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_preview_form
|
||||
msgid ""
|
||||
"<span class=\"text-warning\" attrs=\"{'invisible': [('no_record', '=', "
|
||||
"False)]}\">No records</span>"
|
||||
msgid "<span class=\"text-warning\" attrs=\"{'invisible': [('no_record', '=', False)]}\">No records</span>"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -97,7 +82,7 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_needaction
|
||||
msgid "Action Needed"
|
||||
msgstr "Aðgerða þörf"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_base_automation__state
|
||||
|
|
@ -108,16 +93,13 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_view_form
|
||||
msgid ""
|
||||
"Add a contextual action on the related model to open a sms composer with "
|
||||
"this template"
|
||||
msgid "Add a contextual action on the related model to open a sms composer with this template"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/notification_group/notification_group.xml:0
|
||||
#, python-format
|
||||
msgid "An error occurred when sending an SMS."
|
||||
#: code:addons/sms/static/src/core/notification_group_model_patch.js:0
|
||||
msgid "An error occurred when sending an SMS"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -128,20 +110,13 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_reset_view_form
|
||||
msgid ""
|
||||
"Are you sure you want to reset these sms templates to their original "
|
||||
"configuration? Changes and translations will be lost."
|
||||
msgid "Are you sure you want to reset these sms templates to their original configuration? Changes and translations will be lost."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_attachment_count
|
||||
msgid "Attachment Count"
|
||||
msgstr "Fjöldi viðhengja"
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model,name:sms.model_base
|
||||
msgid "Base"
|
||||
msgstr "Grunnur"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields.selection,name:sms.selection__sms_sms__failure_type__sms_blacklist
|
||||
|
|
@ -173,7 +148,6 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_api.py:0
|
||||
#, python-format
|
||||
msgid "Buy credits."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -192,12 +166,12 @@ msgstr ""
|
|||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_reset_view_form
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_tsms_view_form
|
||||
msgid "Cancel"
|
||||
msgstr "Eyða"
|
||||
msgstr "Hætta við"
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields.selection,name:sms.selection__sms_sms__state__canceled
|
||||
msgid "Canceled"
|
||||
msgstr "Hætt við"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_preview_form
|
||||
|
|
@ -224,7 +198,7 @@ msgstr ""
|
|||
#: model_terms:ir.ui.view,arch_db:sms.mail_resend_message_view_form
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_composer_view_form
|
||||
msgid "Close"
|
||||
msgstr "Loka"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_composer__composition_mode
|
||||
|
|
@ -235,12 +209,12 @@ msgstr ""
|
|||
#: model:ir.model,name:sms.model_res_partner
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_tsms_view_form
|
||||
msgid "Contact"
|
||||
msgstr "Hafa samband"
|
||||
msgstr "Tengiliður"
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_view_form
|
||||
msgid "Content"
|
||||
msgstr "Innihald"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_composer__create_uid
|
||||
|
|
@ -262,12 +236,12 @@ msgstr "Búið til af"
|
|||
#: model:ir.model.fields,field_description:sms.field_sms_template_preview__create_date
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_template_reset__create_date
|
||||
msgid "Created on"
|
||||
msgstr "Búið til þann"
|
||||
msgstr "Stofnað þann"
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_sms__partner_id
|
||||
msgid "Customer"
|
||||
msgstr "Viðskiptavinur"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:sms.template,name:sms.sms_template_demo_0
|
||||
|
|
@ -282,7 +256,7 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_preview_form
|
||||
msgid "Discard"
|
||||
msgstr "Hætta við"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_composer__display_name
|
||||
|
|
@ -293,7 +267,7 @@ msgstr "Hætta við"
|
|||
#: model:ir.model.fields,field_description:sms.field_sms_template_preview__display_name
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_template_reset__display_name
|
||||
msgid "Display Name"
|
||||
msgstr "Birtingarnafn"
|
||||
msgstr "Nafn"
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model,name:sms.model_mail_followers
|
||||
|
|
@ -333,12 +307,18 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model:ir.model,name:sms.model_mail_thread
|
||||
msgid "Email Thread"
|
||||
msgstr "Email Thread"
|
||||
|
||||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/phone_field/phone_field.js:0
|
||||
msgid "Enable SMS"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields.selection,name:sms.selection__sms_sms__state__error
|
||||
msgid "Error"
|
||||
msgstr "Villa"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_resend_recipient__failure_type
|
||||
|
|
@ -357,31 +337,27 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__phone_sanitized
|
||||
msgid ""
|
||||
"Field used to store sanitized phone number. Helps speeding up searches and "
|
||||
"comparisons."
|
||||
msgid "Field used to store sanitized phone number. Helps speeding up searches and comparisons."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_sms_template__template_fs
|
||||
msgid ""
|
||||
"File from where the template originates. Used to reset broken template."
|
||||
msgid "File from where the template originates. Used to reset broken template."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_follower_ids
|
||||
msgid "Followers"
|
||||
msgstr "Fylgjendur"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_partner_ids
|
||||
msgid "Followers (Partners)"
|
||||
msgstr "Fylgjendur (samstarfsaðilar)"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/wizard/sms_composer.py:0
|
||||
#, python-format
|
||||
msgid "Following numbers are not correctly encoded: %s"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -393,7 +369,7 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__has_message
|
||||
msgid "Has Message"
|
||||
msgstr "Hefur skilaboð"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_mail__has_sms_error
|
||||
|
|
@ -415,18 +391,19 @@ msgstr ""
|
|||
#: model:ir.model.fields,field_description:sms.field_sms_template_preview__id
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_template_reset__id
|
||||
msgid "ID"
|
||||
msgstr "Auðkenni (ID)"
|
||||
msgstr "Auðkenni"
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__message_needaction
|
||||
msgid "If checked, new messages require your attention."
|
||||
msgstr "Ef hakað er við krefjast ný skilaboð athygli þinnar."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_account_analytic_account__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_calendar_event__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_crm_team__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_crm_team_member__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_discuss_channel__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_fleet_vehicle__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_fleet_vehicle_log_contract__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_fleet_vehicle_log_services__message_has_sms_error
|
||||
|
|
@ -438,13 +415,14 @@ msgstr "Ef hakað er við krefjast ný skilaboð athygli þinnar."
|
|||
#: model:ir.model.fields,help:sms.field_hr_job__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_hr_leave__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_hr_leave_allocation__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_hr_plan_employee_activity__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_loyalty_card__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_lunch_supplier__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_mail_blacklist__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_mail_channel__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_mail_thread__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_mail_thread_blacklist__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_mail_thread_cc__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_mail_thread_main_attachment__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_mail_thread_phone__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_maintenance_equipment__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_maintenance_equipment_category__message_has_sms_error
|
||||
|
|
@ -453,17 +431,16 @@ msgstr "Ef hakað er við krefjast ný skilaboð athygli þinnar."
|
|||
#: model:ir.model.fields,help:sms.field_phone_blacklist__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_product_product__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_product_template__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_rating_mixin__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__message_has_error
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_res_users__message_has_sms_error
|
||||
msgid "If checked, some messages have a delivery error."
|
||||
msgstr "Ef hakað er við hafa sum skilaboð sendingarvillu."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__phone_sanitized_blacklisted
|
||||
msgid ""
|
||||
"If the sanitized phone number is on the blacklist, the contact won't receive"
|
||||
" mass mailing sms anymore, from any list"
|
||||
msgid "If the sanitized phone number is on the blacklist, the contact won't receive mass mailing sms anymore, from any list"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -478,18 +455,12 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__mobile_blacklisted
|
||||
msgid ""
|
||||
"Indicates if a blacklisted sanitized phone number is a mobile number. Helps "
|
||||
"distinguish which number is blacklisted when there is both a "
|
||||
"mobile and phone field in a model."
|
||||
msgid "Indicates if a blacklisted sanitized phone number is a mobile number. Helps distinguish which number is blacklisted when there is both a mobile and phone field in a model."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__phone_blacklisted
|
||||
msgid ""
|
||||
"Indicates if a blacklisted sanitized phone number is a phone number. Helps "
|
||||
"distinguish which number is blacklisted when there is both a "
|
||||
"mobile and phone field in a model."
|
||||
msgid "Indicates if a blacklisted sanitized phone number is a phone number. Helps distinguish which number is blacklisted when there is both a mobile and phone field in a model."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -506,14 +477,13 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/wizard/sms_composer.py:0
|
||||
#, python-format
|
||||
msgid "Invalid recipient number. Please update it."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_is_follower
|
||||
msgid "Is Follower"
|
||||
msgstr "Er fylgjandi"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_composer__recipient_single_valid
|
||||
|
|
@ -530,17 +500,6 @@ msgstr ""
|
|||
msgid "Language"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_composer____last_update
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_resend____last_update
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_resend_recipient____last_update
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_sms____last_update
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_template____last_update
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_template_preview____last_update
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_template_reset____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_composer__write_uid
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_resend__write_uid
|
||||
|
|
@ -573,11 +532,6 @@ msgstr ""
|
|||
msgid "Mail Thread SMS"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_main_attachment_id
|
||||
msgid "Main Attachment"
|
||||
msgstr "Aðal viðhengi"
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model,name:sms.model_mail_message
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_composer__body
|
||||
|
|
@ -589,7 +543,7 @@ msgstr "Skilaboð"
|
|||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_has_error
|
||||
msgid "Message Delivery error"
|
||||
msgstr "Villa við afhendingu skilaboða"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model,name:sms.model_mail_notification
|
||||
|
|
@ -599,15 +553,13 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_mail_mail__message_type
|
||||
#: model:ir.model.fields,help:sms.field_mail_message__message_type
|
||||
msgid ""
|
||||
"Message type: email for email message, notification for system message, "
|
||||
"comment for other messages such as user replies"
|
||||
msgid "Message type: email for email message, notification for system message, comment for other messages such as user replies"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_ids
|
||||
msgid "Messages"
|
||||
msgstr "Skilaboð"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields.selection,name:sms.selection__mail_notification__failure_type__sms_number_missing
|
||||
|
|
@ -623,7 +575,7 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_template__name
|
||||
msgid "Name"
|
||||
msgstr "Nafn"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_template_preview__no_record
|
||||
|
|
@ -653,28 +605,26 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_needaction_counter
|
||||
msgid "Number of Actions"
|
||||
msgstr "Fjöldi aðgerða"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_has_error_counter
|
||||
msgid "Number of errors"
|
||||
msgstr "Fjöldi villna"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__message_needaction_counter
|
||||
msgid "Number of messages requiring action"
|
||||
msgstr "Fjöldi skeyta sem krefjast aðgerða"
|
||||
msgid "Number of messages which requires an action"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__message_has_error_counter
|
||||
msgid "Number of messages with delivery error"
|
||||
msgstr "Fjöldi skeyta með sendingarvillu"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_sms_composer__res_ids_count
|
||||
msgid ""
|
||||
"Number of recipients that will receive the SMS if sent in mass mode, without"
|
||||
" applying the Active Domain value"
|
||||
msgid "Number of recipients that will receive the SMS if sent in mass mode, without applying the Active Domain value"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -684,11 +634,7 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_sms_template__lang
|
||||
msgid ""
|
||||
"Optional translation language (ISO code) to select when sending out an "
|
||||
"email. If not set, the english version will be used. This should usually be "
|
||||
"a placeholder expression that provides the appropriate language, e.g. {{ "
|
||||
"object.partner_id.lang }}."
|
||||
msgid "Optional translation language (ISO code) to select when sending out an email. If not set, the english version will be used. This should usually be a placeholder expression that provides the appropriate language, e.g. {{ object.partner_id.lang }}."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -699,7 +645,7 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_resend_recipient__partner_id
|
||||
msgid "Partner"
|
||||
msgstr "Félagi"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model,name:sms.model_mail_thread_phone
|
||||
|
|
@ -714,13 +660,11 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_resend_recipient__sms_number
|
||||
msgid "Phone Number"
|
||||
msgstr "Símanúmer"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_sms_composer__recipient_single_number_itf
|
||||
msgid ""
|
||||
"Phone number of the recipient. If changed, it will be recorded on "
|
||||
"recipient's profile."
|
||||
msgid "Phone number of the recipient. If changed, it will be recorded on recipient's profile."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -743,11 +687,6 @@ msgstr ""
|
|||
msgid "Post on a document"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_view_form
|
||||
msgid "Preview"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_preview_form
|
||||
msgid "Preview of"
|
||||
|
|
@ -763,10 +702,15 @@ msgstr ""
|
|||
msgid "Put in queue"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__rating_ids
|
||||
msgid "Ratings"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.mail_resend_message_view_form
|
||||
msgid "Reason"
|
||||
msgstr "Ástæða"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.mail_resend_message_view_form
|
||||
|
|
@ -787,7 +731,7 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_resend__recipient_ids
|
||||
msgid "Recipients"
|
||||
msgstr ""
|
||||
msgstr "Viðtakendurf"
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_composer__numbers
|
||||
|
|
@ -843,13 +787,12 @@ msgstr ""
|
|||
#: model_terms:ir.ui.view,arch_db:sms.sms_sms_view_tree
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_tsms_view_form
|
||||
msgid "Retry"
|
||||
msgstr "Reyna"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/sms_button/sms_button.xml:0
|
||||
#: code:addons/sms/static/src/models/message_view.js:0
|
||||
#: code:addons/sms/static/src/models/message_view.js:0
|
||||
#: code:addons/sms/static/src/core/notification_model_patch.js:0
|
||||
#: model:ir.actions.act_window,name:sms.sms_sms_action
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_notification__sms_id
|
||||
#: model:ir.model.fields.selection,name:sms.selection__ir_actions_server__sms_method__sms
|
||||
|
|
@ -857,14 +800,12 @@ msgstr "Reyna"
|
|||
#: model:ir.model.fields.selection,name:sms.selection__mail_notification__notification_type__sms
|
||||
#: model:ir.ui.menu,name:sms.sms_sms_menu
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_tsms_view_form
|
||||
#, python-format
|
||||
msgid "SMS"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/sms_widget/fields_sms_widget.xml:0
|
||||
#, python-format
|
||||
msgid "SMS ("
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -878,6 +819,7 @@ msgstr ""
|
|||
#: model:ir.model.fields,field_description:sms.field_calendar_event__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_crm_team__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_crm_team_member__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_discuss_channel__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_fleet_vehicle__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_fleet_vehicle_log_contract__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_fleet_vehicle_log_services__message_has_sms_error
|
||||
|
|
@ -889,13 +831,14 @@ msgstr ""
|
|||
#: model:ir.model.fields,field_description:sms.field_hr_job__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_hr_leave__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_hr_leave_allocation__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_hr_plan_employee_activity__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_loyalty_card__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_lunch_supplier__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_blacklist__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_channel__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_thread__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_thread_blacklist__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_thread_cc__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_thread_main_attachment__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_thread_phone__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_maintenance_equipment__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_maintenance_equipment_category__message_has_sms_error
|
||||
|
|
@ -904,15 +847,15 @@ msgstr ""
|
|||
#: model:ir.model.fields,field_description:sms.field_phone_blacklist__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_product_product__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_product_template__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_rating_mixin__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_res_users__message_has_sms_error
|
||||
msgid "SMS Delivery error"
|
||||
msgstr "SMS sendingarvilla"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/models/notification_group.js:0
|
||||
#, python-format
|
||||
#: code:addons/sms/static/src/messaging_menu/messaging_menu_patch.js:0
|
||||
msgid "SMS Failures"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -929,8 +872,6 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/sms_widget/fields_sms_widget.xml:0
|
||||
#: code:addons/sms/static/src/components/sms_widget/fields_sms_widget.xml:0
|
||||
#, python-format
|
||||
msgid "SMS Pricing"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -974,7 +915,6 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/wizard/sms_template_reset.py:0
|
||||
#, python-format
|
||||
msgid "SMS Templates have been reset"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -985,7 +925,6 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#: model:ir.actions.server,name:sms.ir_cron_sms_scheduler_action_ir_actions_server
|
||||
#: model:ir.cron,cron_name:sms.ir_cron_sms_scheduler_action
|
||||
msgid "SMS: SMS Queue Manager"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -1021,20 +960,16 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_template.py:0
|
||||
#, python-format
|
||||
msgid "Send SMS (%s)"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/sms_button/sms_button.js:0
|
||||
#: code:addons/sms/static/src/js/fields_phone_widget.js:0
|
||||
#: code:addons/sms/static/src/js/fields_phone_widget.js:0
|
||||
#: model:ir.actions.act_window,name:sms.res_partner_act_window_sms_composer_multi
|
||||
#: model:ir.actions.act_window,name:sms.res_partner_act_window_sms_composer_single
|
||||
#: model:ir.actions.act_window,name:sms.sms_composer_action_form
|
||||
#: model:ir.model.fields.selection,name:sms.selection__ir_actions_server__state__sms
|
||||
#, python-format
|
||||
msgid "Send SMS Text Message"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -1083,14 +1018,13 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/ir_actions_server.py:0
|
||||
#, python-format
|
||||
msgid "Sending SMS can only be done on a not transient mail.thread model"
|
||||
msgid "Sending SMS can only be done on a mail.thread or a transient model"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields.selection,name:sms.selection__sms_sms__state__sent
|
||||
msgid "Sent"
|
||||
msgstr "Sent"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model,name:sms.model_ir_actions_server
|
||||
|
|
@ -1115,9 +1049,7 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_sms_template__sidebar_action_id
|
||||
msgid ""
|
||||
"Sidebar action to make this template available on records of the related "
|
||||
"document model"
|
||||
msgid "Sidebar action to make this template available on records of the related document model"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -1143,7 +1075,6 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_sms.py:0
|
||||
#, python-format
|
||||
msgid "Success"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -1175,14 +1106,12 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_sms.py:0
|
||||
#, python-format
|
||||
msgid "The SMS Text Messages could not be resent."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_api.py:0
|
||||
#, python-format
|
||||
msgid "The number you're trying to reach is not correctly formatted."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -1195,14 +1124,12 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_sms.py:0
|
||||
#, python-format
|
||||
msgid "There are no SMS Text Messages to resend."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.res_partner_view_form
|
||||
msgid ""
|
||||
"This phone number is blacklisted for SMS Marketing. Click to unblacklist."
|
||||
msgid "This phone number is blacklisted for SMS Marketing. Click to unblacklist."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -1256,19 +1183,18 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_sms.py:0
|
||||
#, python-format
|
||||
msgid "Warning"
|
||||
msgstr "Aðvörun"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__website_message_ids
|
||||
msgid "Website Messages"
|
||||
msgstr "Skilaboð á vefsíðu"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__website_message_ids
|
||||
msgid "Website communication history"
|
||||
msgstr "Samskiptasaga vefsíðu"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_ir_model__is_mail_thread_sms
|
||||
|
|
@ -1284,37 +1210,31 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/wizard/sms_resend.py:0
|
||||
#, python-format
|
||||
msgid "You do not have access to the message and/or related document."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_api.py:0
|
||||
#, python-format
|
||||
msgid "You don't have an eligible IAP account."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_api.py:0
|
||||
#, python-format
|
||||
msgid "You don't have enough credits on your IAP account."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/sms_widget/fields_sms_widget.js:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Your SMS Text Message must include at least one non-whitespace character"
|
||||
msgid "Your SMS Text Message must include at least one non-whitespace character"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/sms_widget/fields_sms_widget.xml:0
|
||||
#, python-format
|
||||
msgid "characters"
|
||||
msgid "characters, fits in"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -1344,9 +1264,7 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_composer_view_form
|
||||
msgid ""
|
||||
"recipients have an invalid phone number and will not receive this text "
|
||||
"message."
|
||||
msgid "recipients have an invalid phone number and will not receive this text message."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,27 +1,21 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * sms
|
||||
#
|
||||
# * sms
|
||||
#
|
||||
# Translators:
|
||||
# Sitthykun LY <ly.sitthykun@gmail.com>, 2023
|
||||
# AN Souphorn <ansouphorn@gmail.com>, 2023
|
||||
# Samkhann Seang <seangsamkhann@gmail.com>, 2023
|
||||
# Sengtha Chay <sengtha@gmail.com>, 2023
|
||||
# Chan Nath <channath@gmail.com>, 2023
|
||||
# Lux Sok <sok.lux@gmail.com>, 2025
|
||||
#
|
||||
# Sengtha Chay <sengtha@gmail.com>, 2018
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 16.0\n"
|
||||
"Project-Id-Version: Odoo Server saas~11.5\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-05-06 20:36+0000\n"
|
||||
"PO-Revision-Date: 2022-09-22 05:55+0000\n"
|
||||
"Last-Translator: Lux Sok <sok.lux@gmail.com>, 2025\n"
|
||||
"Language-Team: Khmer (https://app.transifex.com/odoo/teams/41243/km/)\n"
|
||||
"POT-Creation-Date: 2023-05-16 13:49+0000\n"
|
||||
"PO-Revision-Date: 2018-09-21 13:17+0000\n"
|
||||
"Last-Translator: Sengtha Chay <sengtha@gmail.com>, 2018\n"
|
||||
"Language-Team: Khmer (https://www.transifex.com/odoo/teams/41243/km/)\n"
|
||||
"Language: km\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Language: km\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -37,30 +31,19 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_template.py:0
|
||||
#, python-format
|
||||
msgid "%s (copy)"
|
||||
msgstr "%s (ចម្លង)"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/wizard/sms_composer.py:0
|
||||
#, python-format
|
||||
msgid "%s invalid recipients"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_sms.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%s out of the %s selected SMS Text Messages have successfully been resent."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/sms_widget/fields_sms_widget.xml:0
|
||||
#, python-format
|
||||
msgid ", fits in"
|
||||
msgid "%s out of the %s selected SMS Text Messages have successfully been resent."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -70,6 +53,11 @@ msgid ""
|
|||
" <span class=\"o_stat_text\">Context Action</span>"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_view_form
|
||||
msgid "<span class=\"o_stat_text\">Preview</span>"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_view_form
|
||||
msgid ""
|
||||
|
|
@ -79,9 +67,7 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_preview_form
|
||||
msgid ""
|
||||
"<span class=\"text-warning\" attrs=\"{'invisible': [('no_record', '=', "
|
||||
"False)]}\">No records</span>"
|
||||
msgid "<span class=\"text-warning\" attrs=\"{'invisible': [('no_record', '=', False)]}\">No records</span>"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -99,51 +85,41 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_needaction
|
||||
msgid "Action Needed"
|
||||
msgstr "តម្រូវការសកម្មភាព"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_base_automation__state
|
||||
#: model:ir.model.fields,field_description:sms.field_ir_actions_server__state
|
||||
#: model:ir.model.fields,field_description:sms.field_ir_cron__state
|
||||
msgid "Action To Do"
|
||||
msgstr "តាមដានសកម្មភាព"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_view_form
|
||||
msgid ""
|
||||
"Add a contextual action on the related model to open a sms composer with "
|
||||
"this template"
|
||||
msgid "Add a contextual action on the related model to open a sms composer with this template"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/notification_group/notification_group.xml:0
|
||||
#, python-format
|
||||
msgid "An error occurred when sending an SMS."
|
||||
#: code:addons/sms/static/src/core/notification_group_model_patch.js:0
|
||||
msgid "An error occurred when sending an SMS"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_template__model_id
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_template_preview__model_id
|
||||
msgid "Applies to"
|
||||
msgstr "ដាក់ពាក្យទៅ"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_reset_view_form
|
||||
msgid ""
|
||||
"Are you sure you want to reset these sms templates to their original "
|
||||
"configuration? Changes and translations will be lost."
|
||||
msgid "Are you sure you want to reset these sms templates to their original configuration? Changes and translations will be lost."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_attachment_count
|
||||
msgid "Attachment Count"
|
||||
msgstr "ចំនួនឯកសារភ្ជាប់"
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model,name:sms.model_base
|
||||
msgid "Base"
|
||||
msgstr "មូលដ្ឋាន"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields.selection,name:sms.selection__sms_sms__failure_type__sms_blacklist
|
||||
|
|
@ -165,17 +141,16 @@ msgstr ""
|
|||
#: model:ir.model.fields,field_description:sms.field_sms_template__body
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_template_preview__body
|
||||
msgid "Body"
|
||||
msgstr "រូបរាង"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.mail_resend_message_view_form
|
||||
msgid "Buy credits"
|
||||
msgstr "ការទិញដោយជំពាក់"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_api.py:0
|
||||
#, python-format
|
||||
msgid "Buy credits."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -199,7 +174,7 @@ msgstr "លុបចោល"
|
|||
#. module: sms
|
||||
#: model:ir.model.fields.selection,name:sms.selection__sms_sms__state__canceled
|
||||
msgid "Canceled"
|
||||
msgstr "លុបចោល"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_preview_form
|
||||
|
|
@ -226,7 +201,7 @@ msgstr ""
|
|||
#: model_terms:ir.ui.view,arch_db:sms.mail_resend_message_view_form
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_composer_view_form
|
||||
msgid "Close"
|
||||
msgstr "បិទ"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_composer__composition_mode
|
||||
|
|
@ -242,7 +217,7 @@ msgstr "ទំនាក់ទំនង"
|
|||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_view_form
|
||||
msgid "Content"
|
||||
msgstr "មាតិកា"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_composer__create_uid
|
||||
|
|
@ -269,7 +244,7 @@ msgstr "បង្កើតនៅ"
|
|||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_sms__partner_id
|
||||
msgid "Customer"
|
||||
msgstr "អតិថិជន"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:sms.template,name:sms.sms_template_demo_0
|
||||
|
|
@ -284,7 +259,7 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_preview_form
|
||||
msgid "Discard"
|
||||
msgstr "បោះបង់"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_composer__display_name
|
||||
|
|
@ -305,7 +280,7 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_composer__res_id
|
||||
msgid "Document ID"
|
||||
msgstr "អត្ត. ឯកសារ"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_composer__res_ids
|
||||
|
|
@ -320,12 +295,12 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_composer__res_model
|
||||
msgid "Document Model Name"
|
||||
msgstr "ឈ្មោះឯកសារគំរូ"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields.selection,name:sms.selection__sms_sms__failure_type__sms_duplicate
|
||||
msgid "Duplicate"
|
||||
msgstr "ត្រួត"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.mail_resend_message_view_form
|
||||
|
|
@ -335,17 +310,23 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model:ir.model,name:sms.model_mail_thread
|
||||
msgid "Email Thread"
|
||||
msgstr "អ៊ីម៉ែលខ្សែស្រឡាយ"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/phone_field/phone_field.js:0
|
||||
msgid "Enable SMS"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields.selection,name:sms.selection__sms_sms__state__error
|
||||
msgid "Error"
|
||||
msgstr "កំហុស"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_resend_recipient__failure_type
|
||||
msgid "Error Message"
|
||||
msgstr "សារកំហុស"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_sms__failure_type
|
||||
|
|
@ -355,35 +336,31 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_notification__failure_type
|
||||
msgid "Failure type"
|
||||
msgstr "ប្រភេទបរាជ័យ។"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__phone_sanitized
|
||||
msgid ""
|
||||
"Field used to store sanitized phone number. Helps speeding up searches and "
|
||||
"comparisons."
|
||||
msgid "Field used to store sanitized phone number. Helps speeding up searches and comparisons."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_sms_template__template_fs
|
||||
msgid ""
|
||||
"File from where the template originates. Used to reset broken template."
|
||||
msgid "File from where the template originates. Used to reset broken template."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_follower_ids
|
||||
msgid "Followers"
|
||||
msgstr "អ្នកតាម"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_partner_ids
|
||||
msgid "Followers (Partners)"
|
||||
msgstr "អ្នកដើរតាម (ដៃគូរ)"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/wizard/sms_composer.py:0
|
||||
#, python-format
|
||||
msgid "Following numbers are not correctly encoded: %s"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -417,18 +394,19 @@ msgstr ""
|
|||
#: model:ir.model.fields,field_description:sms.field_sms_template_preview__id
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_template_reset__id
|
||||
msgid "ID"
|
||||
msgstr "អត្តសញ្ញាណ"
|
||||
msgstr "ID"
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__message_needaction
|
||||
msgid "If checked, new messages require your attention."
|
||||
msgstr "ប្រសិនបើបានគូសធីកសារថ្មីទាមទារការយកចិត្តទុកដាក់របស់អ្នក។"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_account_analytic_account__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_calendar_event__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_crm_team__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_crm_team_member__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_discuss_channel__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_fleet_vehicle__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_fleet_vehicle_log_contract__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_fleet_vehicle_log_services__message_has_sms_error
|
||||
|
|
@ -440,13 +418,14 @@ msgstr "ប្រសិនបើបានគូសធីកសារថ្មី
|
|||
#: model:ir.model.fields,help:sms.field_hr_job__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_hr_leave__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_hr_leave_allocation__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_hr_plan_employee_activity__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_loyalty_card__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_lunch_supplier__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_mail_blacklist__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_mail_channel__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_mail_thread__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_mail_thread_blacklist__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_mail_thread_cc__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_mail_thread_main_attachment__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_mail_thread_phone__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_maintenance_equipment__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_maintenance_equipment_category__message_has_sms_error
|
||||
|
|
@ -455,17 +434,16 @@ msgstr "ប្រសិនបើបានគូសធីកសារថ្មី
|
|||
#: model:ir.model.fields,help:sms.field_phone_blacklist__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_product_product__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_product_template__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_rating_mixin__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__message_has_error
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__message_has_sms_error
|
||||
#: model:ir.model.fields,help:sms.field_res_users__message_has_sms_error
|
||||
msgid "If checked, some messages have a delivery error."
|
||||
msgstr "ប្រសិនបើបានគូសធីកសារខ្លះមានកំហុសបញ្ជូន។"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__phone_sanitized_blacklisted
|
||||
msgid ""
|
||||
"If the sanitized phone number is on the blacklist, the contact won't receive"
|
||||
" mass mailing sms anymore, from any list"
|
||||
msgid "If the sanitized phone number is on the blacklist, the contact won't receive mass mailing sms anymore, from any list"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -476,22 +454,16 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model:ir.model.fields.selection,name:sms.selection__sms_sms__state__outgoing
|
||||
msgid "In Queue"
|
||||
msgstr "នៅក្នុងជួរ"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__mobile_blacklisted
|
||||
msgid ""
|
||||
"Indicates if a blacklisted sanitized phone number is a mobile number. Helps "
|
||||
"distinguish which number is blacklisted when there is both a "
|
||||
"mobile and phone field in a model."
|
||||
msgid "Indicates if a blacklisted sanitized phone number is a mobile number. Helps distinguish which number is blacklisted when there is both a mobile and phone field in a model."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__phone_blacklisted
|
||||
msgid ""
|
||||
"Indicates if a blacklisted sanitized phone number is a phone number. Helps "
|
||||
"distinguish which number is blacklisted when there is both a "
|
||||
"mobile and phone field in a model."
|
||||
msgid "Indicates if a blacklisted sanitized phone number is a phone number. Helps distinguish which number is blacklisted when there is both a mobile and phone field in a model."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -508,14 +480,13 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/wizard/sms_composer.py:0
|
||||
#, python-format
|
||||
msgid "Invalid recipient number. Please update it."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_is_follower
|
||||
msgid "Is Follower"
|
||||
msgstr "ត្រូវតាមអ្នក"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_composer__recipient_single_valid
|
||||
|
|
@ -530,18 +501,7 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_template__lang
|
||||
msgid "Language"
|
||||
msgstr "ភាសារ"
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_composer____last_update
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_resend____last_update
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_resend_recipient____last_update
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_sms____last_update
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_template____last_update
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_template_preview____last_update
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_template_reset____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr "កាលបរិច្ឆេតកែប្រែចុងក្រោយ"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_composer__write_uid
|
||||
|
|
@ -575,43 +535,34 @@ msgstr ""
|
|||
msgid "Mail Thread SMS"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_main_attachment_id
|
||||
msgid "Main Attachment"
|
||||
msgstr "ឯកសារភ្ជាប់សំខាន់"
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model,name:sms.model_mail_message
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_composer__body
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_resend__mail_message_id
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_tsms_view_form
|
||||
msgid "Message"
|
||||
msgstr "សារ"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_has_error
|
||||
msgid "Message Delivery error"
|
||||
msgstr "កំហុសក្នុងការផ្ញើសារ"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model,name:sms.model_mail_notification
|
||||
msgid "Message Notifications"
|
||||
msgstr "ការជូនដំណឹងសារ"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_mail_mail__message_type
|
||||
#: model:ir.model.fields,help:sms.field_mail_message__message_type
|
||||
msgid ""
|
||||
"Message type: email for email message, notification for system message, "
|
||||
"comment for other messages such as user replies"
|
||||
msgid "Message type: email for email message, notification for system message, comment for other messages such as user replies"
|
||||
msgstr ""
|
||||
"ប្រភេទសារ: សារអេឡិចត្រូនិចសម្រាប់សារអ៊ីម៉ែល, ការជូនដំណឹងសម្រាប់ប្រព័ន្ធសារ, "
|
||||
"មតិយោបល់សម្រាប់សារផ្សេងទៀតដូចជាការឆ្លើយតបរបស់អ្នកប្រើ"
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_ids
|
||||
msgid "Messages"
|
||||
msgstr "សារ"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields.selection,name:sms.selection__mail_notification__failure_type__sms_number_missing
|
||||
|
|
@ -622,12 +573,12 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model:ir.model,name:sms.model_ir_model
|
||||
msgid "Models"
|
||||
msgstr "ម៉ូត"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_template__name
|
||||
msgid "Name"
|
||||
msgstr "ឈ្មោះ"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_template_preview__no_record
|
||||
|
|
@ -637,7 +588,7 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_resend_recipient__notification_id
|
||||
msgid "Notification"
|
||||
msgstr "សេចក្តីជូនដំណឹង"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_notification__notification_type
|
||||
|
|
@ -647,7 +598,7 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_sms__number
|
||||
msgid "Number"
|
||||
msgstr "តួរលេខ"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_composer__number_field_name
|
||||
|
|
@ -657,7 +608,7 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_needaction_counter
|
||||
msgid "Number of Actions"
|
||||
msgstr "ចំនួនសកម្មភាព"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_has_error_counter
|
||||
|
|
@ -666,19 +617,17 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__message_needaction_counter
|
||||
msgid "Number of messages requiring action"
|
||||
msgid "Number of messages which requires an action"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__message_has_error_counter
|
||||
msgid "Number of messages with delivery error"
|
||||
msgstr "ចំនួនសារដែលមានកំហុសឆ្គងនៃការដឹកជញ្ជូន"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_sms_composer__res_ids_count
|
||||
msgid ""
|
||||
"Number of recipients that will receive the SMS if sent in mass mode, without"
|
||||
" applying the Active Domain value"
|
||||
msgid "Number of recipients that will receive the SMS if sent in mass mode, without applying the Active Domain value"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -688,11 +637,7 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_sms_template__lang
|
||||
msgid ""
|
||||
"Optional translation language (ISO code) to select when sending out an "
|
||||
"email. If not set, the english version will be used. This should usually be "
|
||||
"a placeholder expression that provides the appropriate language, e.g. {{ "
|
||||
"object.partner_id.lang }}."
|
||||
msgid "Optional translation language (ISO code) to select when sending out an email. If not set, the english version will be used. This should usually be a placeholder expression that provides the appropriate language, e.g. {{ object.partner_id.lang }}."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -703,7 +648,7 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_resend_recipient__partner_id
|
||||
msgid "Partner"
|
||||
msgstr "ដៃគូ"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model,name:sms.model_mail_thread_phone
|
||||
|
|
@ -718,13 +663,11 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_resend_recipient__sms_number
|
||||
msgid "Phone Number"
|
||||
msgstr "លេខទូរស័ព្ទ"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_sms_composer__recipient_single_number_itf
|
||||
msgid ""
|
||||
"Phone number of the recipient. If changed, it will be recorded on "
|
||||
"recipient's profile."
|
||||
msgid "Phone number of the recipient. If changed, it will be recorded on recipient's profile."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -747,11 +690,6 @@ msgstr ""
|
|||
msgid "Post on a document"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_view_form
|
||||
msgid "Preview"
|
||||
msgstr "ពីមុន"
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_preview_form
|
||||
msgid "Preview of"
|
||||
|
|
@ -767,16 +705,21 @@ msgstr ""
|
|||
msgid "Put in queue"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__rating_ids
|
||||
msgid "Ratings"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.mail_resend_message_view_form
|
||||
msgid "Reason"
|
||||
msgstr "ហេតុផល"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.mail_resend_message_view_form
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_composer_view_form
|
||||
msgid "Recipient"
|
||||
msgstr "ការទទួល"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_resend_recipient__partner_name
|
||||
|
|
@ -811,7 +754,7 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_template__model
|
||||
msgid "Related Document Model"
|
||||
msgstr "គំរូឯកសារដែលទាក់ទង"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_template_view_form
|
||||
|
|
@ -852,8 +795,7 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/sms_button/sms_button.xml:0
|
||||
#: code:addons/sms/static/src/models/message_view.js:0
|
||||
#: code:addons/sms/static/src/models/message_view.js:0
|
||||
#: code:addons/sms/static/src/core/notification_model_patch.js:0
|
||||
#: model:ir.actions.act_window,name:sms.sms_sms_action
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_notification__sms_id
|
||||
#: model:ir.model.fields.selection,name:sms.selection__ir_actions_server__sms_method__sms
|
||||
|
|
@ -861,27 +803,26 @@ msgstr ""
|
|||
#: model:ir.model.fields.selection,name:sms.selection__mail_notification__notification_type__sms
|
||||
#: model:ir.ui.menu,name:sms.sms_sms_menu
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_tsms_view_form
|
||||
#, python-format
|
||||
msgid "SMS"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/sms_widget/fields_sms_widget.xml:0
|
||||
#, python-format
|
||||
msgid "SMS ("
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model,name:sms.model_sms_api
|
||||
msgid "SMS API"
|
||||
msgstr "SMS API"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_account_analytic_account__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_calendar_event__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_crm_team__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_crm_team_member__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_discuss_channel__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_fleet_vehicle__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_fleet_vehicle_log_contract__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_fleet_vehicle_log_services__message_has_sms_error
|
||||
|
|
@ -893,13 +834,14 @@ msgstr "SMS API"
|
|||
#: model:ir.model.fields,field_description:sms.field_hr_job__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_hr_leave__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_hr_leave_allocation__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_hr_plan_employee_activity__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_loyalty_card__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_lunch_supplier__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_blacklist__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_channel__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_thread__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_thread_blacklist__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_thread_cc__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_thread_main_attachment__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_thread_phone__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_maintenance_equipment__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_maintenance_equipment_category__message_has_sms_error
|
||||
|
|
@ -908,6 +850,7 @@ msgstr "SMS API"
|
|||
#: model:ir.model.fields,field_description:sms.field_phone_blacklist__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_product_product__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_product_template__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_rating_mixin__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__message_has_sms_error
|
||||
#: model:ir.model.fields,field_description:sms.field_res_users__message_has_sms_error
|
||||
msgid "SMS Delivery error"
|
||||
|
|
@ -915,8 +858,7 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/models/notification_group.js:0
|
||||
#, python-format
|
||||
#: code:addons/sms/static/src/messaging_menu/messaging_menu_patch.js:0
|
||||
msgid "SMS Failures"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -933,10 +875,8 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/sms_widget/fields_sms_widget.xml:0
|
||||
#: code:addons/sms/static/src/components/sms_widget/fields_sms_widget.xml:0
|
||||
#, python-format
|
||||
msgid "SMS Pricing"
|
||||
msgstr "តម្លៃ សារ SMS"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model,name:sms.model_sms_resend
|
||||
|
|
@ -978,7 +918,6 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/wizard/sms_template_reset.py:0
|
||||
#, python-format
|
||||
msgid "SMS Templates have been reset"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -989,7 +928,6 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#: model:ir.actions.server,name:sms.ir_cron_sms_scheduler_action_ir_actions_server
|
||||
#: model:ir.cron,cron_name:sms.ir_cron_sms_scheduler_action
|
||||
msgid "SMS: SMS Queue Manager"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -1015,30 +953,26 @@ msgstr ""
|
|||
#: model_terms:ir.ui.view,arch_db:sms.sms_sms_view_tree
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_tsms_view_form
|
||||
msgid "Send Now"
|
||||
msgstr "ការផ្ញើរឥឡូវ"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_composer_view_form
|
||||
msgid "Send SMS"
|
||||
msgstr "ផ្ញើរសារ SMS"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_template.py:0
|
||||
#, python-format
|
||||
msgid "Send SMS (%s)"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/sms_button/sms_button.js:0
|
||||
#: code:addons/sms/static/src/js/fields_phone_widget.js:0
|
||||
#: code:addons/sms/static/src/js/fields_phone_widget.js:0
|
||||
#: model:ir.actions.act_window,name:sms.res_partner_act_window_sms_composer_multi
|
||||
#: model:ir.actions.act_window,name:sms.res_partner_act_window_sms_composer_single
|
||||
#: model:ir.actions.act_window,name:sms.sms_composer_action_form
|
||||
#: model:ir.model.fields.selection,name:sms.selection__ir_actions_server__state__sms
|
||||
#, python-format
|
||||
msgid "Send SMS Text Message"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -1055,7 +989,7 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_composer_view_form
|
||||
msgid "Send an SMS"
|
||||
msgstr "ផ្ញើរសារ SMSមួយ"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.ir_actions_server_view_form
|
||||
|
|
@ -1087,25 +1021,24 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/ir_actions_server.py:0
|
||||
#, python-format
|
||||
msgid "Sending SMS can only be done on a not transient mail.thread model"
|
||||
msgid "Sending SMS can only be done on a mail.thread or a transient model"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields.selection,name:sms.selection__sms_sms__state__sent
|
||||
msgid "Sent"
|
||||
msgstr "បានផ្ងើរ"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model,name:sms.model_ir_actions_server
|
||||
msgid "Server Action"
|
||||
msgstr "សកម្មភាពម៉ាស៊ីនបម្រើ"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields.selection,name:sms.selection__mail_notification__failure_type__sms_server
|
||||
#: model:ir.model.fields.selection,name:sms.selection__sms_sms__failure_type__sms_server
|
||||
msgid "Server Error"
|
||||
msgstr "កំហុសម៉ាស៊ីន"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.mail_resend_message_view_form
|
||||
|
|
@ -1119,9 +1052,7 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_sms_template__sidebar_action_id
|
||||
msgid ""
|
||||
"Sidebar action to make this template available on records of the related "
|
||||
"document model"
|
||||
msgid "Sidebar action to make this template available on records of the related document model"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -1147,14 +1078,13 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_sms.py:0
|
||||
#, python-format
|
||||
msgid "Success"
|
||||
msgstr "ជោគជ័យ"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_template_reset__template_ids
|
||||
msgid "Template"
|
||||
msgstr "គំរូ"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_sms_template__template_fs
|
||||
|
|
@ -1174,19 +1104,17 @@ msgstr ""
|
|||
#. module: sms
|
||||
#: model:ir.actions.act_window,name:sms.sms_template_action
|
||||
msgid "Templates"
|
||||
msgstr "គម្រូ"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_sms.py:0
|
||||
#, python-format
|
||||
msgid "The SMS Text Messages could not be resent."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_api.py:0
|
||||
#, python-format
|
||||
msgid "The number you're trying to reach is not correctly formatted."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -1199,14 +1127,12 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_sms.py:0
|
||||
#, python-format
|
||||
msgid "There are no SMS Text Messages to resend."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.res_partner_view_form
|
||||
msgid ""
|
||||
"This phone number is blacklisted for SMS Marketing. Click to unblacklist."
|
||||
msgid "This phone number is blacklisted for SMS Marketing. Click to unblacklist."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -1218,7 +1144,7 @@ msgstr ""
|
|||
#: model:ir.model.fields,field_description:sms.field_mail_mail__message_type
|
||||
#: model:ir.model.fields,field_description:sms.field_mail_message__message_type
|
||||
msgid "Type"
|
||||
msgstr "ប្រភេទ"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_base_automation__state
|
||||
|
|
@ -1260,19 +1186,18 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_sms.py:0
|
||||
#, python-format
|
||||
msgid "Warning"
|
||||
msgstr "ព្រមាន"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,field_description:sms.field_res_partner__website_message_ids
|
||||
msgid "Website Messages"
|
||||
msgstr "សារវែបសាយ"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_res_partner__website_message_ids
|
||||
msgid "Website communication history"
|
||||
msgstr "ប្រវត្តិទំនាក់ទំនងវែបសាយ"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#: model:ir.model.fields,help:sms.field_ir_model__is_mail_thread_sms
|
||||
|
|
@ -1288,37 +1213,31 @@ msgstr ""
|
|||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/wizard/sms_resend.py:0
|
||||
#, python-format
|
||||
msgid "You do not have access to the message and/or related document."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_api.py:0
|
||||
#, python-format
|
||||
msgid "You don't have an eligible IAP account."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-python
|
||||
#: code:addons/sms/models/sms_api.py:0
|
||||
#, python-format
|
||||
msgid "You don't have enough credits on your IAP account."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/sms_widget/fields_sms_widget.js:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Your SMS Text Message must include at least one non-whitespace character"
|
||||
msgid "Your SMS Text Message must include at least one non-whitespace character"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
#. odoo-javascript
|
||||
#: code:addons/sms/static/src/components/sms_widget/fields_sms_widget.xml:0
|
||||
#, python-format
|
||||
msgid "characters"
|
||||
msgid "characters, fits in"
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
@ -1348,9 +1267,7 @@ msgstr ""
|
|||
|
||||
#. module: sms
|
||||
#: model_terms:ir.ui.view,arch_db:sms.sms_composer_view_form
|
||||
msgid ""
|
||||
"recipients have an invalid phone number and will not receive this text "
|
||||
"message."
|
||||
msgid "recipients have an invalid phone number and will not receive this text message."
|
||||
msgstr ""
|
||||
|
||||
#. module: sms
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
1894
odoo-bringout-oca-ocb-sms/sms/i18n/uz.po
Normal file
1894
odoo-bringout-oca-ocb-sms/sms/i18n/uz.po
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,15 +1,15 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import iap_account
|
||||
from . import ir_actions_server
|
||||
from . import ir_model
|
||||
from . import mail_followers
|
||||
from . import mail_message
|
||||
from . import mail_notification
|
||||
from . import mail_thread
|
||||
from . import mail_thread_phone
|
||||
from . import models
|
||||
from . import res_partner
|
||||
from . import sms_api
|
||||
from . import res_company
|
||||
from . import sms_sms
|
||||
from . import sms_template
|
||||
from . import sms_tracker
|
||||
|
|
|
|||
35
odoo-bringout-oca-ocb-sms/sms/models/iap_account.py
Normal file
35
odoo-bringout-oca-ocb-sms/sms/models/iap_account.py
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import fields, models, _
|
||||
|
||||
|
||||
class IapAccount(models.Model):
|
||||
_inherit = 'iap.account'
|
||||
|
||||
sender_name = fields.Char(help="This is the name that will be displayed as the sender of the SMS.", readonly=True)
|
||||
|
||||
def action_open_registration_wizard(self):
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'target': 'new',
|
||||
'name': _('Register Account'),
|
||||
'view_mode': 'form',
|
||||
'res_model': 'sms.account.phone',
|
||||
'context': {'default_account_id': self.id},
|
||||
}
|
||||
|
||||
def action_open_sender_name_wizard(self):
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'target': 'new',
|
||||
'name': _('Choose your sender name'),
|
||||
'view_mode': 'form',
|
||||
'res_model': 'sms.account.sender',
|
||||
'context': {'default_account_id': self.id},
|
||||
}
|
||||
|
||||
def _get_account_info(self, account_id, balance, information):
|
||||
res = super()._get_account_info(account_id, balance, information)
|
||||
if account_id.service_name == 'sms':
|
||||
res['sender_name'] = information.get('sender_name')
|
||||
return res
|
||||
|
|
@ -2,16 +2,14 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class ServerActions(models.Model):
|
||||
class IrActionsServer(models.Model):
|
||||
""" Add SMS option in server actions. """
|
||||
_name = 'ir.actions.server'
|
||||
_inherit = ['ir.actions.server']
|
||||
_inherit = 'ir.actions.server'
|
||||
|
||||
state = fields.Selection(selection_add=[
|
||||
('sms', 'Send SMS Text Message'),
|
||||
('sms', 'Send SMS'), ('followers',),
|
||||
], ondelete={'sms': 'cascade'})
|
||||
# SMS
|
||||
sms_template_id = fields.Many2one(
|
||||
|
|
@ -21,11 +19,28 @@ class ServerActions(models.Model):
|
|||
domain="[('model_id', '=', model_id)]",
|
||||
)
|
||||
sms_method = fields.Selection(
|
||||
selection=[('sms', 'SMS'), ('comment', 'Post as Message'), ('note', 'Post as Note')],
|
||||
string='Send as (SMS)',
|
||||
selection=[('sms', 'SMS (without note)'), ('comment', 'SMS (with note)'), ('note', 'Note only')],
|
||||
string='Send SMS As',
|
||||
compute='_compute_sms_method',
|
||||
readonly=False, store=True,
|
||||
help='Choose method for SMS sending:\nSMS: mass SMS\nPost as Message: log on document\nPost as Note: mass SMS with archives')
|
||||
readonly=False, store=True)
|
||||
|
||||
def _name_depends(self):
|
||||
return [*super()._name_depends(), "sms_template_id"]
|
||||
|
||||
def _generate_action_name(self):
|
||||
self.ensure_one()
|
||||
if self.state == 'sms' and self.sms_template_id:
|
||||
return _('Send %(template_name)s', template_name=self.sms_template_id.name)
|
||||
return super()._generate_action_name()
|
||||
|
||||
@api.depends('state')
|
||||
def _compute_available_model_ids(self):
|
||||
mail_thread_based = self.filtered(lambda action: action.state == 'sms')
|
||||
if mail_thread_based:
|
||||
mail_models = self.env['ir.model'].search([('is_mail_thread', '=', True), ('transient', '=', False)])
|
||||
for action in mail_thread_based:
|
||||
action.available_model_ids = mail_models.ids
|
||||
super(IrActionsServer, self - mail_thread_based)._compute_available_model_ids()
|
||||
|
||||
@api.depends('model_id', 'state')
|
||||
def _compute_sms_template_id(self):
|
||||
|
|
@ -45,11 +60,30 @@ class ServerActions(models.Model):
|
|||
if other:
|
||||
other.sms_method = 'sms'
|
||||
|
||||
def _check_model_coherency(self):
|
||||
super()._check_model_coherency()
|
||||
for action in self:
|
||||
if action.state == 'sms' and (action.model_id.transient or not action.model_id.is_mail_thread):
|
||||
raise ValidationError(_("Sending SMS can only be done on a not transient mail.thread model"))
|
||||
@api.model
|
||||
def _warning_depends(self):
|
||||
return super()._warning_depends() + [
|
||||
'model_id',
|
||||
'state',
|
||||
'sms_template_id',
|
||||
]
|
||||
|
||||
def _get_warning_messages(self):
|
||||
self.ensure_one()
|
||||
warnings = super()._get_warning_messages()
|
||||
|
||||
if self.state == 'sms':
|
||||
if self.model_id.transient or not self.model_id.is_mail_thread:
|
||||
warnings.append(_("Sending SMS can only be done on a not transient mail.thread model"))
|
||||
|
||||
if self.sms_template_id and self.sms_template_id.model_id != self.model_id:
|
||||
warnings.append(
|
||||
_('SMS template model of %(action_name)s does not match action model.',
|
||||
action_name=self.name
|
||||
)
|
||||
)
|
||||
|
||||
return warnings
|
||||
|
||||
def _run_action_sms_multi(self, eval_context=None):
|
||||
# TDE CLEANME: when going to new api with server action, remove action
|
||||
|
|
|
|||
|
|
@ -18,24 +18,23 @@ class IrModel(models.Model):
|
|||
for model in self:
|
||||
if model.is_mail_thread:
|
||||
ModelObject = self.env[model.model]
|
||||
potential_fields = ModelObject._sms_get_number_fields() + ModelObject._sms_get_partner_fields()
|
||||
potential_fields = ModelObject._phone_get_number_fields() + ModelObject._mail_get_partner_fields()
|
||||
if any(fname in ModelObject._fields for fname in potential_fields):
|
||||
model.is_mail_thread_sms = True
|
||||
continue
|
||||
model.is_mail_thread_sms = False
|
||||
|
||||
def _search_is_mail_thread_sms(self, operator, value):
|
||||
if operator != 'in':
|
||||
return NotImplemented
|
||||
thread_models = self.search([('is_mail_thread', '=', True)])
|
||||
valid_models = self.env['ir.model']
|
||||
for model in thread_models:
|
||||
if model.model not in self.env:
|
||||
continue
|
||||
ModelObject = self.env[model.model]
|
||||
potential_fields = ModelObject._sms_get_number_fields() + ModelObject._sms_get_partner_fields()
|
||||
potential_fields = ModelObject._phone_get_number_fields() + ModelObject._mail_get_partner_fields()
|
||||
if any(fname in ModelObject._fields for fname in potential_fields):
|
||||
valid_models |= model
|
||||
|
||||
search_sms = (operator == '=' and value) or (operator == '!=' and not value)
|
||||
if search_sms:
|
||||
return [('id', 'in', valid_models.ids)]
|
||||
return [('id', 'not in', valid_models.ids)]
|
||||
return [('id', 'in', valid_models.ids)]
|
||||
|
|
|
|||
|
|
@ -4,23 +4,23 @@
|
|||
from odoo import models
|
||||
|
||||
|
||||
class Followers(models.Model):
|
||||
_inherit = ['mail.followers']
|
||||
class MailFollowers(models.Model):
|
||||
_inherit = 'mail.followers'
|
||||
|
||||
def _get_recipient_data(self, records, message_type, subtype_id, pids=None):
|
||||
recipients_data = super()._get_recipient_data(records, message_type, subtype_id, pids=pids)
|
||||
if message_type != 'sms' or not (pids or records):
|
||||
return super(Followers, self)._get_recipient_data(records, message_type, subtype_id, pids=pids)
|
||||
return recipients_data
|
||||
|
||||
if pids is None and records:
|
||||
records_pids = dict(
|
||||
(record.id, record._sms_get_default_partners().ids)
|
||||
for record in records
|
||||
(rec_id, partners.ids)
|
||||
for rec_id, partners in records._mail_get_partners().items()
|
||||
)
|
||||
elif pids and records:
|
||||
records_pids = dict((record.id, pids) for record in records)
|
||||
else:
|
||||
records_pids = {0: pids if pids else []}
|
||||
recipients_data = super(Followers, self)._get_recipient_data(records, message_type, subtype_id, pids=pids)
|
||||
for rid, rdata in recipients_data.items():
|
||||
sms_pids = records_pids.get(rid) or []
|
||||
for pid, pdata in rdata.items():
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from collections import defaultdict
|
||||
from operator import itemgetter
|
||||
|
||||
from odoo import exceptions, fields, models
|
||||
from odoo.tools import groupby
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class MailMessage(models.Model):
|
||||
|
|
@ -14,9 +9,9 @@ class MailMessage(models.Model):
|
|||
gateway. """
|
||||
_inherit = 'mail.message'
|
||||
|
||||
message_type = fields.Selection(selection_add=[
|
||||
('sms', 'SMS')
|
||||
], ondelete={'sms': lambda recs: recs.write({'message_type': 'email'})})
|
||||
message_type = fields.Selection(
|
||||
selection_add=[('sms', 'SMS')],
|
||||
ondelete={'sms': lambda recs: recs.write({'message_type': 'comment'})})
|
||||
has_sms_error = fields.Boolean(
|
||||
'Has SMS error', compute='_compute_has_sms_error', search='_search_has_sms_error')
|
||||
|
||||
|
|
@ -29,26 +24,9 @@ class MailMessage(models.Model):
|
|||
message.has_sms_error = message in sms_error_from_notification
|
||||
|
||||
def _search_has_sms_error(self, operator, operand):
|
||||
if operator == '=' and operand:
|
||||
return ['&', ('notification_ids.notification_status', '=', 'exception'), ('notification_ids.notification_type', '=', 'sms')]
|
||||
raise NotImplementedError()
|
||||
|
||||
def message_format(self, format_reply=True):
|
||||
""" Override in order to retrieves data about SMS (recipient name and
|
||||
SMS status)
|
||||
|
||||
TDE FIXME: clean the overall message_format thingy
|
||||
"""
|
||||
message_values = super(MailMessage, self).message_format(format_reply=format_reply)
|
||||
all_sms_notifications = self.env['mail.notification'].sudo().search([
|
||||
('mail_message_id', 'in', [r['id'] for r in message_values]),
|
||||
('notification_type', '=', 'sms')
|
||||
])
|
||||
msgid_to_notif = defaultdict(lambda: self.env['mail.notification'].sudo())
|
||||
for notif in all_sms_notifications:
|
||||
msgid_to_notif[notif.mail_message_id.id] += notif
|
||||
|
||||
for message in message_values:
|
||||
customer_sms_data = [(notif.id, notif.res_partner_id.display_name or notif.sms_number, notif.notification_status) for notif in msgid_to_notif.get(message['id'], [])]
|
||||
message['sms_ids'] = customer_sms_data
|
||||
return message_values
|
||||
if operator != 'in':
|
||||
return NotImplemented
|
||||
return [('notification_ids', 'any', [
|
||||
('notification_status', '=', 'exception'),
|
||||
('notification_type', '=', 'sms'),
|
||||
])]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import fields, models
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class MailNotification(models.Model):
|
||||
|
|
@ -10,12 +10,35 @@ class MailNotification(models.Model):
|
|||
notification_type = fields.Selection(selection_add=[
|
||||
('sms', 'SMS')
|
||||
], ondelete={'sms': 'cascade'})
|
||||
sms_id = fields.Many2one('sms.sms', string='SMS', index='btree_not_null', ondelete='set null')
|
||||
sms_id_int = fields.Integer('SMS ID', index='btree_not_null')
|
||||
# Used to give links on form view without foreign key. In most cases, you'd want to use sms_id_int or sms_tracker_ids.sms_uuid.
|
||||
sms_id = fields.Many2one('sms.sms', string='SMS', store=False, compute='_compute_sms_id')
|
||||
sms_tracker_ids = fields.One2many('sms.tracker', 'mail_notification_id', string="SMS Trackers")
|
||||
sms_number = fields.Char('SMS Number', groups='base.group_user')
|
||||
failure_type = fields.Selection(selection_add=[
|
||||
('sms_number_missing', 'Missing Number'),
|
||||
('sms_number_format', 'Wrong Number Format'),
|
||||
('sms_credit', 'Insufficient Credit'),
|
||||
('sms_country_not_supported', 'Country Not Supported'),
|
||||
('sms_registration_needed', 'Country-specific Registration Required'),
|
||||
('sms_server', 'Server Error'),
|
||||
('sms_acc', 'Unregistered Account')
|
||||
('sms_acc', 'Unregistered Account'),
|
||||
# delivery report errors
|
||||
('sms_expired', 'Expired'),
|
||||
('sms_invalid_destination', 'Invalid Destination'),
|
||||
('sms_not_allowed', 'Not Allowed'),
|
||||
('sms_not_delivered', 'Not Delivered'),
|
||||
('sms_rejected', 'Rejected'),
|
||||
])
|
||||
|
||||
@api.depends('sms_id_int', 'notification_type')
|
||||
def _compute_sms_id(self):
|
||||
self.sms_id = False
|
||||
sms_notifications = self.filtered(lambda n: n.notification_type == 'sms' and bool(n.sms_id_int))
|
||||
if not sms_notifications:
|
||||
return
|
||||
existing_sms_ids = self.env['sms.sms'].sudo().search([
|
||||
('id', 'in', sms_notifications.mapped('sms_id_int')), ('to_delete', '!=', True)
|
||||
]).ids
|
||||
for sms_notification in sms_notifications.filtered(lambda n: n.sms_id_int in set(existing_sms_ids)):
|
||||
sms_notification.sms_id = sms_notification.sms_id_int
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@
|
|||
|
||||
import logging
|
||||
|
||||
from odoo import api, models, fields
|
||||
from odoo.addons.phone_validation.tools import phone_validation
|
||||
from odoo import api, Command, models, fields
|
||||
from odoo.addons.sms.tools.sms_tools import sms_content_to_rendered_html
|
||||
from odoo.tools import html2plaintext
|
||||
|
||||
|
|
@ -34,16 +33,17 @@ class MailThread(models.AbstractModel):
|
|||
AND msg.message_type != 'user_notification'
|
||||
GROUP BY msg.res_id
|
||||
""", {'author_id': self.env.user.partner_id.id, 'model_name': self._name, 'res_ids': tuple(self.ids)})
|
||||
res.update(self._cr.fetchall())
|
||||
res.update(self.env.cr.fetchall())
|
||||
|
||||
for record in self:
|
||||
record.message_has_sms_error = bool(res.get(record._origin.id, 0))
|
||||
|
||||
@api.model
|
||||
def _search_message_has_sms_error(self, operator, operand):
|
||||
return ['&', ('message_ids.has_sms_error', operator, operand), ('message_ids.author_id', '=', self.env.user.partner_id.id)]
|
||||
if operator != 'in':
|
||||
return NotImplemented
|
||||
return ['&', ('message_ids.has_sms_error', '=', True), ('message_ids.author_id', '=', self.env.user.partner_id.id)]
|
||||
|
||||
@api.returns('mail.message', lambda value: value.id)
|
||||
def message_post(self, *args, body='', message_type='notification', **kwargs):
|
||||
# When posting an 'SMS' `message_type`, make sure that the body is used as-is in the sms,
|
||||
# and reformat the message body for the notification (mainly making URLs clickable).
|
||||
|
|
@ -136,30 +136,25 @@ class MailThread(models.AbstractModel):
|
|||
)
|
||||
|
||||
def _notify_thread(self, message, msg_vals=False, **kwargs):
|
||||
recipients_data = super(MailThread, self)._notify_thread(message, msg_vals=msg_vals, **kwargs)
|
||||
self._notify_thread_by_sms(message, recipients_data, msg_vals=msg_vals, **kwargs)
|
||||
# Main notification method. Override to add support of sending SMS notifications.
|
||||
scheduled_date = self._is_notification_scheduled(kwargs.get('scheduled_date'))
|
||||
recipients_data = super()._notify_thread(message, msg_vals=msg_vals, **kwargs)
|
||||
if not scheduled_date:
|
||||
self._notify_thread_by_sms(message, recipients_data, msg_vals=msg_vals, **kwargs)
|
||||
return recipients_data
|
||||
|
||||
def _notify_thread_by_sms(self, message, recipients_data, msg_vals=False,
|
||||
sms_content=None, sms_numbers=None, sms_pid_to_number=None,
|
||||
resend_existing=False, put_in_queue=False, **kwargs):
|
||||
put_in_queue=False, **kwargs):
|
||||
""" Notification method: by SMS.
|
||||
|
||||
:param message: ``mail.message`` record to notify;
|
||||
:param recipients_data: list of recipients information (based on res.partner
|
||||
records), formatted like
|
||||
[{'active': partner.active;
|
||||
'id': id of the res.partner being recipient to notify;
|
||||
'groups': res.group IDs if linked to a user;
|
||||
'notif': 'inbox', 'email', 'sms' (SMS App);
|
||||
'share': partner.partner_share;
|
||||
'type': 'customer', 'portal', 'user;'
|
||||
}, {...}].
|
||||
See ``MailThread._notify_get_recipients``;
|
||||
:param msg_vals: dictionary of values used to create the message. If given it
|
||||
may be used to access values related to ``message`` without accessing it
|
||||
directly. It lessens query count in some optimized use cases by avoiding
|
||||
access message content in db;
|
||||
:param record message: <mail.message> record being notified. May be
|
||||
void as 'msg_vals' superseeds it;
|
||||
:param list recipients_data: list of recipients data based on <res.partner>
|
||||
records formatted like a list of dicts containing information. See
|
||||
``MailThread._notify_get_recipients()``;
|
||||
:param dict msg_vals: values dict used to create the message, allows to
|
||||
skip message usage and spare some queries if given;
|
||||
|
||||
:param sms_content: plaintext version of body, mainly to avoid
|
||||
conversion glitches by splitting html and plain text content formatting
|
||||
|
|
@ -167,20 +162,19 @@ class MailThread(models.AbstractModel):
|
|||
If not given, `msg_vals`'s `body` is used and converted from html to plaintext;
|
||||
:param sms_numbers: additional numbers to notify in addition to partners
|
||||
and classic recipients;
|
||||
:param pid_to_number: force a number to notify for a given partner ID
|
||||
:param sms_pid_to_number: force a number to notify for a given partner ID
|
||||
instead of taking its mobile / phone number;
|
||||
:param resend_existing: check for existing notifications to update based on
|
||||
mailed recipient, otherwise create new notifications;
|
||||
:param put_in_queue: use cron to send queued SMS instead of sending them
|
||||
directly;
|
||||
"""
|
||||
msg_vals = msg_vals or {}
|
||||
sms_pid_to_number = sms_pid_to_number if sms_pid_to_number is not None else {}
|
||||
sms_numbers = sms_numbers if sms_numbers is not None else []
|
||||
sms_create_vals = []
|
||||
sms_all = self.env['sms.sms'].sudo()
|
||||
|
||||
# pre-compute SMS data
|
||||
body = sms_content or html2plaintext(msg_vals['body'] if msg_vals and 'body' in msg_vals else message.body)
|
||||
body = sms_content or html2plaintext(msg_vals['body'] if 'body' in msg_vals else message.body)
|
||||
sms_base_vals = {
|
||||
'body': body,
|
||||
'mail_message_id': message.id,
|
||||
|
|
@ -192,21 +186,18 @@ class MailThread(models.AbstractModel):
|
|||
partner_ids = [r['id'] for r in partners_data]
|
||||
if partner_ids:
|
||||
for partner in self.env['res.partner'].sudo().browse(partner_ids):
|
||||
number = sms_pid_to_number.get(partner.id) or partner.mobile or partner.phone
|
||||
sanitize_res = phone_validation.phone_sanitize_numbers_w_record([number], partner)[number]
|
||||
number = sanitize_res['sanitized'] or number
|
||||
number = sms_pid_to_number.get(partner.id) or partner.phone
|
||||
sms_create_vals.append(dict(
|
||||
sms_base_vals,
|
||||
partner_id=partner.id,
|
||||
number=number
|
||||
number=partner._phone_format(number=number) or number,
|
||||
))
|
||||
|
||||
# notify from additional numbers
|
||||
if sms_numbers:
|
||||
sanitized = phone_validation.phone_sanitize_numbers_w_record(sms_numbers, self)
|
||||
tocreate_numbers = [
|
||||
value['sanitized'] or original
|
||||
for original, value in sanitized.items()
|
||||
self._phone_format(number=sms_number) or sms_number
|
||||
for sms_number in sms_numbers
|
||||
]
|
||||
existing_partners_numbers = {vals_dict['number'] for vals_dict in sms_create_vals}
|
||||
sms_create_vals += [dict(
|
||||
|
|
@ -218,55 +209,34 @@ class MailThread(models.AbstractModel):
|
|||
) for n in tocreate_numbers if n not in existing_partners_numbers]
|
||||
|
||||
# create sms and notification
|
||||
existing_pids, existing_numbers = [], []
|
||||
if sms_create_vals:
|
||||
sms_all |= self.env['sms.sms'].sudo().create(sms_create_vals)
|
||||
|
||||
if resend_existing:
|
||||
existing = self.env['mail.notification'].sudo().search([
|
||||
'|', ('res_partner_id', 'in', partner_ids),
|
||||
'&', ('res_partner_id', '=', False), ('sms_number', 'in', sms_numbers),
|
||||
('notification_type', '=', 'sms'),
|
||||
('mail_message_id', '=', message.id)
|
||||
])
|
||||
for n in existing:
|
||||
if n.res_partner_id.id in partner_ids and n.mail_message_id == message:
|
||||
existing_pids.append(n.res_partner_id.id)
|
||||
if not n.res_partner_id and n.sms_number in sms_numbers and n.mail_message_id == message:
|
||||
existing_numbers.append(n.sms_number)
|
||||
|
||||
notif_create_values = [{
|
||||
'author_id': message.author_id.id,
|
||||
'mail_message_id': message.id,
|
||||
'res_partner_id': sms.partner_id.id,
|
||||
'sms_number': sms.number,
|
||||
'notification_type': 'sms',
|
||||
'sms_id': sms.id,
|
||||
'sms_id_int': sms.id,
|
||||
'sms_tracker_ids': [Command.create({'sms_uuid': sms.uuid})] if sms.state == 'outgoing' else False,
|
||||
'is_read': True, # discard Inbox notification
|
||||
'notification_status': 'ready' if sms.state == 'outgoing' else 'exception',
|
||||
'failure_type': '' if sms.state == 'outgoing' else sms.failure_type,
|
||||
} for sms in sms_all if (sms.partner_id and sms.partner_id.id not in existing_pids) or (not sms.partner_id and sms.number not in existing_numbers)]
|
||||
} for sms in sms_all]
|
||||
if notif_create_values:
|
||||
self.env['mail.notification'].sudo().create(notif_create_values)
|
||||
|
||||
if existing_pids or existing_numbers:
|
||||
for sms in sms_all:
|
||||
notif = next((n for n in existing if
|
||||
(n.res_partner_id.id in existing_pids and n.res_partner_id.id == sms.partner_id.id) or
|
||||
(not n.res_partner_id and n.sms_number in existing_numbers and n.sms_number == sms.number)), False)
|
||||
if notif:
|
||||
notif.write({
|
||||
'notification_type': 'sms',
|
||||
'notification_status': 'ready',
|
||||
'sms_id': sms.id,
|
||||
'sms_number': sms.number,
|
||||
})
|
||||
|
||||
if sms_all and not put_in_queue:
|
||||
sms_all.filtered(lambda sms: sms.state == 'outgoing').send(auto_commit=False, raise_exception=False)
|
||||
sms_all.filtered(lambda sms: sms.state == 'outgoing').send(raise_exception=False)
|
||||
|
||||
return True
|
||||
|
||||
def _get_notify_valid_parameters(self):
|
||||
return super()._get_notify_valid_parameters() | {
|
||||
'put_in_queue', 'sms_numbers', 'sms_pid_to_number', 'sms_content',
|
||||
}
|
||||
|
||||
@api.model
|
||||
def notify_cancel_by_type(self, notification_type):
|
||||
super().notify_cancel_by_type(notification_type)
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import models
|
||||
|
||||
|
||||
class PhoneMixin(models.AbstractModel):
|
||||
_inherit = 'mail.thread.phone'
|
||||
|
||||
def _sms_get_number_fields(self):
|
||||
""" Add fields coming from mail.thread.phone implementation. """
|
||||
phone_fields = self._phone_get_number_fields()
|
||||
sms_fields = super(PhoneMixin, self)._sms_get_number_fields()
|
||||
for fname in (f for f in sms_fields if f not in phone_fields):
|
||||
phone_fields.append(fname)
|
||||
return phone_fields
|
||||
|
|
@ -5,36 +5,8 @@ from odoo.addons.phone_validation.tools import phone_validation
|
|||
class BaseModel(models.AbstractModel):
|
||||
_inherit = 'base'
|
||||
|
||||
def _sms_get_partner_fields(self):
|
||||
""" This method returns the fields to use to find the contact to link
|
||||
whensending an SMS. Having partner is not necessary, having only phone
|
||||
number fields is possible. However it gives more flexibility to
|
||||
notifications management when having partners. """
|
||||
fields = []
|
||||
if hasattr(self, 'partner_id'):
|
||||
fields.append('partner_id')
|
||||
if hasattr(self, 'partner_ids'):
|
||||
fields.append('partner_ids')
|
||||
return fields
|
||||
|
||||
def _sms_get_default_partners(self):
|
||||
""" This method will likely need to be overridden by inherited models.
|
||||
:returns partners: recordset of res.partner
|
||||
"""
|
||||
partners = self.env['res.partner']
|
||||
for fname in self._sms_get_partner_fields():
|
||||
partners = partners.union(*self.mapped(fname)) # ensure ordering
|
||||
return partners
|
||||
|
||||
def _sms_get_number_fields(self):
|
||||
""" This method returns the fields to use to find the number to use to
|
||||
send an SMS on a record. """
|
||||
if 'mobile' in self:
|
||||
return ['mobile']
|
||||
return []
|
||||
|
||||
def _sms_get_recipients_info(self, force_field=False, partner_fallback=True):
|
||||
"""" Get SMS recipient information on current record set. This method
|
||||
""" Get SMS recipient information on current record set. This method
|
||||
checks for numbers and sanitation in order to centralize computation.
|
||||
|
||||
Example of use cases
|
||||
|
|
@ -45,32 +17,52 @@ class BaseModel(models.AbstractModel):
|
|||
customer, force its number to found field number or fallback on customer fields;
|
||||
|
||||
:param force_field: either give a specific field to find phone number, either
|
||||
generic heuristic is used to find one based on ``_sms_get_number_fields``;
|
||||
generic heuristic is used to find one based on :meth:`_phone_get_number_fields`;
|
||||
:param partner_fallback: if no value found in the record, check its customer
|
||||
values based on ``_sms_get_default_partners``;
|
||||
values based on :meth:`_mail_get_partners`;
|
||||
|
||||
:rtype: dict[int, dict[str, Any]]
|
||||
:return: a dictionnary with the following structure:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
{
|
||||
record.id: {
|
||||
# a res.partner recordset that is the customer (void or
|
||||
# singleton) linked to the recipient.
|
||||
# See _mail_get_partners;
|
||||
'partner': ...,
|
||||
|
||||
# sanitized number to use (coming from record's field
|
||||
# or partner's phone fields). Set to False if number
|
||||
# impossible to parse and format;
|
||||
'sanitized': ...,
|
||||
|
||||
# original number before sanitation;
|
||||
'number': ...,
|
||||
|
||||
# whether the number comes from the customer phone
|
||||
# fields. If False it means number comes from the
|
||||
# record itself, even if linked to a customer;
|
||||
'partner_store': ...,
|
||||
|
||||
# field in which the number has been found (generally
|
||||
# mobile or phone, see _phone_get_number_fields);
|
||||
'field_store': ...,
|
||||
}
|
||||
for record in self
|
||||
}
|
||||
|
||||
:return dict: record.id: {
|
||||
'partner': a res.partner recordset that is the customer (void or singleton)
|
||||
linked to the recipient. See ``_sms_get_default_partners``;
|
||||
'sanitized': sanitized number to use (coming from record's field or partner's
|
||||
phone fields). Set to False is number impossible to parse and format;
|
||||
'number': original number before sanitation;
|
||||
'partner_store': whether the number comes from the customer phone fields. If
|
||||
False it means number comes from the record itself, even if linked to a
|
||||
customer;
|
||||
'field_store': field in which the number has been found (generally mobile or
|
||||
phone, see ``_sms_get_number_fields``);
|
||||
} for each record in self
|
||||
"""
|
||||
result = dict.fromkeys(self.ids, False)
|
||||
tocheck_fields = [force_field] if force_field else self._sms_get_number_fields()
|
||||
tocheck_fields = [force_field] if force_field else self._phone_get_number_fields()
|
||||
for record in self:
|
||||
all_numbers = [record[fname] for fname in tocheck_fields if fname in record]
|
||||
all_partners = record._sms_get_default_partners()
|
||||
all_partners = record._mail_get_partners()[record.id]
|
||||
|
||||
valid_number = False
|
||||
valid_number, fname = False, False
|
||||
for fname in [f for f in tocheck_fields if f in record]:
|
||||
valid_number = phone_validation.phone_sanitize_numbers_w_record([record[fname]], record)[record[fname]]['sanitized']
|
||||
valid_number = record._phone_format(fname=fname)
|
||||
if valid_number:
|
||||
break
|
||||
|
||||
|
|
@ -85,13 +77,13 @@ class BaseModel(models.AbstractModel):
|
|||
elif all_partners and partner_fallback:
|
||||
partner = self.env['res.partner']
|
||||
for partner in all_partners:
|
||||
for fname in self.env['res.partner']._sms_get_number_fields():
|
||||
valid_number = phone_validation.phone_sanitize_numbers_w_record([partner[fname]], record)[partner[fname]]['sanitized']
|
||||
for fname in self.env['res.partner']._phone_get_number_fields():
|
||||
valid_number = partner._phone_format(fname=fname)
|
||||
if valid_number:
|
||||
break
|
||||
|
||||
if not valid_number:
|
||||
fname = 'mobile' if partner.mobile else ('phone' if partner.phone else 'mobile')
|
||||
fname = 'phone'
|
||||
|
||||
result[record.id] = {
|
||||
'partner': partner,
|
||||
|
|
|
|||
11
odoo-bringout-oca-ocb-sms/sms/models/res_company.py
Normal file
11
odoo-bringout-oca-ocb-sms/sms/models/res_company.py
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
from odoo import models
|
||||
|
||||
from odoo.addons.sms.tools.sms_api import SmsApi
|
||||
|
||||
|
||||
class ResCompany(models.Model):
|
||||
_inherit = 'res.company'
|
||||
|
||||
def _get_sms_api_class(self):
|
||||
self.ensure_one()
|
||||
return SmsApi
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import models
|
||||
|
||||
|
||||
class ResPartner(models.Model):
|
||||
_name = 'res.partner'
|
||||
_inherit = ['mail.thread.phone', 'res.partner']
|
||||
|
||||
def _sms_get_default_partners(self):
|
||||
""" Override of mail.thread method.
|
||||
SMS recipients on partners are the partners themselves.
|
||||
"""
|
||||
return self
|
||||
|
||||
def _phone_get_number_fields(self):
|
||||
""" This method returns the fields to use to find the number to use to
|
||||
send an SMS on a record. """
|
||||
return ['mobile', 'phone']
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import _, api, exceptions, models
|
||||
from odoo.addons.iap.tools import iap_tools
|
||||
|
||||
DEFAULT_ENDPOINT = 'https://iap-sms.odoo.com'
|
||||
|
||||
|
||||
class SmsApi(models.AbstractModel):
|
||||
_name = 'sms.api'
|
||||
_description = 'SMS API'
|
||||
|
||||
@api.model
|
||||
def _contact_iap(self, local_endpoint, params):
|
||||
if not self.env.registry.ready: # Don't reach IAP servers during module installation
|
||||
raise exceptions.AccessError("Unavailable during module installation.")
|
||||
|
||||
account = self.env['iap.account'].get('sms')
|
||||
params['account_token'] = account.account_token
|
||||
endpoint = self.env['ir.config_parameter'].sudo().get_param('sms.endpoint', DEFAULT_ENDPOINT)
|
||||
# TODO PRO, the default timeout is 15, do we have to increase it ?
|
||||
return iap_tools.iap_jsonrpc(endpoint + local_endpoint, params=params)
|
||||
|
||||
@api.model
|
||||
def _send_sms(self, numbers, message):
|
||||
""" Send a single message to several numbers
|
||||
|
||||
:param numbers: list of E164 formatted phone numbers
|
||||
:param message: content to send
|
||||
|
||||
:raises ? TDE FIXME
|
||||
"""
|
||||
params = {
|
||||
'numbers': numbers,
|
||||
'message': message,
|
||||
}
|
||||
return self._contact_iap('/iap/message_send', params)
|
||||
|
||||
@api.model
|
||||
def _send_sms_batch(self, messages):
|
||||
""" Send SMS using IAP in batch mode
|
||||
|
||||
:param messages: list of SMS to send, structured as dict [{
|
||||
'res_id': integer: ID of sms.sms,
|
||||
'number': string: E164 formatted phone number,
|
||||
'content': string: content to send
|
||||
}]
|
||||
|
||||
:return: return of /iap/sms/1/send controller which is a list of dict [{
|
||||
'res_id': integer: ID of sms.sms,
|
||||
'state': string: 'insufficient_credit' or 'wrong_number_format' or 'success',
|
||||
'credit': integer: number of credits spent to send this SMS,
|
||||
}]
|
||||
|
||||
:raises: normally none
|
||||
"""
|
||||
params = {
|
||||
'messages': messages
|
||||
}
|
||||
return self._contact_iap('/iap/sms/2/send', params)
|
||||
|
||||
@api.model
|
||||
def _get_sms_api_error_messages(self):
|
||||
""" Returns a dict containing the error message to display for every known error 'state'
|
||||
resulting from the '_send_sms_batch' method.
|
||||
We prefer a dict instead of a message-per-error-state based method so we only call
|
||||
the 'get_credits_url' once, to avoid extra RPC calls. """
|
||||
|
||||
buy_credits_url = self.sudo().env['iap.account'].get_credits_url(service_name='sms')
|
||||
buy_credits = '<a href="%s" target="_blank">%s</a>' % (
|
||||
buy_credits_url,
|
||||
_('Buy credits.')
|
||||
)
|
||||
return {
|
||||
'unregistered': _("You don't have an eligible IAP account."),
|
||||
'insufficient_credit': ' '.join([_('You don\'t have enough credits on your IAP account.'), buy_credits]),
|
||||
'wrong_number_format': _("The number you're trying to reach is not correctly formatted."),
|
||||
}
|
||||
|
|
@ -1,10 +1,12 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import logging
|
||||
import threading
|
||||
|
||||
from uuid import uuid4
|
||||
|
||||
from odoo import api, fields, models, tools, _
|
||||
from odoo.addons.sms.tools.sms_api import SmsApi
|
||||
from odoo.tools.urls import urljoin as url_join
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -15,93 +17,111 @@ class SmsSms(models.Model):
|
|||
_rec_name = 'number'
|
||||
_order = 'id DESC'
|
||||
|
||||
IAP_TO_SMS_STATE = {
|
||||
'success': 'sent',
|
||||
IAP_TO_SMS_STATE_SUCCESS = {
|
||||
'processing': 'process',
|
||||
'success': 'pending',
|
||||
# These below are not returned in responses from IAP API in _send but are received via webhook events.
|
||||
'sent': 'pending',
|
||||
'delivered': 'sent',
|
||||
}
|
||||
IAP_TO_SMS_FAILURE_TYPE = { # TODO RIGR remove me in master
|
||||
'insufficient_credit': 'sms_credit',
|
||||
'wrong_number_format': 'sms_number_format',
|
||||
'country_not_supported': 'sms_country_not_supported',
|
||||
'server_error': 'sms_server',
|
||||
'unregistered': 'sms_acc'
|
||||
}
|
||||
|
||||
BOUNCE_DELIVERY_ERRORS = {'sms_invalid_destination', 'sms_not_allowed', 'sms_rejected'}
|
||||
DELIVERY_ERRORS = {'sms_expired', 'sms_not_delivered', *BOUNCE_DELIVERY_ERRORS}
|
||||
|
||||
uuid = fields.Char('UUID', copy=False, readonly=True, default=lambda self: uuid4().hex,
|
||||
help='Alternate way to identify a SMS record, used for delivery reports')
|
||||
number = fields.Char('Number')
|
||||
body = fields.Text()
|
||||
partner_id = fields.Many2one('res.partner', 'Customer')
|
||||
mail_message_id = fields.Many2one('mail.message', index=True)
|
||||
state = fields.Selection([
|
||||
('outgoing', 'In Queue'),
|
||||
('sent', 'Sent'),
|
||||
('process', 'Processing'),
|
||||
('pending', 'Sent'),
|
||||
('sent', 'Delivered'), # As for notifications and traces
|
||||
('error', 'Error'),
|
||||
('canceled', 'Canceled')
|
||||
('canceled', 'Cancelled')
|
||||
], 'SMS Status', readonly=True, copy=False, default='outgoing', required=True)
|
||||
failure_type = fields.Selection([
|
||||
("unknown", "Unknown error"),
|
||||
('sms_number_missing', 'Missing Number'),
|
||||
('sms_number_format', 'Wrong Number Format'),
|
||||
('sms_country_not_supported', 'Country Not Supported'),
|
||||
('sms_registration_needed', 'Country-specific Registration Required'),
|
||||
('sms_credit', 'Insufficient Credit'),
|
||||
('sms_server', 'Server Error'),
|
||||
('sms_acc', 'Unregistered Account'),
|
||||
# mass mode specific codes
|
||||
# mass mode specific codes, generated internally, not returned by IAP.
|
||||
('sms_blacklist', 'Blacklisted'),
|
||||
('sms_duplicate', 'Duplicate'),
|
||||
('sms_optout', 'Opted Out'),
|
||||
], copy=False)
|
||||
sms_tracker_id = fields.Many2one('sms.tracker', string='SMS trackers', compute='_compute_sms_tracker_id')
|
||||
to_delete = fields.Boolean(
|
||||
'Marked for deletion', default=False,
|
||||
help='Will automatically be deleted, while notifications will not be deleted in any case.'
|
||||
)
|
||||
|
||||
_uuid_unique = models.Constraint(
|
||||
'unique(uuid)',
|
||||
'UUID must be unique',
|
||||
)
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
self.env.ref('sms.ir_cron_sms_scheduler_action')._trigger()
|
||||
return super().create(vals_list)
|
||||
|
||||
@api.depends('uuid')
|
||||
def _compute_sms_tracker_id(self):
|
||||
self.sms_tracker_id = False
|
||||
existing_trackers = self.env['sms.tracker'].search([('sms_uuid', 'in', self.filtered('uuid').mapped('uuid'))])
|
||||
tracker_ids_by_sms_uuid = {tracker.sms_uuid: tracker.id for tracker in existing_trackers}
|
||||
for sms in self.filtered(lambda s: s.uuid in tracker_ids_by_sms_uuid):
|
||||
sms.sms_tracker_id = tracker_ids_by_sms_uuid[sms.uuid]
|
||||
|
||||
def action_set_canceled(self):
|
||||
self.state = 'canceled'
|
||||
notifications = self.env['mail.notification'].sudo().search([
|
||||
('sms_id', 'in', self.ids),
|
||||
# sent is sent -> cannot reset
|
||||
('notification_status', 'not in', ['canceled', 'sent']),
|
||||
])
|
||||
if notifications:
|
||||
notifications.write({'notification_status': 'canceled'})
|
||||
if not self._context.get('sms_skip_msg_notification', False):
|
||||
notifications.mail_message_id._notify_message_notification_update()
|
||||
self._update_sms_state_and_trackers('canceled')
|
||||
|
||||
def action_set_error(self, failure_type):
|
||||
self.state = 'error'
|
||||
self.failure_type = failure_type
|
||||
notifications = self.env['mail.notification'].sudo().search([
|
||||
('sms_id', 'in', self.ids),
|
||||
# sent can be set to error due to IAP feedback
|
||||
('notification_status', '!=', 'exception'),
|
||||
])
|
||||
if notifications:
|
||||
notifications.write({'notification_status': 'exception', 'failure_type': failure_type})
|
||||
if not self._context.get('sms_skip_msg_notification', False):
|
||||
notifications.mail_message_id._notify_message_notification_update()
|
||||
self._update_sms_state_and_trackers('error', failure_type=failure_type)
|
||||
|
||||
def action_set_outgoing(self):
|
||||
self.write({
|
||||
'state': 'outgoing',
|
||||
'failure_type': False
|
||||
})
|
||||
notifications = self.env['mail.notification'].sudo().search([
|
||||
('sms_id', 'in', self.ids),
|
||||
# sent is sent -> cannot reset
|
||||
('notification_status', 'not in', ['ready', 'sent']),
|
||||
])
|
||||
if notifications:
|
||||
notifications.write({'notification_status': 'ready', 'failure_type': False})
|
||||
if not self._context.get('sms_skip_msg_notification', False):
|
||||
notifications.mail_message_id._notify_message_notification_update()
|
||||
self._update_sms_state_and_trackers('outgoing', failure_type=False)
|
||||
|
||||
def send(self, unlink_failed=False, unlink_sent=True, auto_commit=False, raise_exception=False):
|
||||
def send(self, unlink_failed=False, unlink_sent=True, raise_exception=False):
|
||||
""" Main API method to send SMS.
|
||||
|
||||
This contacts an external server. If the transaction fails, it may be
|
||||
retried which can result in sending multiple SMS messages!
|
||||
|
||||
:param unlink_failed: unlink failed SMS after IAP feedback;
|
||||
:param unlink_sent: unlink sent SMS after IAP feedback;
|
||||
:param auto_commit: commit after each batch of SMS;
|
||||
:param raise_exception: raise if there is an issue contacting IAP;
|
||||
"""
|
||||
self = self.filtered(lambda sms: sms.state == 'outgoing')
|
||||
for batch_ids in self._split_batch():
|
||||
self.browse(batch_ids)._send(unlink_failed=unlink_failed, unlink_sent=unlink_sent, raise_exception=raise_exception)
|
||||
# auto-commit if asked except in testing mode
|
||||
if auto_commit is True and not getattr(threading.current_thread(), 'testing', False):
|
||||
self._cr.commit()
|
||||
domain = [('state', '=', 'outgoing'), ('to_delete', '!=', True)]
|
||||
to_send = self.try_lock_for_update().filtered_domain(domain)
|
||||
|
||||
for sms_api, sms in to_send._split_by_api():
|
||||
for batch_ids in sms._split_batch():
|
||||
self.browse(batch_ids).with_context(sms_api=sms_api)._send(
|
||||
unlink_failed=unlink_failed,
|
||||
unlink_sent=unlink_sent,
|
||||
raise_exception=raise_exception,
|
||||
)
|
||||
|
||||
def _split_by_api(self):
|
||||
yield SmsApi(self.env), self
|
||||
|
||||
def resend_failed(self):
|
||||
sms_to_send = self.filtered(lambda sms: sms.state == 'error')
|
||||
sms_to_send = self.filtered(lambda sms: sms.state == 'error' and not sms.to_delete)
|
||||
sms_to_send.state = 'outgoing'
|
||||
notification_title = _('Warning')
|
||||
notification_type = 'danger'
|
||||
|
|
@ -112,7 +132,7 @@ class SmsSms(models.Model):
|
|||
if success_sms > 0:
|
||||
notification_title = _('Success')
|
||||
notification_type = 'success'
|
||||
notification_message = _('%s out of the %s selected SMS Text Messages have successfully been resent.', success_sms, len(self))
|
||||
notification_message = _('%(count)s out of the %(total)s selected SMS Text Messages have successfully been resent.', count=success_sms, total=len(self))
|
||||
else:
|
||||
notification_message = _('The SMS Text Messages could not be resent.')
|
||||
else:
|
||||
|
|
@ -128,90 +148,93 @@ class SmsSms(models.Model):
|
|||
}
|
||||
|
||||
@api.model
|
||||
def _process_queue(self, ids=None):
|
||||
""" Send immediately queued messages, committing after each message is sent.
|
||||
This is not transactional and should not be called during another transaction!
|
||||
def _process_queue(self):
|
||||
""" CRON job to send queued SMS messages. """
|
||||
domain = [('state', '=', 'outgoing'), ('to_delete', '!=', True)]
|
||||
|
||||
:param list ids: optional list of emails ids to send. If passed no search
|
||||
is performed, and these ids are used instead.
|
||||
"""
|
||||
domain = [('state', '=', 'outgoing')]
|
||||
batch_size = self._get_send_batch_size()
|
||||
records = self.search(domain, limit=batch_size, order='id').try_lock_for_update()
|
||||
if not records:
|
||||
return
|
||||
|
||||
filtered_ids = self.search(domain, limit=10000).ids # TDE note: arbitrary limit we might have to update
|
||||
if ids:
|
||||
ids = list(set(filtered_ids) & set(ids))
|
||||
else:
|
||||
ids = filtered_ids
|
||||
ids.sort()
|
||||
records._send(unlink_failed=False, unlink_sent=True, raise_exception=False)
|
||||
self.env['ir.cron']._commit_progress(len(records), remaining=self.search_count(domain) if len(records) == batch_size else 0)
|
||||
|
||||
res = None
|
||||
try:
|
||||
# auto-commit except in testing mode
|
||||
auto_commit = not getattr(threading.current_thread(), 'testing', False)
|
||||
res = self.browse(ids).send(unlink_failed=False, unlink_sent=True, auto_commit=auto_commit, raise_exception=False)
|
||||
except Exception:
|
||||
_logger.exception("Failed processing SMS queue")
|
||||
return res
|
||||
def _get_send_batch_size(self):
|
||||
return int(self.env['ir.config_parameter'].sudo().get_param('sms.session.batch.size', 500))
|
||||
|
||||
def _get_sms_company(self):
|
||||
return self.mail_message_id.record_company_id or self.env.company
|
||||
|
||||
def _split_batch(self):
|
||||
batch_size = int(self.env['ir.config_parameter'].sudo().get_param('sms.session.batch.size', 500))
|
||||
for sms_batch in tools.split_every(batch_size, self.ids):
|
||||
yield sms_batch
|
||||
batch_size = self._get_send_batch_size()
|
||||
yield from tools.split_every(batch_size, self.ids)
|
||||
|
||||
def _send(self, unlink_failed=False, unlink_sent=True, raise_exception=False):
|
||||
""" This method tries to send SMS after checking the number (presence and
|
||||
formatting). """
|
||||
iap_data = [{
|
||||
'res_id': record.id,
|
||||
'number': record.number,
|
||||
'content': record.body,
|
||||
} for record in self]
|
||||
"""Send SMS after checking the number (presence and formatting)."""
|
||||
sms_api = self.env.context.get('sms_api')
|
||||
if not sms_api:
|
||||
company = self._get_sms_company()
|
||||
company.ensure_one() # This should always be the case since the grouping is done in `send`
|
||||
sms_api = company._get_sms_api_class()(self.env)
|
||||
|
||||
return self._send_with_api(
|
||||
sms_api,
|
||||
unlink_failed=unlink_failed,
|
||||
unlink_sent=unlink_sent,
|
||||
raise_exception=raise_exception,
|
||||
)
|
||||
|
||||
def _send_with_api(self, sms_api, unlink_failed=False, unlink_sent=True, raise_exception=False):
|
||||
"""Send SMS after checking the number (presence and formatting)."""
|
||||
messages = [{
|
||||
'content': body,
|
||||
'numbers': [{'number': sms.number, 'uuid': sms.uuid} for sms in body_sms_records],
|
||||
} for body, body_sms_records in self.grouped('body').items()]
|
||||
|
||||
delivery_reports_url = url_join(self[0].get_base_url(), '/sms/status')
|
||||
try:
|
||||
iap_results = self.env['sms.api']._send_sms_batch(iap_data)
|
||||
results = sms_api._send_sms_batch(messages, delivery_reports_url=delivery_reports_url)
|
||||
except Exception as e:
|
||||
_logger.info('Sent batch %s SMS: %s: failed with exception %s', len(self.ids), self.ids, e)
|
||||
if raise_exception:
|
||||
raise
|
||||
self._postprocess_iap_sent_sms(
|
||||
[{'res_id': sms.id, 'state': 'server_error'} for sms in self],
|
||||
unlink_failed=unlink_failed, unlink_sent=unlink_sent)
|
||||
results = [{'uuid': sms.uuid, 'state': 'server_error'} for sms in self]
|
||||
else:
|
||||
_logger.info('Send batch %s SMS: %s: gave %s', len(self.ids), self.ids, iap_results)
|
||||
self._postprocess_iap_sent_sms(iap_results, unlink_failed=unlink_failed, unlink_sent=unlink_sent)
|
||||
_logger.info('Send batch %s SMS: %s: gave %s', len(self.ids), self.ids, results)
|
||||
|
||||
def _postprocess_iap_sent_sms(self, iap_results, failure_reason=None, unlink_failed=False, unlink_sent=True):
|
||||
todelete_sms_ids = []
|
||||
if unlink_failed:
|
||||
todelete_sms_ids += [item['res_id'] for item in iap_results if item['state'] != 'success']
|
||||
if unlink_sent:
|
||||
todelete_sms_ids += [item['res_id'] for item in iap_results if item['state'] == 'success']
|
||||
results_uuids = [result['uuid'] for result in results]
|
||||
all_sms_sudo = self.env['sms.sms'].sudo().search([('uuid', 'in', results_uuids)]).with_context(sms_skip_msg_notification=True)
|
||||
|
||||
for state in self.IAP_TO_SMS_STATE.keys():
|
||||
sms_ids = [item['res_id'] for item in iap_results if item['state'] == state]
|
||||
if sms_ids:
|
||||
if state != 'success' and not unlink_failed:
|
||||
self.env['sms.sms'].sudo().browse(sms_ids).write({
|
||||
'state': 'error',
|
||||
'failure_type': self.IAP_TO_SMS_STATE[state],
|
||||
})
|
||||
if state == 'success' and not unlink_sent:
|
||||
self.env['sms.sms'].sudo().browse(sms_ids).write({
|
||||
'state': 'sent',
|
||||
'failure_type': False,
|
||||
})
|
||||
notifications = self.env['mail.notification'].sudo().search([
|
||||
('notification_type', '=', 'sms'),
|
||||
('sms_id', 'in', sms_ids),
|
||||
('notification_status', 'not in', ('sent', 'canceled')),
|
||||
])
|
||||
if notifications:
|
||||
notifications.write({
|
||||
'notification_status': 'sent' if state == 'success' else 'exception',
|
||||
'failure_type': self.IAP_TO_SMS_STATE[state] if state != 'success' else False,
|
||||
'failure_reason': failure_reason if failure_reason else False,
|
||||
})
|
||||
self.mail_message_id._notify_message_notification_update()
|
||||
for (iap_state, failure_reason), results_group in tools.groupby(results, key=lambda result: (result['state'], result.get('failure_reason'))):
|
||||
sms_sudo = all_sms_sudo.filtered(lambda s: s.uuid in {result['uuid'] for result in results_group})
|
||||
if success_state := self.IAP_TO_SMS_STATE_SUCCESS.get(iap_state):
|
||||
sms_sudo.sms_tracker_id._action_update_from_sms_state(success_state)
|
||||
to_delete = {'to_delete': True} if unlink_sent else {}
|
||||
sms_sudo.write({'state': success_state, 'failure_type': False, **to_delete})
|
||||
else:
|
||||
failure_type = sms_api.PROVIDER_TO_SMS_FAILURE_TYPE.get(iap_state, 'unknown')
|
||||
if failure_type != 'unknown':
|
||||
sms_sudo.sms_tracker_id._action_update_from_sms_state('error', failure_type=failure_type, failure_reason=failure_reason)
|
||||
else:
|
||||
sms_sudo.sms_tracker_id.with_context(sms_known_failure_reason=failure_reason)._action_update_from_provider_error(iap_state)
|
||||
to_delete = {'to_delete': True} if unlink_failed else {}
|
||||
sms_sudo.write({'state': 'error', 'failure_type': failure_type, **to_delete})
|
||||
|
||||
if todelete_sms_ids:
|
||||
self.browse(todelete_sms_ids).sudo().unlink()
|
||||
all_sms_sudo._handle_call_result_hook(results)
|
||||
all_sms_sudo.mail_message_id._notify_message_notification_update()
|
||||
|
||||
def _update_sms_state_and_trackers(self, new_state, failure_type=None):
|
||||
"""Update sms state update and related tracking records (notifications, traces)."""
|
||||
self.write({'state': new_state, 'failure_type': failure_type})
|
||||
# Use sudo on mail.notification to allow writing other users' notifications; rights are already checked by sms write
|
||||
self.sms_tracker_id.sudo()._action_update_from_sms_state(new_state, failure_type=failure_type)
|
||||
|
||||
def _handle_call_result_hook(self, results):
|
||||
"""Further process SMS sending API results."""
|
||||
pass
|
||||
|
||||
@api.autovacuum
|
||||
def _gc_device(self):
|
||||
self.env.cr.execute("DELETE FROM sms_sms WHERE to_delete = TRUE")
|
||||
_logger.info("GC'd %d sms marked for deletion", self.env.cr.rowcount)
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@
|
|||
from odoo import api, fields, models, _
|
||||
|
||||
|
||||
class SMSTemplate(models.Model):
|
||||
class SmsTemplate(models.Model):
|
||||
"Templates for sending SMS"
|
||||
_name = "sms.template"
|
||||
_name = 'sms.template'
|
||||
_inherit = ['mail.render.mixin', 'template.reset.mixin']
|
||||
_description = 'SMS Templates'
|
||||
|
||||
|
|
@ -14,8 +14,8 @@ class SMSTemplate(models.Model):
|
|||
|
||||
@api.model
|
||||
def default_get(self, fields):
|
||||
res = super(SMSTemplate, self).default_get(fields)
|
||||
if not fields or 'model_id' in fields and not res.get('model_id') and res.get('model'):
|
||||
res = super().default_get(fields)
|
||||
if 'model_id' in fields and not res.get('model_id') and res.get('model'):
|
||||
res['model_id'] = self.env['ir.model']._get(res['model']).id
|
||||
return res
|
||||
|
||||
|
|
@ -41,15 +41,13 @@ class SMSTemplate(models.Model):
|
|||
# CRUD
|
||||
# ------------------------------------------------------------
|
||||
|
||||
@api.returns('self', lambda value: value.id)
|
||||
def copy(self, default=None):
|
||||
default = dict(default or {},
|
||||
name=_("%s (copy)", self.name))
|
||||
return super(SMSTemplate, self).copy(default=default)
|
||||
def copy_data(self, default=None):
|
||||
vals_list = super().copy_data(default=default)
|
||||
return [dict(vals, name=self.env._("%s (copy)", template.name)) for template, vals in zip(self, vals_list)]
|
||||
|
||||
def unlink(self):
|
||||
self.sudo().mapped('sidebar_action_id').unlink()
|
||||
return super(SMSTemplate, self).unlink()
|
||||
return super().unlink()
|
||||
|
||||
def action_create_sidebar_action(self):
|
||||
ActWindow = self.env['ir.actions.act_window']
|
||||
|
|
|
|||
83
odoo-bringout-oca-ocb-sms/sms/models/sms_tracker.py
Normal file
83
odoo-bringout-oca-ocb-sms/sms/models/sms_tracker.py
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class SmsTracker(models.Model):
|
||||
"""Relationship between a sent SMS and tracking records such as notifications and traces.
|
||||
|
||||
This model acts as an extension of a `mail.notification` or a `mailing.trace` and allows to
|
||||
update those based on the SMS provider responses both at sending and when later receiving
|
||||
sent/delivery reports (see `SmsController`).
|
||||
SMS trackers are supposed to be created manually when necessary, and tied to their related
|
||||
SMS through the SMS UUID field. (They are not tied to the SMS records directly as those can
|
||||
be deleted when sent).
|
||||
|
||||
Note: Only admins/system user should need to access (a fortiori modify) these technical
|
||||
records so no "sudo" is used nor should be required here.
|
||||
"""
|
||||
_name = 'sms.tracker'
|
||||
_description = "Link SMS to mailing/sms tracking models"
|
||||
|
||||
SMS_STATE_TO_NOTIFICATION_STATUS = {
|
||||
'canceled': 'canceled',
|
||||
'process': 'process',
|
||||
'error': 'exception',
|
||||
'outgoing': 'ready',
|
||||
'sent': 'sent',
|
||||
'pending': 'pending',
|
||||
}
|
||||
|
||||
sms_uuid = fields.Char('SMS uuid', required=True)
|
||||
mail_notification_id = fields.Many2one('mail.notification', ondelete='cascade', index='btree_not_null')
|
||||
|
||||
_sms_uuid_unique = models.Constraint(
|
||||
'unique(sms_uuid)',
|
||||
'A record for this UUID already exists',
|
||||
)
|
||||
|
||||
def _action_update_from_provider_error(self, provider_error):
|
||||
"""
|
||||
:param str provider_error: value returned by SMS service provider (IAP) or any string.
|
||||
If provided, notification values will be derived from it.
|
||||
(see ``_get_tracker_values_from_provider_error``)
|
||||
"""
|
||||
failure_reason = self.env.context.get("sms_known_failure_reason") # TODO RIGR in master: pass as param instead of context
|
||||
failure_type = f'sms_{provider_error}'
|
||||
error_status = None
|
||||
if failure_type not in self.env['sms.sms'].DELIVERY_ERRORS:
|
||||
failure_type = 'unknown'
|
||||
failure_reason = failure_reason or provider_error
|
||||
elif failure_type in self.env['sms.sms'].BOUNCE_DELIVERY_ERRORS:
|
||||
error_status = "bounce"
|
||||
|
||||
self._update_sms_notifications(error_status or 'exception', failure_type=failure_type, failure_reason=failure_reason)
|
||||
return error_status, failure_type, failure_reason
|
||||
|
||||
def _action_update_from_sms_state(self, sms_state, failure_type=False, failure_reason=False):
|
||||
notification_status = self.SMS_STATE_TO_NOTIFICATION_STATUS[sms_state]
|
||||
self._update_sms_notifications(notification_status, failure_type=failure_type, failure_reason=failure_reason)
|
||||
|
||||
def _update_sms_notifications(self, notification_status, failure_type=False, failure_reason=False):
|
||||
# canceled is a state which means that the SMS sending order should not be sent to the SMS service.
|
||||
# `process`, `pending` are sent to IAP which is not revertible (as `sent` which means "delivered").
|
||||
notifications_statuses_to_ignore = {
|
||||
'canceled': ['canceled', 'process', 'pending', 'sent'],
|
||||
'ready': ['ready', 'process', 'pending', 'sent'],
|
||||
'process': ['process', 'pending', 'sent'],
|
||||
'pending': ['pending', 'sent'],
|
||||
'bounce': ['bounce', 'sent'],
|
||||
'sent': ['sent'],
|
||||
'exception': ['exception'],
|
||||
}[notification_status]
|
||||
notifications = self.mail_notification_id.filtered(
|
||||
lambda n: n.notification_status not in notifications_statuses_to_ignore
|
||||
)
|
||||
if notifications:
|
||||
notifications.write({
|
||||
'notification_status': notification_status,
|
||||
'failure_type': failure_type,
|
||||
'failure_reason': failure_reason,
|
||||
})
|
||||
if not self.env.context.get('sms_skip_msg_notification'):
|
||||
notifications.mail_message_id._notify_message_notification_update()
|
||||
|
|
@ -4,8 +4,11 @@ access_sms_sms_system,access.sms.sms.system,model_sms_sms,base.group_system,1,1,
|
|||
access_sms_template_all,access.sms.template.all,model_sms_template,,0,0,0,0
|
||||
access_sms_template_user,access.sms.template.user,model_sms_template,base.group_user,1,0,0,0
|
||||
access_sms_template_system,access.sms.template.system,model_sms_template,base.group_system,1,1,1,1
|
||||
access_sms_tracker_all,access.sms.tracker.all,model_sms_tracker,,0,0,0,0
|
||||
access_sms_tracker_system,access.sms.tracker.system,model_sms_tracker,base.group_system,1,1,1,1
|
||||
access_sms_composer,access.sms.composer,model_sms_composer,base.group_user,1,1,1,0
|
||||
access_sms_resend_recipient,access.sms.resend.recipient,model_sms_resend_recipient,base.group_user,1,1,1,0
|
||||
access_sms_resend,access.sms.resend,model_sms_resend,base.group_user,1,1,1,0
|
||||
access_sms_template_preview,access.sms.template.preview,model_sms_template_preview,base.group_user,1,1,1,0
|
||||
access_sms_template_reset,access.sms.template.reset,model_sms_template_reset,mail.group_mail_template_editor,1,1,1,1
|
||||
access_sms_account_registration_phone_number_wizard_system,access.sms.account.phone.system,model_sms_account_phone,base.group_system,1,1,1,1
|
||||
access_sms_account_verification_code_wizard_system,access.sms.account.code.system,model_sms_account_code,base.group_system,1,1,1,1
|
||||
access_sms_account_sender_name_wizard_system,access.sms.account.sender.system,model_sms_account_sender,base.group_system,1,1,1,1
|
||||
|
|
|
|||
|
Binary file not shown.
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 1.6 KiB |
|
|
@ -1,41 +1 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 70 70">
|
||||
<defs>
|
||||
<mask id="mask" x="0" y="0" width="70" height="70" maskUnits="userSpaceOnUse">
|
||||
<g id="b">
|
||||
<path id="a" d="M4,0H65c4,0,5,1,5,5V65c0,4-1,5-5,5H4c-3,0-4-1-4-5V5C0,1,1,0,4,0Z" fill="#fff" fill-rule="evenodd"/>
|
||||
</g>
|
||||
</mask>
|
||||
<linearGradient id="linear-gradient" x1="-1172.36" y1="477.94" x2="-1173.36" y2="476.94" gradientTransform="matrix(70, 0, 0, -70, 82134.99, 33455.73)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#7cc098"/>
|
||||
<stop offset="1" stop-color="#5f8a71"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g mask="url(#mask)">
|
||||
<g>
|
||||
<path d="M0,0H70V70H0Z" fill-rule="evenodd" fill="url(#linear-gradient)"/>
|
||||
<path d="M4,1H65c2.67,0,4.33.67,5,2V0H0V3C.67,1.67,2,1,4,1Z" fill="#fff" fill-opacity="0.38" fill-rule="evenodd"/>
|
||||
<path d="M4,69H65c2.67,0,4.33-1,5-3v4H0V66A3.92,3.92,0,0,0,4,69Z" fill-opacity="0.38" fill-rule="evenodd"/>
|
||||
<path d="M4,69a3.66,3.66,0,0,1-4-4V34.17L20.65,13.52l24.78-.66,2,3.78v9.44l-6.11,6.11,2.41,2.11-1.09,1.09,1.31,2L47.32,34l1.52,0,3.8-3.83,1.87,12-7.08,7.1-.56,7.6L34.81,69Z" fill-opacity="0.15" fill-rule="evenodd"/>
|
||||
<g>
|
||||
<g opacity="0.4" style="isolation: isolate">
|
||||
<path d="M21.59,39.06,23,39a2.29,2.29,0,0,0,.49,1,1.5,1.5,0,0,0,1.05.33,1.87,1.87,0,0,0,1-.27.87.87,0,0,0,.33-.66A.64.64,0,0,0,25.7,39a1.88,1.88,0,0,0-.49-.33l-1.15-.33a4.49,4.49,0,0,1-1.59-.71,1.82,1.82,0,0,1-.66-1.42,1.52,1.52,0,0,1,.33-1,1.83,1.83,0,0,1,.88-.71,3.31,3.31,0,0,1,1.37-.22,3.2,3.2,0,0,1,2,.6,2.05,2.05,0,0,1,.72,1.54l-1.43,0a1.3,1.3,0,0,0-.38-.77,1.44,1.44,0,0,0-.88-.22,1.73,1.73,0,0,0-1,.28.51.51,0,0,0-.22.44.52.52,0,0,0,.22.44,3.47,3.47,0,0,0,1.32.49,7.23,7.23,0,0,1,1.53.49,2,2,0,0,1,.77.71,2.34,2.34,0,0,1,.27,1.16A2.3,2.3,0,0,1,27,40.6a2.08,2.08,0,0,1-.94.76,4.1,4.1,0,0,1-1.53.28A3.3,3.3,0,0,1,22.47,41,3.1,3.1,0,0,1,21.59,39.06Z"/>
|
||||
<path d="M28.39,41.36V34.29h2.13l1.26,4.83L33,34.29h2.14v7.07H33.87V35.83L32.5,41.36H31.13l-1.37-5.53v5.53Z"/>
|
||||
<path d="M36.17,39.06,37.54,39A2.29,2.29,0,0,0,38,40a1.56,1.56,0,0,0,1,.28,1.77,1.77,0,0,0,1-.28.83.83,0,0,0,.33-.65.61.61,0,0,0-.16-.44,2.07,2.07,0,0,0-.49-.33c-.17-.06-.55-.17-1.16-.33A3.37,3.37,0,0,1,37,37.53a1.88,1.88,0,0,1-.65-1.43,1.51,1.51,0,0,1,.33-1,1.93,1.93,0,0,1,.87-.72A3.52,3.52,0,0,1,39,34.18a3.15,3.15,0,0,1,2,.61,2,2,0,0,1,.71,1.53l-1.42.06a1.25,1.25,0,0,0-.39-.77,1.33,1.33,0,0,0-.87-.22,1.81,1.81,0,0,0-1,.27.52.52,0,0,0-.22.44.51.51,0,0,0,.22.44,3.09,3.09,0,0,0,1.32.49,7.13,7.13,0,0,1,1.53.5,2,2,0,0,1,.77.71,2.44,2.44,0,0,1,.27,1.15,2.29,2.29,0,0,1-.33,1.15,1.8,1.8,0,0,1-.93.77,4.36,4.36,0,0,1-1.53.27A3.42,3.42,0,0,1,37,41,3,3,0,0,1,36.17,39.06Z"/>
|
||||
<path d="M57.14,37.2l-4.55-4.93a1.37,1.37,0,0,0-2.36,1.06v2.74H45.3v4h4.93v3a1.37,1.37,0,0,0,2.36,1.06l4.55-4.93A1.54,1.54,0,0,0,57.14,37.2Z"/>
|
||||
<path d="M18.09,36.07H10a1.78,1.78,0,0,0-1.69,1.34,2,2,0,0,0,1.62,2.66h8.18Z"/>
|
||||
<path d="M43.41,14.88H20.11a2,2,0,0,0-2,2V28.09h2.3V21.28a.27.27,0,0,1,.3-.3h22.1a.27.27,0,0,1,.3.3v6.81h2.3V16.88A2,2,0,0,0,43.41,14.88Zm-8.5,4.7h-6.1a.47.47,0,0,1-.5-.5c0-.3.1-.5.4-.5h6.1a.47.47,0,0,1,.5.5A.46.46,0,0,1,34.91,19.58Z"/>
|
||||
<path d="M43.11,47.38v6.9a.27.27,0,0,1-.3.3H20.71a.27.27,0,0,1-.3-.3v-6.9h-2.3v10.2a2,2,0,0,0,2,2h23.3a2,2,0,0,0,2-2V47.38Zm-11.3,11.1a1.5,1.5,0,1,1,1.5-1.5A1.47,1.47,0,0,1,31.81,58.48Z"/>
|
||||
</g>
|
||||
<g style="isolation: isolate">
|
||||
<path d="M23.61,37,25,36.93a2.3,2.3,0,0,0,.5,1,1.48,1.48,0,0,0,1,.33,1.85,1.85,0,0,0,1-.27.87.87,0,0,0,.33-.66.62.62,0,0,0-.17-.44,1.88,1.88,0,0,0-.49-.33l-1.15-.33a5,5,0,0,1-1.59-.71,1.84,1.84,0,0,1-.66-1.43,1.51,1.51,0,0,1,.33-1,1.87,1.87,0,0,1,.88-.71,3.31,3.31,0,0,1,1.37-.22,3.23,3.23,0,0,1,2,.6,2.06,2.06,0,0,1,.71,1.53l-1.43.06a1.27,1.27,0,0,0-.38-.77,1.42,1.42,0,0,0-.88-.22,1.7,1.7,0,0,0-1,.28.48.48,0,0,0-.22.43.48.48,0,0,0,.22.44,3.13,3.13,0,0,0,1.31.5,6.81,6.81,0,0,1,1.54.49,1.87,1.87,0,0,1,.76.71,2.33,2.33,0,0,1,.28,1.15A2.27,2.27,0,0,1,29,38.57a2.13,2.13,0,0,1-.93.77,4.37,4.37,0,0,1-1.54.27,3.32,3.32,0,0,1-2.08-.6A3.15,3.15,0,0,1,23.61,37Z" fill="#fff"/>
|
||||
<path d="M30.41,39.34V32.27h2.14l1.26,4.82,1.26-4.82H37.2v7.07H35.89V33.81l-1.37,5.53H33.15l-1.37-5.53v5.53Z" fill="#fff"/>
|
||||
<path d="M38.19,37l1.37-.11a2.4,2.4,0,0,0,.49,1,1.57,1.57,0,0,0,1.05.27,1.87,1.87,0,0,0,1-.27.85.85,0,0,0,.33-.66.64.64,0,0,0-.17-.44,1.66,1.66,0,0,0-.49-.32c-.17-.06-.55-.17-1.15-.33a3.27,3.27,0,0,1-1.59-.72,1.82,1.82,0,0,1-.66-1.42,1.55,1.55,0,0,1,.33-1,1.83,1.83,0,0,1,.88-.71A3.48,3.48,0,0,1,41,32.16a3.2,3.2,0,0,1,2,.6,2.07,2.07,0,0,1,.72,1.54l-1.43.05a1.24,1.24,0,0,0-.38-.76,1.37,1.37,0,0,0-.88-.22,1.81,1.81,0,0,0-1,.27.5.5,0,0,0-.21.44.51.51,0,0,0,.21.44,3.3,3.3,0,0,0,1.32.49,7.64,7.64,0,0,1,1.53.49,1.92,1.92,0,0,1,.77.72,2.32,2.32,0,0,1-.05,2.3,1.89,1.89,0,0,1-.93.77,4.42,4.42,0,0,1-1.54.27,3.36,3.36,0,0,1-2.08-.6A3,3,0,0,1,38.19,37Z" fill="#fff"/>
|
||||
<path d="M59.16,35.18l-4.54-4.93a1.37,1.37,0,0,0-2.36,1.06V34H47.32v4h4.94v3a1.37,1.37,0,0,0,2.36,1.06l4.54-4.93A1.54,1.54,0,0,0,59.16,35.18Z" fill="#fff"/>
|
||||
<path d="M20.11,34H12a1.79,1.79,0,0,0-1.7,1.35A2,2,0,0,0,11.94,38h8.17Z" fill="#fff"/>
|
||||
<path d="M45.43,12.86H22.13a2,2,0,0,0-2,2V26.07h2.3V19.26a.27.27,0,0,1,.3-.3h22.1a.27.27,0,0,1,.3.3v6.81h2.3V14.86A2,2,0,0,0,45.43,12.86Zm-8.5,4.7h-6.1a.47.47,0,0,1-.5-.5c0-.3.1-.5.4-.5h6.1a.47.47,0,0,1,.5.5A.46.46,0,0,1,36.93,17.56Z" fill="#fff"/>
|
||||
<path d="M45.13,45.35v6.91a.27.27,0,0,1-.3.3H22.73a.27.27,0,0,1-.3-.3V45.35h-2.3V55.56a2,2,0,0,0,2,2h23.3a2,2,0,0,0,2-2V45.35ZM33.83,56.46a1.5,1.5,0,1,1,1.5-1.5A1.47,1.47,0,0,1,33.83,56.46Z" fill="#fff"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<svg width="50" height="50" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg"><path d="M13 8a4 4 0 0 1 4-4h16a4 4 0 0 1 4 4v34a4 4 0 0 1-4 4H17a4 4 0 0 1-4-4V8Z" fill="#1AD3BB"/><path d="M37 19v18a9 9 0 1 1 0-18Z" fill="#1A6F66"/><path d="M13 31V13a9 9 0 1 1 0 18Z" fill="#005E7A"/><path d="M13 13H4v9a9 9 0 0 0 9 9V13Z" fill="#985184"/><path d="M37 37h9v-9a9 9 0 0 0-9-9v18Z" fill="#FC868B"/></svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 405 B |
BIN
odoo-bringout-oca-ocb-sms/sms/static/description/icon_hi.png
Normal file
BIN
odoo-bringout-oca-ocb-sms/sms/static/description/icon_hi.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.5 KiB |
|
|
@ -1,12 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-inherit="mail.NotificationGroup" t-inherit-mode="extension">
|
||||
<xpath expr="//*[hasclass('o_NotificationGroup_inlineText')]" position="inside">
|
||||
<t t-if="notificationGroupView.notificationGroup.notification_type === 'sms'">
|
||||
An error occurred when sending an SMS.
|
||||
</t>
|
||||
</xpath>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
|
@ -1,10 +1,9 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { PhoneField } from "@web/views/fields/phone/phone_field";
|
||||
import { PhoneField, phoneField, formPhoneField } from "@web/views/fields/phone/phone_field";
|
||||
import { SendSMSButton } from '@sms/components/sms_button/sms_button';
|
||||
|
||||
patch(PhoneField, "sms.PhoneField", {
|
||||
patch(PhoneField, {
|
||||
components: {
|
||||
...PhoneField.components,
|
||||
SendSMSButton
|
||||
|
|
@ -17,10 +16,21 @@ patch(PhoneField, "sms.PhoneField", {
|
|||
...PhoneField.props,
|
||||
enableButton: { type: Boolean, optional: true },
|
||||
},
|
||||
extractProps: ({ attrs }) => {
|
||||
return {
|
||||
enableButton: attrs.options.enable_sms,
|
||||
placeholder: attrs.placeholder,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
const patchDescr = () => ({
|
||||
extractProps({ options }) {
|
||||
const props = super.extractProps(...arguments);
|
||||
props.enableButton = options.enable_sms;
|
||||
return props;
|
||||
},
|
||||
supportedOptions: [{
|
||||
label: _t("Enable SMS"),
|
||||
name: "enable_sms",
|
||||
type: "boolean",
|
||||
default: true,
|
||||
}],
|
||||
});
|
||||
|
||||
patch(phoneField, patchDescr());
|
||||
patch(formPhoneField, patchDescr());
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
<t t-inherit="web.PhoneField" t-inherit-mode="extension">
|
||||
<xpath expr="//div[hasclass('o_phone_content')]//a" position="after">
|
||||
<t t-if="props.enableButton and props.value.length > 0">
|
||||
<t t-if="props.enableButton and props.record.data[props.name].length > 0">
|
||||
<SendSMSButton t-props="props" />
|
||||
</t>
|
||||
</xpath>
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
<t t-inherit="web.FormPhoneField" t-inherit-mode="extension">
|
||||
<xpath expr="//div[hasclass('o_phone_content')]" position="inside">
|
||||
<t t-if="props.enableButton and props.value.length > 0">
|
||||
<t t-if="props.enableButton and props.record.data[props.name].length > 0">
|
||||
<SendSMSButton t-props="props" />
|
||||
</t>
|
||||
</xpath>
|
||||
|
|
|
|||
|
|
@ -1,41 +1,44 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
import { user } from "@web/core/user";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
|
||||
const { Component , status } = owl;
|
||||
import { Component, status } from "@odoo/owl";
|
||||
|
||||
export class SendSMSButton extends Component {
|
||||
static template = "sms.SendSMSButton";
|
||||
static props = ["*"];
|
||||
setup() {
|
||||
this.action = useService("action");
|
||||
this.user = useService("user");
|
||||
this.title = this.env._t("Send SMS Text Message");
|
||||
this.title = _t("Send SMS");
|
||||
}
|
||||
get phoneHref() {
|
||||
return "sms:" + this.props.value.replace(/\s+/g, "");
|
||||
return "sms:" + this.props.record.data[this.props.name].replace(/\s+/g, "");
|
||||
}
|
||||
async onClick() {
|
||||
await this.props.record.save();
|
||||
this.action.doAction({
|
||||
type: "ir.actions.act_window",
|
||||
target: "new",
|
||||
name: this.title,
|
||||
res_model: "sms.composer",
|
||||
views: [[false, "form"]],
|
||||
context: {
|
||||
...this.user.context,
|
||||
default_res_model: this.props.record.resModel,
|
||||
default_res_id: this.props.record.resId,
|
||||
default_number_field_name: this.props.name,
|
||||
default_composition_mode: 'comment',
|
||||
}
|
||||
}, {
|
||||
onClose: () => {
|
||||
if (status(this) !== "destroyed") {
|
||||
this.props.record.load();
|
||||
this.props.record.model.notify();
|
||||
}
|
||||
this.action.doAction(
|
||||
{
|
||||
type: "ir.actions.act_window",
|
||||
target: "new",
|
||||
name: this.title,
|
||||
res_model: "sms.composer",
|
||||
views: [[false, "form"]],
|
||||
context: {
|
||||
...user.context,
|
||||
default_res_model: this.props.record.resModel,
|
||||
default_res_id: this.props.record.resId,
|
||||
default_number_field_name: this.props.name,
|
||||
default_composition_mode: "comment",
|
||||
dialog_size: "medium",
|
||||
},
|
||||
},
|
||||
});
|
||||
{
|
||||
onClose: () => {
|
||||
if (status(this) === "destroyed") {
|
||||
return;
|
||||
}
|
||||
this.props.record.load();
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
SendSMSButton.template = "sms.SendSMSButton";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="sms.SendSMSButton" owl="1">
|
||||
<t t-name="sms.SendSMSButton">
|
||||
<a
|
||||
t-att-title="title"
|
||||
t-att-href="phoneHref"
|
||||
|
|
|
|||
|
|
@ -1,52 +1,38 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import basic_fields from 'web.basic_fields';
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { EmojisTextField} from '@mail/views/fields/emojis_text_field/emojis_text_field';
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
import {
|
||||
EmojisTextField,
|
||||
emojisTextField,
|
||||
} from "@mail/views/web/fields/emojis_text_field/emojis_text_field";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
const DynamicPlaceholderFieldMixin = basic_fields.DynamicPlaceholderFieldMixin;
|
||||
/**
|
||||
* SmsWidget is a widget to display a textarea (the body) and a text representing
|
||||
* the number of SMS and the number of characters. This text is computed every
|
||||
* time the user changes the body.
|
||||
*/
|
||||
export class SmsWidget extends EmojisTextField {
|
||||
static template = "sms.SmsWidget";
|
||||
setup() {
|
||||
super.setup();
|
||||
this._emojiAdded = () => this.props.record.update({ [this.props.name]: this.targetEditElement.el.value });
|
||||
this.notification = useService('notification');
|
||||
}
|
||||
|
||||
get encoding() {
|
||||
return this._extractEncoding(this.props.value || '');
|
||||
return this._extractEncoding(this.props.record.data[this.props.name] || '');
|
||||
}
|
||||
get nbrChar() {
|
||||
const content = this._getValueForSmsCounts(this.props.value || '');
|
||||
const content = this._getValueForSmsCounts(this.props.record.data[this.props.name] || "");
|
||||
return content.length + (content.match(/\n/g) || []).length;
|
||||
}
|
||||
get nbrCharExplanation() {
|
||||
return '';
|
||||
return "";
|
||||
}
|
||||
get nbrSMS() {
|
||||
return this._countSMS(this.nbrChar, this.encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a Model Field Selector in order to select fields
|
||||
* and create a dynamic placeholder string with or without
|
||||
* a default text value.
|
||||
*
|
||||
* @public
|
||||
* @param {String} baseModel
|
||||
* @param {Array} chain
|
||||
*
|
||||
*/
|
||||
async openDynamicPlaceholder(baseModel, chain = []) {
|
||||
const modelSelector = await this._openNewModelSelector(baseModel, chain);
|
||||
modelSelector.$el.css('margin-top', 4);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private: SMS
|
||||
//--------------------------------------------------------------------------
|
||||
|
|
@ -109,13 +95,14 @@ export class SmsWidget extends EmojisTextField {
|
|||
* @private
|
||||
*/
|
||||
async onBlur() {
|
||||
var content = this.props.value || '';
|
||||
await super.onBlur();
|
||||
var content = this.props.record.data[this.props.name] || '';
|
||||
if( !content.trim().length && content.length > 0) {
|
||||
this.notification.add(
|
||||
this.env._t("Your SMS Text Message must include at least one non-whitespace character"),
|
||||
_t("Your SMS Text Message must include at least one non-whitespace character"),
|
||||
{ type: 'danger' },
|
||||
)
|
||||
await this.props.update(content.trim());
|
||||
await this.props.record.update({ [this.props.name]: content.trim() });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -124,18 +111,19 @@ export class SmsWidget extends EmojisTextField {
|
|||
* @private
|
||||
*/
|
||||
async onInput(ev) {
|
||||
await this.props.update(this.targetEditElement.el.value);
|
||||
super.onInput(...arguments);
|
||||
const key = ev.originalEvent ? ev.originalEvent.data : '';
|
||||
if (this.props.dynamicPlaceholder && key === this.DYNAMIC_PLACEHOLDER_TRIGGER_KEY) {
|
||||
const baseModel = this.recordData && this.recordData.mailing_model_real ? this.recordData.mailing_model_real : undefined;
|
||||
if (baseModel) {
|
||||
this.openDynamicPlaceholder(baseModel);
|
||||
}
|
||||
}
|
||||
await this.props.record.update({ [this.props.name]: this.targetEditElement.el.value });
|
||||
}
|
||||
}
|
||||
|
||||
export const smsWidget = {
|
||||
...emojisTextField,
|
||||
component: SmsWidget,
|
||||
additionalClasses: [
|
||||
...(emojisTextField.additionalClasses || []),
|
||||
"o_field_text",
|
||||
"o_field_text_emojis",
|
||||
],
|
||||
};
|
||||
SmsWidget.template = 'sms.SmsWidget';
|
||||
SmsWidget.additionalClasses = [...(EmojisTextField.additionalClasses || []), 'o_field_text'];
|
||||
patch(SmsWidget.prototype, 'sms_widget_dynamic_placeholder_field_mixin', DynamicPlaceholderFieldMixin);
|
||||
registry.category("fields").add("sms_widget", SmsWidget);
|
||||
|
||||
registry.category("fields").add("sms_widget", smsWidget);
|
||||
|
|
|
|||
|
|
@ -1,17 +1,20 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<templates xml:space="preserve">
|
||||
<t t-name="sms.SmsWidget" t-inherit="mail.EmojisTextField" t-inherit-mode="primary" owl="1">
|
||||
<xpath expr="//textarea[1]" position="attributes">
|
||||
<attribute name="t-on-blur">onBlur</attribute>
|
||||
</xpath>
|
||||
<t t-name="sms.SmsWidget" t-inherit="mail.EmojisTextField" t-inherit-mode="primary">
|
||||
<xpath expr="//div[hasclass('o_field_input_buttons')]/button[hasclass('fa-magic')]" position="replace"/>
|
||||
<xpath expr="/*[last()]/*[last()]" position="after">
|
||||
<div class="o_sms_container">
|
||||
<span class="text-muted o_sms_count">
|
||||
<t t-out="nbrChar"/> characters<t t-out="nbrCharExplanation"/>, fits in <t t-out="nbrSMS"/> SMS (<t t-out="encoding"/>)
|
||||
<div class="o_sms_container mt-3">
|
||||
<span class="text-muted o_sms_count me-1">
|
||||
<t t-out="nbrChar"/>/<t t-out="160 * nbrSMS" /> <t t-out="nbrCharExplanation" /> | <t t-out="nbrSMS"/> SMS (<t t-out="encoding"/>)
|
||||
<a href="https://iap-services.odoo.com/iap/sms/pricing" target="_blank"
|
||||
title="SMS Pricing" aria-label="SMS Pricing" class="fa fa-lg fa-info-circle"/>
|
||||
title="SMS Pricing" aria-label="SMS Pricing" class="fa fa-lg fa-info-circle align-middle"/>
|
||||
</span>
|
||||
<button t-if="props.dynamicPlaceholder"
|
||||
class="btn btn-link py-0 border-0"
|
||||
title="Insert Field"
|
||||
t-on-click="onDynamicPlaceholderOpen"
|
||||
><span class="fa fa-magic me-1"/><span>Insert Field</span></button>
|
||||
</div>
|
||||
</xpath>
|
||||
</t>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
import { Failure } from "@mail/core/common/failure_model";
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
|
||||
patch(Failure.prototype, {
|
||||
get iconSrc() {
|
||||
if (this.type === "sms") {
|
||||
return "/sms/static/img/sms_failure.svg";
|
||||
}
|
||||
return super.iconSrc;
|
||||
},
|
||||
get body() {
|
||||
if (this.type === "sms") {
|
||||
if (this.notifications.length === 1 && this.lastMessage?.thread) {
|
||||
return _t("An error occurred when sending an SMS on “%(record_name)s”", {
|
||||
record_name: this.lastMessage.thread.display_name,
|
||||
});
|
||||
}
|
||||
return _t("An error occurred when sending an SMS");
|
||||
}
|
||||
return super.body;
|
||||
},
|
||||
});
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
import { Notification } from "@mail/core/common/notification_model";
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
|
||||
/** @type {import("models").Notification} */
|
||||
const notificationPatch = {
|
||||
get failureMessage() {
|
||||
switch (this.failure_type) {
|
||||
case "sms_number_missing":
|
||||
return _t("Missing Number");
|
||||
case "sms_number_format":
|
||||
return _t("Wrong Number Format");
|
||||
case "sms_credit":
|
||||
return _t("Insufficient Credit");
|
||||
case "sms_country_not_supported":
|
||||
return _t("Country Not Supported");
|
||||
case "sms_registration_needed":
|
||||
return _t("Country-specific Registration Required");
|
||||
case "sms_server":
|
||||
return _t("Server Error");
|
||||
case "sms_acc":
|
||||
return _t("Unregistered Account");
|
||||
case "sms_expired":
|
||||
return _t("Expired");
|
||||
case "sms_invalid_destination":
|
||||
return _t("Invalid Destination");
|
||||
case "sms_not_allowed":
|
||||
return _t("Not Allowed");
|
||||
case "sms_not_delivered":
|
||||
return _t("Not Delivered");
|
||||
case "sms_rejected":
|
||||
return _t("Rejected");
|
||||
default:
|
||||
return super.failureMessage;
|
||||
}
|
||||
},
|
||||
get icon() {
|
||||
if (this.notification_type === "sms") {
|
||||
return "fa fa-mobile";
|
||||
}
|
||||
return super.icon;
|
||||
},
|
||||
get label() {
|
||||
if (this.notification_type === "sms") {
|
||||
return _t("SMS");
|
||||
}
|
||||
return super.label;
|
||||
},
|
||||
};
|
||||
patch(Notification.prototype, notificationPatch);
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
odoo.define('sms.fields', function (require) {
|
||||
"use strict";
|
||||
|
||||
var basic_fields = require('web.basic_fields');
|
||||
var core = require('web.core');
|
||||
var session = require('web.session');
|
||||
|
||||
var _t = core._t;
|
||||
|
||||
/**
|
||||
* Override of FieldPhone to add a button calling SMS composer if option activated (default)
|
||||
*/
|
||||
|
||||
var Phone = basic_fields.FieldPhone;
|
||||
Phone.include({
|
||||
/**
|
||||
* By default, enable_sms is activated
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
init() {
|
||||
this._super.apply(this, arguments);
|
||||
this.enableSMS = 'enable_sms' in this.attrs.options ? this.attrs.options.enable_sms : true;
|
||||
// reinject in nodeOptions (and thus in this.attrs) to signal the property
|
||||
this.attrs.options.enable_sms = this.enableSMS;
|
||||
},
|
||||
/**
|
||||
* When the send SMS button is displayed, $el becomes a div wrapping
|
||||
* the original links.
|
||||
* This method makes sure we always focus the phone number
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
getFocusableElement() {
|
||||
if (this.enableSMS && this.mode === 'readonly') {
|
||||
return this.$el.filter('.' + this.className).find('a');
|
||||
}
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Open SMS composer wizard
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_onClickSMS: function (ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
var context = session.user_context;
|
||||
context = _.extend({}, context, {
|
||||
default_res_model: this.model,
|
||||
default_res_id: parseInt(this.res_id),
|
||||
default_number_field_name: this.name,
|
||||
default_composition_mode: 'comment',
|
||||
});
|
||||
var self = this;
|
||||
return this.do_action({
|
||||
title: _t('Send SMS Text Message'),
|
||||
type: 'ir.actions.act_window',
|
||||
res_model: 'sms.composer',
|
||||
target: 'new',
|
||||
views: [[false, 'form']],
|
||||
context: context,
|
||||
}, {
|
||||
on_close: function () {
|
||||
self.trigger_up('reload');
|
||||
}});
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a button to call the composer wizard
|
||||
*
|
||||
* @override
|
||||
* @private
|
||||
*/
|
||||
_renderReadonly: function () {
|
||||
var def = this._super.apply(this, arguments);
|
||||
if (this.enableSMS && this.value) {
|
||||
var $composerButton = $('<a>', {
|
||||
title: _t('Send SMS Text Message'),
|
||||
href: '',
|
||||
class: 'ms-3 d-inline-flex align-items-center o_field_phone_sms',
|
||||
html: $('<small>', {class: 'fw-bold ms-1', html: 'SMS'}),
|
||||
});
|
||||
$composerButton.prepend($('<i>', {class: 'fa fa-mobile'}));
|
||||
$composerButton.on('click', this._onClickSMS.bind(this));
|
||||
this.$el = this.$el.add($composerButton);
|
||||
}
|
||||
return def;
|
||||
},
|
||||
});
|
||||
|
||||
return Phone;
|
||||
|
||||
});
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
import { MessagingMenu } from "@mail/core/public_web/messaging_menu";
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
|
||||
patch(MessagingMenu.prototype, {
|
||||
openFailureView(failure) {
|
||||
if (failure.type === "email") {
|
||||
return super.openFailureView(failure);
|
||||
}
|
||||
this.env.services.action.doAction({
|
||||
name: _t("SMS Failures"),
|
||||
type: "ir.actions.act_window",
|
||||
view_mode: "kanban,list,form",
|
||||
views: [
|
||||
[false, "kanban"],
|
||||
[false, "list"],
|
||||
[false, "form"],
|
||||
],
|
||||
target: "current",
|
||||
res_model: failure.resModel,
|
||||
domain: [["message_has_sms_error", "=", true]],
|
||||
context: { create: false },
|
||||
});
|
||||
this.dropdown.close();
|
||||
},
|
||||
getFailureNotificationName(failure) {
|
||||
if (failure.type === "sms") {
|
||||
return _t("SMS Failure: %(modelName)s", { modelName: failure.modelName });
|
||||
}
|
||||
return super.getFailureNotificationName(...arguments);
|
||||
},
|
||||
});
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { registerPatch } from '@mail/model/model_core';
|
||||
|
||||
registerPatch({
|
||||
name: 'Message',
|
||||
recordMethods: {
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
openResendAction() {
|
||||
if (this.message_type === 'sms') {
|
||||
this.env.services.action.doAction(
|
||||
'sms.sms_resend_action',
|
||||
{
|
||||
additionalContext: {
|
||||
default_mail_message_id: this.id,
|
||||
},
|
||||
},
|
||||
);
|
||||
} else {
|
||||
this._super(...arguments);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue