-
10base_sms_client/README.rst
-
0base_sms_client/__init__.py
-
20base_sms_client/__manifest__.py
-
11base_sms_client/data/sms_gateway_data.xml
-
0base_sms_client/i18n/ar.po
-
0base_sms_client/i18n/ca.po
-
0base_sms_client/i18n/de.po
-
0base_sms_client/i18n/es.po
-
0base_sms_client/i18n/fr.po
-
0base_sms_client/i18n/pt_BR.po
-
0base_sms_client/images/client.jpeg
-
0base_sms_client/images/gateway.jpeg
-
0base_sms_client/images/gateway_access.jpeg
-
0base_sms_client/images/send_sms.jpeg
-
0base_sms_client/images/sms.jpeg
-
9base_sms_client/models/__init__.py
-
7base_sms_client/models/server_action.py
-
100base_sms_client/models/sms_gateway.py
-
129base_sms_client/models/sms_sms.py
-
2base_sms_client/models/sms_template.py
-
6base_sms_client/security/groups.xml
-
0base_sms_client/security/ir.model.access.csv
-
2base_sms_client/security/ir.rule.csv
-
0base_sms_client/static/src/img/icon.png
-
19base_sms_client/views/server_action_view.xml
-
140base_sms_client/views/sms_gateway_view.xml
-
17base_sms_client/views/smstemplate_view.xml
-
5base_sms_client/wizard/__init__.py
-
66base_sms_client/wizard/mass_sms.py
-
55base_sms_client/wizard/mass_sms_view.xml
-
1oca_dependencies.txt
-
4ovh_sms_client/README.rst
-
0ovh_sms_client/__init__.py
-
17ovh_sms_client/__manifest__.py
-
2ovh_sms_client/data/keychain.xml
-
0ovh_sms_client/models/__init__.py
-
21ovh_sms_client/models/keychain.py
-
19ovh_sms_client/models/sms_gateway.py
-
227smsclient_core/models/sms_gateway.py
-
8smsclient_core/security/groups.xml
-
20smsclient_core/views/serveraction_view.xml
-
146smsclient_core/views/sms_gateway_view.xml
-
23smsclient_core/views/smstemplate_view.xml
-
22smsclient_core/wizard/__init__.py
-
55smsclient_core/wizard/mass_sms_view.xml
-
45smsclient_ovh/models/keychain.py
Before Width: 1301 | Height: 359 | Size: 43 KiB After Width: 1301 | Height: 359 | Size: 43 KiB |
Before Width: 1301 | Height: 418 | Size: 59 KiB After Width: 1301 | Height: 418 | Size: 59 KiB |
Before Width: 1301 | Height: 413 | Size: 56 KiB After Width: 1301 | Height: 413 | Size: 56 KiB |
Before Width: 897 | Height: 480 | Size: 23 KiB After Width: 897 | Height: 480 | Size: 23 KiB |
Before Width: 1301 | Height: 359 | Size: 43 KiB After Width: 1301 | Height: 359 | Size: 43 KiB |
@ -0,0 +1,9 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright (C) 2013 Julius Network Solutions SARL <contact@julius.fr> |
|||
# Author: Sébastien BEAU <sebastien.beau@akretion.com> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
from . import sms_gateway |
|||
from . import server_action |
|||
from . import sms_template |
|||
from . import sms_sms |
@ -0,0 +1,100 @@ |
|||
# coding: utf-8 |
|||
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). |
|||
# Copyright (C) 2011 SYLEAM (<http://syleam.fr/>) |
|||
# Copyright (C) 2013 Julius Network Solutions SARL <contact@julius.fr> |
|||
# Copyright (C) 2015 Valentin Chemiere <valentin.chemiere@akretion.com> |
|||
# Copyright (C) 2015 Sébastien BEAU <sebastien.beau@akretion.com> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
from odoo import models, fields, api |
|||
|
|||
PRIORITY_LIST = [ |
|||
('0', '0'), |
|||
('1', '1'), |
|||
('2', '2'), |
|||
('3', '3') |
|||
] |
|||
|
|||
CLASSES_LIST = [ |
|||
('0', 'Flash'), |
|||
('1', 'Phone display'), |
|||
('2', 'SIM'), |
|||
('3', 'Toolkit') |
|||
] |
|||
|
|||
|
|||
class SmsAbstract(models.AbstractModel): |
|||
_name = 'sms.abstract' |
|||
_description = 'SMS Abstract Model' |
|||
|
|||
code = fields.Char('Verification Code') |
|||
body = fields.Text( |
|||
string='Message', |
|||
help="The message text that will be send along with the" |
|||
" email which is send through this server.") |
|||
classes = fields.Selection( |
|||
selection=CLASSES_LIST, string='Class', |
|||
default='1', |
|||
help='The SMS class') |
|||
deferred = fields.Integer( |
|||
help='The time -in minute(s)- to wait before sending the message.') |
|||
priority = fields.Selection( |
|||
selection=PRIORITY_LIST, string='Priority', default='3', |
|||
help='The priority of the message') |
|||
coding = fields.Selection(selection=[ |
|||
('1', '7 bit'), |
|||
('2', 'Unicode') |
|||
], string='Coding', |
|||
help='The SMS coding: 1 for 7 bit (160 chracters max' |
|||
'length) or 2 for unicode (70 characters max' |
|||
'length)', |
|||
default='1' |
|||
) |
|||
tag = fields.Char('Tag', help='an optional tag') |
|||
nostop = fields.Boolean( |
|||
default=True, |
|||
help='Do not display STOP clause in the message, this requires that ' |
|||
'this is not an advertising message.') |
|||
validity = fields.Integer( |
|||
default=10, |
|||
help="The maximum time - in minute(s) - before the message " |
|||
"is dropped.") |
|||
|
|||
char_limit = fields.Integer(string='Character Limit', default=160) |
|||
default_gateway = fields.Boolean() |
|||
company_id = fields.Many2one(comodel_name='res.company') |
|||
|
|||
|
|||
class SmsGateway(models.Model): |
|||
_name = 'sms.gateway' |
|||
_description = 'SMS Client' |
|||
_inherit = 'sms.abstract' |
|||
|
|||
name = fields.Char(string='Gateway Name', required=True) |
|||
from_provider = fields.Char(string="From") |
|||
method = fields.Selection(string='API Method', selection=[]) |
|||
url = fields.Char( |
|||
string='Gateway URL', help='Base url for message') |
|||
state = fields.Selection(selection=[ |
|||
('new', 'Not Verified'), |
|||
('waiting', 'Waiting for Verification'), |
|||
('confirm', 'Verified'), |
|||
], string='Gateway Status', index=True, readonly=True, default='new') |
|||
user_ids = fields.Many2many( |
|||
comodel_name='res.users', |
|||
string='Users Allowed to use the gateway') |
|||
|
|||
@api.multi |
|||
def _check_permissions(self): |
|||
self.ensure_one() |
|||
if self.env.uid not in self.sudo().user_ids.ids: |
|||
return False |
|||
return True |
|||
|
|||
@api.model |
|||
def _run_send_sms(self, domain=None): |
|||
if domain is None: |
|||
domain = [] |
|||
domain.append(('state', '=', 'draft')) |
|||
sms = self.env['sms.sms'].search(domain) |
|||
return sms.send() |
@ -0,0 +1,129 @@ |
|||
# coding: utf-8 |
|||
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). |
|||
# Copyright (C) 2011 SYLEAM (<http://syleam.fr/>) |
|||
# Copyright (C) 2013 Julius Network Solutions SARL <contact@julius.fr> |
|||
# Copyright (C) 2015 Valentin Chemiere <valentin.chemiere@akretion.com> |
|||
# Copyright (C) 2015 Sébastien BEAU <sebastien.beau@akretion.com> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
from odoo import models, fields, api, _ |
|||
import logging |
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
|
|||
class SmsSms(models.Model): |
|||
_name = 'sms.sms' |
|||
_description = 'SMS' |
|||
_rec_name = 'mobile' |
|||
_inherit = 'sms.abstract' |
|||
|
|||
message = fields.Text( |
|||
size=256, |
|||
required=True, |
|||
readonly=True, |
|||
states={'draft': [('readonly', False)]}) |
|||
mobile = fields.Char( |
|||
required=True, |
|||
readonly=True, |
|||
states={'draft': [('readonly', False)]}) |
|||
gateway_id = fields.Many2one( |
|||
comodel_name='sms.gateway', |
|||
string='SMS Gateway', |
|||
readonly=True, |
|||
states={'draft': [('readonly', False)]}) |
|||
partner_id = fields.Many2one( |
|||
'res.partner', |
|||
readonly=True, |
|||
states={'draft': [('readonly', False)]}, |
|||
string='Partner') |
|||
state = fields.Selection(selection=[ |
|||
('draft', 'Queued'), |
|||
('sent', 'Sent'), |
|||
('cancel', 'Cancel'), |
|||
('error', 'Error'), |
|||
], string='Message Status', |
|||
readonly=True, |
|||
default='draft') |
|||
error = fields.Text( |
|||
string='Last Error', |
|||
size=256, |
|||
readonly=True, |
|||
states={'draft': [('readonly', False)]}) |
|||
|
|||
@api.onchange('partner_id') |
|||
def onchange_partner_id(self): |
|||
self.mobile = self.partner_id.mobile |
|||
|
|||
# commit is use to not loose each sms state with orm rollback |
|||
@api.multi |
|||
def _check_gateway_method(self): |
|||
self.ensure_one() |
|||
if self.gateway_id.method: |
|||
return True |
|||
else: |
|||
self.write({ |
|||
'state': 'error', |
|||
'error': _("No method gateway selected ")}) |
|||
self._cr.commit() |
|||
return False |
|||
|
|||
@api.multi |
|||
def _check_gateway_permission(self): |
|||
self.ensure_one() |
|||
if self.gateway_id._check_permissions(): |
|||
return True |
|||
else: |
|||
self.write( |
|||
{'error': 'no permission on gateway', 'state': 'error'}) |
|||
self._cr.commit() |
|||
return False |
|||
|
|||
@api.multi |
|||
def _check_sms_length(self): |
|||
self.ensure_one() |
|||
if len(self.message) <= self.gateway_id.char_limit: |
|||
return True |
|||
else: |
|||
self.write({ |
|||
'state': 'error', |
|||
'error': _("Size of SMS should not be more than %s " |
|||
"characters ") % self.sms.gateway_id.char_limit |
|||
}) |
|||
self._cr.commit() |
|||
return False |
|||
|
|||
@api.multi |
|||
def send(self): |
|||
allsend_ok = True |
|||
for sms in self: |
|||
sms_check = True |
|||
if not sms._check_gateway_method(): |
|||
allsend_ok = False |
|||
sms_check = False |
|||
continue |
|||
if not sms.gateway_id._check_permissions(): |
|||
allsend_ok = False |
|||
sms_check = False |
|||
continue |
|||
if not sms._check_sms_length(): |
|||
allsend_ok = False |
|||
sms_check = False |
|||
continue |
|||
if sms_check: |
|||
try: |
|||
with sms._cr.savepoint(): |
|||
getattr(sms, "_send_%s" % sms.gateway_id.method)() |
|||
sms.write({'state': 'sent', 'error': ''}) |
|||
except Exception as e: |
|||
_logger.error('Failed to send sms %s', e) |
|||
sms.write({'error': e, 'state': 'error'}) |
|||
sms._cr.commit() |
|||
return allsend_ok |
|||
|
|||
@api.multi |
|||
def cancel(self): |
|||
self.write({'state': 'cancel'}) |
|||
|
|||
@api.multi |
|||
def retry(self): |
|||
self.write({'state': 'draft'}) |
@ -0,0 +1,6 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<odoo> |
|||
<record id="group_sms_user" model="res.groups"> |
|||
<field name="name">SMS / User</field> |
|||
</record> |
|||
</odoo> |
@ -1,4 +1,4 @@ |
|||
id,name,model_id:id,groups:id,perm_read,perm_write,perm_create,perm_unlink,domain_force |
|||
edit_access_sms,Edit Access Sms,model_sms_sms,,True,True,True,True,"[('company_id','=', user.company_id.id)]" |
|||
edit_access_sms_gateway,Edit Access Sms Gateway,model_sms_gateway,,False,True,True,True,"[('company_id','=', user.company_id.id)]" |
|||
read_access_sms_gateway,Read Access Sms Gateway,model_sms_gateway,,True,False,False,False,"['|', '|', ('company_id','=', user.company_id.id),('company_id','child_of',[user.company_id.id]),('company_id','=',user.company_id.parent_id.id)]" |
|||
edit_access_sms,Edit Access Sms,model_sms_sms,,True,True,True,True,"[('company_id','=', user.company_id.id)]" |
Before Width: 224 | Height: 225 | Size: 34 KiB After Width: 224 | Height: 225 | Size: 34 KiB |
@ -0,0 +1,19 @@ |
|||
<?xml version="1.0"?> |
|||
<odoo> |
|||
<record model="ir.ui.view" id="view_server_statistics_graph"> |
|||
<field name="model">ir.actions.server</field> |
|||
<field name="inherit_id" ref="base.view_server_action_form"/> |
|||
<field name="arch" type="xml"> |
|||
<page name="code" position="after" autofocus="autofocus"> |
|||
<page string="SMS" name="sms" attrs="{'invisible': [('state', '!=', 'sms')]}"> |
|||
<group> |
|||
<field name="sms"/> |
|||
<field name="mobile"/> |
|||
<field name="sms_server_id" invisible="1"/> |
|||
<field name="sms_template_id" domain="[('sms_template','=',True)]" attrs="{'required':[('state','=','sms')]}"/> |
|||
</group> |
|||
</page> |
|||
</page> |
|||
</field> |
|||
</record> |
|||
</odoo> |
@ -0,0 +1,140 @@ |
|||
<?xml version="1.0"?> |
|||
<odoo> |
|||
<record model="ir.ui.view" id="sms_gateway_form"> |
|||
<field name="model">sms.gateway</field> |
|||
<field name="priority" eval="8"/> |
|||
<field name="arch" type="xml"> |
|||
<form string="SMS Gateway"> |
|||
<sheet> |
|||
<group col="2"> |
|||
<h1><field name="name" nolabel="1" placeholder="Name" colspan="2"/></h1> |
|||
<field name="method" nolabel="1" placeholder="Method" colspan="2"/> |
|||
<field name="default_gateway"/> |
|||
<field name="company_id" groups="base.group_multi_company"/> |
|||
</group> |
|||
<notebook colspan="4"> |
|||
<page string="General"> |
|||
<group col="4"> |
|||
<field name="state"/> |
|||
<field name="from_provider"/> |
|||
<field name="url"/> |
|||
</group> |
|||
</page> |
|||
<page string="Permission"> |
|||
<separator string="Access Permission" |
|||
colspan="4" /> |
|||
<field name="user_ids" colspan="4" nolabel="1"/> |
|||
</page> |
|||
<page string="Additional option"> |
|||
<group> |
|||
<group> |
|||
<field name="validity" /> |
|||
<field name="classes"/> |
|||
<field name="deferred" /> |
|||
<field name="nostop" /> |
|||
</group> |
|||
<group> |
|||
<field name="priority" /> |
|||
<field name="coding"/> |
|||
<field name="tag"/> |
|||
<field name="char_limit"/> |
|||
</group> |
|||
</group> |
|||
</page> |
|||
</notebook> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.ui.view" id="sms_gateway_tree"> |
|||
<field name="model">sms.gateway</field> |
|||
<field name="priority" eval="8"/> |
|||
<field name="arch" type="xml"> |
|||
<tree string="SMS Gateways"> |
|||
<field name="name"/> |
|||
<field name="method"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.actions.act_window" id="action_sms_gateway_tree"> |
|||
<field name="name">SMS Gateway</field> |
|||
<field name="res_model">sms.gateway</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">form,tree</field> |
|||
<field name="view_id" ref="sms_gateway_tree" /> |
|||
</record> |
|||
|
|||
<menuitem name="SMS Gateway" |
|||
id="menu_gateway_administration_sms_server" |
|||
sequence="100" |
|||
parent="base_phone.menu_config_phone" |
|||
action="action_sms_gateway_tree"/> |
|||
|
|||
<record model="ir.ui.view" id="sms_sms_tree"> |
|||
<field name="model">sms.sms</field> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Sms"> |
|||
<field name="create_date"/> |
|||
<field name="mobile"/> |
|||
<field name="message"/> |
|||
<field name="state"/> |
|||
<field name="gateway_id"/> |
|||
<button string="Send" states="draft" type="object" name="send"/> |
|||
<button string="Retry" states="error" type="object" name="retry"/> |
|||
<button string="Cancel" states="draft,error" type="object" name="cancel"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.ui.view" id="sms_sms_form"> |
|||
<field name="model">sms.sms</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="Sms"> |
|||
<header> |
|||
<button string="Send" states="draft" type="object" name="send"/> |
|||
<button string="Retry" states="error" type="object" name="retry"/> |
|||
<button string="Cancel" states="draft,error" type="object" name="cancel"/> |
|||
<field name="state" widget="statusbar" statusbar_visible="draft,send"/> |
|||
</header> |
|||
<sheet> |
|||
<label for="partner_id" class="oe_edit_only"/> |
|||
<h1><field name="partner_id"/></h1> |
|||
<label for="mobile" class="oe_edit_only"/> |
|||
<h1><field name="mobile"/></h1> |
|||
<group col="4"> |
|||
<field name="create_date" readonly="True"/> |
|||
<field name="gateway_id" colspan="2"/> |
|||
<field name="company_id" groups="base.group_multi_company"/> |
|||
<separator string="SMS Message" colspan="4"/> |
|||
<field name="message" colspan="4" nolabel="1"/> |
|||
<separator string="Last Error" colspan="4"/> |
|||
<field name="error" colspan="4" nolabel="1"/> |
|||
</group> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.actions.act_window" id="action_sms_sms_tree"> |
|||
<field name="name">Sms</field> |
|||
<field name="res_model">sms.sms</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">form,tree</field> |
|||
<field name="view_id" ref="sms_sms_tree" /> |
|||
</record> |
|||
|
|||
<menuitem name="SMS Message" |
|||
id="menu_gateway_administration_sms" |
|||
sequence="110" |
|||
parent="base_phone.menu_config_phone" |
|||
action="action_sms_sms_tree"/> |
|||
|
|||
<act_window context="{'gateway_id': active_id}" |
|||
domain="[('gateway_id', '=', active_id)]" |
|||
id="act_sms_gateway_2_sms" |
|||
name="Sms Message" |
|||
res_model="sms.sms" |
|||
src_model="sms.gateway"/> |
|||
</odoo> |
@ -0,0 +1,17 @@ |
|||
<?xml version="1.0"?> |
|||
<odoo> |
|||
<record model="ir.ui.view" id="email_template_form"> |
|||
<field name="name">mail.template.form</field> |
|||
<field name="model">mail.template</field> |
|||
<field name="inherit_id" ref="mail.email_template_form"/> |
|||
<field name="arch" type="xml"> |
|||
<field name="email_to" position="after"> |
|||
<field name="mobile_to"/> |
|||
</field> |
|||
<field name="lang" position="before"> |
|||
<field name="sms_template"/> |
|||
<field name="gateway_id"/> |
|||
</field> |
|||
</field> |
|||
</record> |
|||
</odoo> |
@ -1,7 +1,6 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright (C) 2013 Julius Network Solutions SARL <contact@julius.fr> |
|||
# Author: Sébastien BEAU <sebastien.beau@akretion.com> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
from . import sms_gateway |
|||
from . import serveraction |
|||
from . import smstemplate |
|||
from . import mass_sms |
@ -0,0 +1,55 @@ |
|||
<?xml version="1.0"?> |
|||
<odoo> |
|||
<record model="ir.ui.view" id="view_wizard_mass_sms"> |
|||
<field name="model">wizard.mass.sms</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="SMS Gateway - Sens SMS" version="7.0"> |
|||
<group string="Gateway" colspan="4"> |
|||
<field name="gateway_id"/> |
|||
</group> |
|||
<notebook> |
|||
<page string="Message"> |
|||
<field name="message" colspan="4" nolabel="1"/> |
|||
<!-- TODO limit to 10 the number of partner to show --> |
|||
<field name="partner_ids" colspan="4" nolabel="1"> |
|||
<tree options="{'limit': 10}"> |
|||
<field name="name"/> |
|||
<field name="mobile"/> |
|||
</tree> |
|||
</field> |
|||
</page> |
|||
<page string="Additional option"> |
|||
<group> |
|||
<group> |
|||
<field name="validity"/> |
|||
<field name="classes"/> |
|||
<field name="deferred"/> |
|||
<field name="nostop"/> |
|||
</group> |
|||
<group> |
|||
<field name="priority"/> |
|||
<field name="coding"/> |
|||
<field name="tag"/> |
|||
</group> |
|||
</group> |
|||
</page> |
|||
</notebook> |
|||
<footer> |
|||
<button string="Send SMS" name="send" type="object" |
|||
class="oe_highlight"/> |
|||
or |
|||
<button string="Cancel" class="oe_link" |
|||
special="cancel"/> |
|||
</footer> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<act_window name="Send an SMS" |
|||
res_model="wizard.mass.sms" |
|||
src_model="res.partner" |
|||
view_mode="form" |
|||
target="new" |
|||
key2="client_action_multi" |
|||
id="action_wizard_mass_sms"/> |
|||
</odoo> |
@ -0,0 +1 @@ |
|||
server-tools |
@ -0,0 +1,21 @@ |
|||
# coding: utf-8 |
|||
# Copyright (C) 2015 Sébastien BEAU <sebastien.beau@akretion.com> |
|||
# Valentin CHEMIERE <valentin.chemiere@akretion.com> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
from odoo import models, fields |
|||
|
|||
OVH_KEYCHAIN_NAMESPACE = 'ovh_provider' |
|||
|
|||
|
|||
class Keychain(models.Model): |
|||
_inherit = 'keychain.account' |
|||
|
|||
namespace = fields.Selection( |
|||
selection_add=[(OVH_KEYCHAIN_NAMESPACE, 'Ovh_sms')]) |
|||
|
|||
def _ovh_provider_init_data(self): |
|||
return {'sms_account': ""} |
|||
|
|||
def _ovh_provider_validate_data(self, data): |
|||
return True |
@ -1,227 +0,0 @@ |
|||
# coding: utf-8 |
|||
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). |
|||
# Copyright (C) 2011 SYLEAM (<http://syleam.fr/>) |
|||
# Copyright (C) 2013 Julius Network Solutions SARL <contact@julius.fr> |
|||
# Copyright (C) 2015 Valentin Chemiere <valentin.chemiere@akretion.com> |
|||
# Copyright (C) 2015 Sébastien BEAU <sebastien.beau@akretion.com> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
import logging |
|||
from odoo import models, fields, api, _ |
|||
from odoo.exceptions import UserError |
|||
|
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
PRIORITY_LIST = [ |
|||
('0', '0'), |
|||
('1', '1'), |
|||
('2', '2'), |
|||
('3', '3') |
|||
] |
|||
|
|||
CLASSES_LIST = [ |
|||
('0', 'Flash'), |
|||
('1', 'Phone display'), |
|||
('2', 'SIM'), |
|||
('3', 'Toolkit') |
|||
] |
|||
|
|||
|
|||
class SMSClient(models.Model): |
|||
_name = 'sms.gateway' |
|||
_description = 'SMS Client' |
|||
|
|||
@api.model |
|||
def get_method(self): |
|||
return [] |
|||
|
|||
name = fields.Char(string='Gateway Name', required=True) |
|||
from_provider = fields.Char(string="From") |
|||
method = fields.Selection( |
|||
string='API Method', |
|||
selection='get_method') |
|||
url = fields.Char( |
|||
string='Gateway URL', help='Base url for message') |
|||
state = fields.Selection(selection=[ |
|||
('new', 'Not Verified'), |
|||
('waiting', 'Waiting for Verification'), |
|||
('confirm', 'Verified'), |
|||
], string='Gateway Status', index=True, readonly=True, default='new') |
|||
user_ids = fields.Many2many( |
|||
comodel_name='res.users', |
|||
string='Users Allowed') |
|||
code = fields.Char('Verification Code') |
|||
body = fields.Text( |
|||
string='Message', |
|||
help="The message text that will be send along with the" |
|||
" email which is send through this server.") |
|||
validity = fields.Integer( |
|||
default=10, |
|||
help="The maximum time - in minute(s) - before the message " |
|||
"is dropped.") |
|||
classes = fields.Selection( |
|||
selection=CLASSES_LIST, string='Class', |
|||
default='1', |
|||
help='The SMS class: flash(0),phone display(1),SIM(2),toolkit(3)') |
|||
deferred = fields.Integer( |
|||
default=0, |
|||
help='The time -in minute(s)- to wait before sending the message.') |
|||
deferred_visible = fields.Boolean(default=False) |
|||
priority = fields.Selection( |
|||
selection=PRIORITY_LIST, string='Priority', default='3', |
|||
help='The priority of the message') |
|||
coding = fields.Selection(selection=[ |
|||
('1', '7 bit'), |
|||
('2', 'Unicode') |
|||
], string='Coding', |
|||
help='The SMS coding: 1 for 7 bit (160 chracters max' |
|||
'lenght) or 2 for unicode (70 characters max' |
|||
'lenght)', |
|||
default='1' |
|||
) |
|||
tag = fields.Char('Tag', help='an optional tag') |
|||
nostop = fields.Boolean( |
|||
default=True, |
|||
help='Do not display STOP clause in the message, this requires that ' |
|||
'this is not an advertising message.') |
|||
char_limit = fields.Boolean('Character Limit', default=True) |
|||
default_gateway = fields.Boolean(default=False) |
|||
company_id = fields.Many2one(comodel_name='res.company') |
|||
|
|||
@api.multi |
|||
def _check_permissions(self): |
|||
self.ensure_one() |
|||
if self.env.uid not in self.sudo().user_ids.ids: |
|||
return False |
|||
return True |
|||
|
|||
@api.model |
|||
def _run_send_sms(self, domain=None): |
|||
if domain is None: |
|||
domain = [] |
|||
domain.append(('state', '=', 'draft')) |
|||
sms = self.env['sms.sms'].search(domain) |
|||
return sms.send() |
|||
|
|||
|
|||
class SmsSms(models.Model): |
|||
_name = 'sms.sms' |
|||
_description = 'SMS' |
|||
_rec_name = 'mobile' |
|||
|
|||
message = fields.Text( |
|||
size=256, |
|||
required=True, |
|||
readonly=True, |
|||
states={'draft': [('readonly', False)]}) |
|||
mobile = fields.Char( |
|||
required=True, |
|||
readonly=True, |
|||
states={'draft': [('readonly', False)]}) |
|||
gateway_id = fields.Many2one( |
|||
comodel_name='sms.gateway', |
|||
string='SMS Gateway', |
|||
readonly=True, |
|||
states={'draft': [('readonly', False)]}) |
|||
state = fields.Selection(selection=[ |
|||
('draft', 'Queued'), |
|||
('sent', 'Sent'), |
|||
('cancel', 'Cancel'), |
|||
('error', 'Error'), |
|||
], string='Message Status', |
|||
readonly=True, |
|||
default='draft') |
|||
error = fields.Text( |
|||
string='Last Error', |
|||
size=256, |
|||
readonly=True, |
|||
states={'draft': [('readonly', False)]}) |
|||
validity = fields.Integer( |
|||
string='Validity', |
|||
readonly=True, |
|||
states={'draft': [('readonly', False)]}, |
|||
help='The maximum time -in minute(s)- before the message is dropped.') |
|||
classes = fields.Selection( |
|||
selection=CLASSES_LIST, |
|||
readonly=True, |
|||
states={'draft': [('readonly', False)]}, |
|||
help='The sms class: flash(0), phone display(1), SIM(2), toolkit(3)') |
|||
deferred = fields.Integer( |
|||
readonly=True, |
|||
states={'draft': [('readonly', False)]}, |
|||
help='The time -in minute(s)- to wait before sending the message.') |
|||
priority = fields.Selection( |
|||
readonly=True, |
|||
states={'draft': [('readonly', False)]}, |
|||
selection=PRIORITY_LIST, |
|||
help='The priority of the message ') |
|||
coding = fields.Selection([ |
|||
('1', '7 bit'), |
|||
('2', 'Unicode') |
|||
], readonly=True, |
|||
states={'draft': [('readonly', False)]}, |
|||
help='The sms coding: 1 for 7 bit or 2 for unicode') |
|||
tag = fields.Char( |
|||
size=256, |
|||
readonly=True, |
|||
states={'draft': [('readonly', False)]}, |
|||
help='An optional tag') |
|||
nostop = fields.Boolean( |
|||
string='NoStop', |
|||
readonly=True, |
|||
states={'draft': [('readonly', False)]}, |
|||
help='Do not display STOP clause in the message, this requires that' |
|||
'this is not an advertising message.') |
|||
partner_id = fields.Many2one( |
|||
'res.partner', |
|||
readonly=True, |
|||
states={'draft': [('readonly', False)]}, |
|||
string='Partner') |
|||
company_id = fields.Many2one( |
|||
comodel_name='res.company', |
|||
readonly=True, |
|||
states={'draft': [('readonly', False)]}) |
|||
|
|||
@api.model |
|||
def _convert_to_e164(self, erp_number): |
|||
to_dial_number = erp_number.replace(u'\xa0', u' ') |
|||
return to_dial_number |
|||
|
|||
@api.onchange('partner_id') |
|||
def onchange_partner_id(self): |
|||
self.mobile = self.partner_id.mobile |
|||
|
|||
@api.multi |
|||
def send(self): |
|||
for sms in self: |
|||
if not sms.gateway_id._check_permissions(): |
|||
sms.write( |
|||
{'error': 'no permission on gateway', 'state': 'error'}) |
|||
sms._cr.commit() |
|||
return False |
|||
if sms.gateway_id.char_limit and len(sms.message) > 160: |
|||
sms.write({ |
|||
'state': 'error', |
|||
'error': _('Size of SMS should not be more then 160 char'), |
|||
}) |
|||
if not hasattr(sms, "_send_%s" % sms.gateway_id.method): |
|||
#may not exist the gateway |
|||
raise UserError(_("No method gateway selected")) |
|||
else: |
|||
try: |
|||
with sms._cr.savepoint(): |
|||
getattr(sms, "_send_%s" % sms.gateway_id.method)() |
|||
sms.write({'state': 'sent', 'error': ''}) |
|||
except Exception, e: |
|||
_logger.error('Failed to send sms %s', e) |
|||
sms.write({'error': e, 'state': 'error'}) |
|||
sms._cr.commit() |
|||
return True |
|||
|
|||
@api.multi |
|||
def cancel(self): |
|||
self.write({'state': 'cancel'}) |
|||
|
|||
@api.multi |
|||
def retry(self): |
|||
self.write({'state': 'draft'}) |
@ -1,8 +0,0 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<openerp> |
|||
<data> |
|||
<record id="group_sms_user" model="res.groups"> |
|||
<field name="name">SMS / User</field> |
|||
</record> |
|||
</data> |
|||
</openerp> |
@ -1,20 +0,0 @@ |
|||
<?xml version="1.0"?> |
|||
<odoo> |
|||
<record model="ir.ui.view" id="view_server_statistics_graph"> |
|||
<field name="name">ir.actions.server.form.inherit</field> |
|||
<field name="model">ir.actions.server</field> |
|||
<field name="inherit_id" ref="base.view_server_action_form"/> |
|||
<field name="arch" type="xml"> |
|||
<page name="code" position="after" autofocus="autofocus"> |
|||
<page string="SMS" name="sms" attrs="{'invisible': [('state', '!=', 'sms')]}"> |
|||
<group> |
|||
<field name="sms"/> |
|||
<field name="mobile"/> |
|||
<field name="sms_server" invisible="1"/> |
|||
<field name="sms_template_id" domain="[('sms_template','=',True)]" attrs="{'required':[('state','=','sms')]}"/> |
|||
</group> |
|||
</page> |
|||
</page> |
|||
</field> |
|||
</record> |
|||
</odoo> |
@ -1,146 +0,0 @@ |
|||
<?xml version="1.0"?> |
|||
<odoo> |
|||
|
|||
<!-- ************************************************************** --> |
|||
<!-- ** SMS Gateway list ****************************************** --> |
|||
<!-- ************************************************************** --> |
|||
<record model="ir.ui.view" id="sms_gateway_form"> |
|||
<field name="model">sms.gateway</field> |
|||
<field name="priority" eval="8"/> |
|||
<field name="arch" type="xml"> |
|||
<form string="SMS Gateway"> |
|||
<sheet> |
|||
<group col="2"> |
|||
<h1><field name="name" nolabel="1" placeholder="Name" colspan="2"/></h1> |
|||
<field name="method" nolabel="1" placeholder="Method" colspan="2"/> |
|||
<field name="default_gateway"/> |
|||
<field name="company_id" groups="base.group_multi_company"/> |
|||
</group> |
|||
<notebook colspan="4"> |
|||
<page string="General"> |
|||
<group col="4"> |
|||
<field name="state"/> |
|||
<field name="from_provider"/> |
|||
<field name="url"/> |
|||
</group> |
|||
</page> |
|||
<page string="Permission"> |
|||
<separator string="Access Permission" |
|||
colspan="4" /> |
|||
<field name="user_ids" colspan="4" nolabel="1"/> |
|||
</page> |
|||
<page string="Additional option"> |
|||
<group> |
|||
<group> |
|||
<field name="validity" /> |
|||
<field name="classes"/> |
|||
<field name="deferred" /> |
|||
<field name="nostop" /> |
|||
</group> |
|||
<group> |
|||
<field name="priority" /> |
|||
<field name="coding"/> |
|||
<field name="tag"/> |
|||
<field name="char_limit"/> |
|||
</group> |
|||
</group> |
|||
</page> |
|||
</notebook> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.ui.view" id="sms_gateway_tree"> |
|||
<field name="model">sms.gateway</field> |
|||
<field name="priority" eval="8"/> |
|||
<field name="arch" type="xml"> |
|||
<tree string="SMS Gateways"> |
|||
<field name="name"/> |
|||
<field name="method"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.actions.act_window" id="action_sms_gateway_tree"> |
|||
<field name="name">SMS Gateway</field> |
|||
<field name="res_model">sms.gateway</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">form,tree</field> |
|||
<field name="view_id" ref="sms_gateway_tree" /> |
|||
</record> |
|||
|
|||
<menuitem name="SMS Gateway" |
|||
id="menu_gateway_administration_sms_server" |
|||
sequence="100" |
|||
parent="base_phone.menu_config_phone" |
|||
action="action_sms_gateway_tree"/> |
|||
|
|||
<record model="ir.ui.view" id="sms_sms_tree"> |
|||
<field name="model">sms.sms</field> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Sms"> |
|||
<field name="create_date"/> |
|||
<field name="mobile"/> |
|||
<field name="message"/> |
|||
<field name="state"/> |
|||
<field name="gateway_id"/> |
|||
<button string="Send" states="draft" type="object" name="send" icon="gtk-ok"/> |
|||
<button string="Retry" states="error" type="object" name="retry" icon="gtk-redo"/> |
|||
<button string="Cancel" states="draft,error" type="object" name="cancel" icon="terp-gtk-stop"/> |
|||
<field name="state"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.ui.view" id="sms_sms_form"> |
|||
<field name="model">sms.sms</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="Sms"> |
|||
<header> |
|||
<button string="Send" states="draft" type="object" name="send"/> |
|||
<button string="Retry" states="error" type="object" name="retry"/> |
|||
<button string="Cancel" states="draft,error" type="object" name="cancel"/> |
|||
<field name="state" widget="statusbar" statusbar_visible="draft,send"/> |
|||
</header> |
|||
<sheet> |
|||
<label for="partner_id" class="oe_edit_only"/> |
|||
<h1><field name="partner_id"/></h1> |
|||
<label for="mobile" class="oe_edit_only"/> |
|||
<h1><field name="mobile"/></h1> |
|||
<group> |
|||
<field name="create_date" readonly="True"/> |
|||
<field name="gateway_id"/> |
|||
<field name="company_id" groups="base.group_multi_company"/> |
|||
<separator string="SMS Message" colspan="4"/> |
|||
<field name="message" colspan="4" nolabel="1"/> |
|||
<separator string="Last Error" colspan="4"/> |
|||
<field name="error" colspan="4" nolabel="1"/> |
|||
</group> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.actions.act_window" id="action_sms_sms_tree"> |
|||
<field name="name">Sms</field> |
|||
<field name="res_model">sms.sms</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">form,tree</field> |
|||
<field name="view_id" ref="sms_sms_tree" /> |
|||
</record> |
|||
|
|||
<menuitem name="SMS Message" |
|||
id="menu_gateway_administration_sms" |
|||
sequence="110" |
|||
parent="base_phone.menu_config_phone" |
|||
action="action_sms_sms_tree"/> |
|||
|
|||
<act_window context="{'gateway_id': active_id}" |
|||
domain="[('gateway_id', '=', active_id)]" |
|||
id="act_sms_gateway_2_sms" |
|||
name="Sms Message" |
|||
res_model="sms.sms" |
|||
src_model="sms.gateway"/> |
|||
|
|||
</odoo> |
@ -1,23 +0,0 @@ |
|||
<?xml version="1.0"?> |
|||
<openerp> |
|||
<data> |
|||
|
|||
<!-- ************************************************************** --> |
|||
<!-- ** SMS Template ****************************************** --> |
|||
<!-- ************************************************************** --> |
|||
<record model="ir.ui.view" id="email_template_form"> |
|||
<field name="name">email.template.form</field> |
|||
<field name="model">mail.template</field> |
|||
<field name="inherit_id" ref="mail.email_template_form"/> |
|||
<field name="arch" type="xml"> |
|||
<field name="email_to" position="after"> |
|||
<field name="mobile_to"/> |
|||
</field> |
|||
<field name="lang" position="before"> |
|||
<field name="sms_template"/> |
|||
<field name="gateway_id"/> |
|||
</field> |
|||
</field> |
|||
</record> |
|||
</data> |
|||
</openerp> |
@ -1,22 +0,0 @@ |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>) |
|||
# Copyright (C) 2013 Julius Network Solutions SARL <contact@julius.fr> |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/> |
|||
# |
|||
############################################################################## |
|||
|
|||
from . import mass_sms |
@ -1,55 +0,0 @@ |
|||
<?xml version="1.0"?> |
|||
<openerp> |
|||
<data> |
|||
<record model="ir.ui.view" id="view_wizard_send_sms"> |
|||
<field name="model">wizard.send.sms</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="SMS Gateway - Sens SMS" version="7.0"> |
|||
<group string="Gateway" colspan="4"> |
|||
<field name="gateway_id"/> |
|||
</group> |
|||
<notebook> |
|||
<page string="Message"> |
|||
<field name="message" colspan="4" nolabel="1"/> |
|||
<!-- TODO limit to 10 the number of partner to show --> |
|||
<field name="partner_ids" colspan="4" nolabel="1"> |
|||
<tree options="{'limit': 10}"> |
|||
<field name="name"/> |
|||
<field name="mobile"/> |
|||
</tree> |
|||
</field> |
|||
</page> |
|||
<page string="Additional option"> |
|||
<group> |
|||
<group> |
|||
<field name="validity"/> |
|||
<field name="classes"/> |
|||
<field name="deferred"/> |
|||
<field name="nostop"/> |
|||
</group> |
|||
<group> |
|||
<field name="priority"/> |
|||
<field name="coding"/> |
|||
<field name="tag"/> |
|||
</group> |
|||
</group> |
|||
</page> |
|||
</notebook> |
|||
<footer> |
|||
<button string="Send SMS" name="send" type="object" class="oe_highlight"/> |
|||
or |
|||
<button string="Cancel" class="oe_link" special="cancel"/> |
|||
</footer> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<act_window name="Send an SMS" |
|||
res_model="wizard.send.sms" |
|||
src_model="res.partner" |
|||
view_mode="form" |
|||
target="new" |
|||
key2="client_action_multi" |
|||
id="action_wizard_send_sms" /> |
|||
</data> |
|||
</openerp> |
@ -1,45 +0,0 @@ |
|||
# coding: utf-8 |
|||
# Copyright (C) 2015 Sébastien BEAU <sebastien.beau@akretion.com> |
|||
# Valentin CHEMIERE <valentin.chemiere@akretion.com> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
from odoo import models, fields |
|||
from functools import wraps |
|||
|
|||
|
|||
def implemented_by_provider(func): |
|||
"""Decorator: call _provider_prefixed method instead. |
|||
Usage: |
|||
@implemented_by_provider |
|||
def _do_something() |
|||
def _laposte_do_something() |
|||
def _gls_do_something() |
|||
At runtime, sms-client._do_something() will try to call |
|||
the provider spectific method or fallback to generic _do_something |
|||
""" |
|||
@wraps(func) |
|||
def wrapper(cls, *args, **kwargs): |
|||
fun_name = func.__name__ |
|||
fun = '_%s%s' % (cls.provider_type, fun_name) |
|||
if not hasattr(cls, fun): |
|||
fun = '_provider%s' % (fun_name) |
|||
# return func(cls, *args, **kwargs) |
|||
return getattr(cls, fun)(*args, **kwargs) |
|||
return wrapper |
|||
|
|||
|
|||
OVH_KEYCHAIN_NAMESPACE = 'ovh_provider' |
|||
|
|||
|
|||
class AccountProduct(models.Model): |
|||
_inherit = 'keychain.account' |
|||
|
|||
namespace = fields.Selection( |
|||
selection_add=[(OVH_KEYCHAIN_NAMESPACE, 'Ovh_sms')]) |
|||
|
|||
def _ovh_provider_init_data(self): |
|||
return {'sms_account': ""} |
|||
|
|||
def _ovh_provider_validate_data(self, data): |
|||
|
|||
return True |