Commit f83f35e4 authored by Arnaud Fontaine's avatar Arnaud Fontaine

ZODB Components: Migrate ERP5ShortMessage Product and fix pylint warnings.

After upgrading bt5s, portal_sms may still ERP5BaseBroken until restarting Zope.
parent d8961c51
...@@ -40,10 +40,12 @@ from AccessControl.SecurityManagement import getSecurityManager, \ ...@@ -40,10 +40,12 @@ from AccessControl.SecurityManagement import getSecurityManager, \
newSecurityManager newSecurityManager
import zope.interface import zope.interface
from Products.ERP5Type import Permissions, PropertySheet, interfaces from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type.XMLObject import XMLObject from Products.ERP5Type.XMLObject import XMLObject
from Products import ERP5Security from Products import ERP5Security
from erp5.component.interface.ISmsSendingGateway import ISmsSendingGateway
from erp5.component.interface.ISmsReceivingGateway import ISmsReceivingGateway
class DummyGateway(XMLObject): class DummyGateway(XMLObject):
...@@ -56,8 +58,8 @@ class DummyGateway(XMLObject): ...@@ -56,8 +58,8 @@ class DummyGateway(XMLObject):
add_permission = Permissions.AddPortalContent add_permission = Permissions.AddPortalContent
zope.interface.implements( zope.interface.implements(
interfaces.ISmsSendingGateway, ISmsSendingGateway,
interfaces.ISmsReceivingGateway) ISmsReceivingGateway)
# Declarative security # Declarative security
security = ClassSecurityInfo() security = ClassSecurityInfo()
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>DummyGateway</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5ShortMessage.Document.DummyGateway</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.DummyGateway</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -42,14 +42,13 @@ from AccessControl.SecurityManagement import getSecurityManager, \ ...@@ -42,14 +42,13 @@ from AccessControl.SecurityManagement import getSecurityManager, \
import zope.interface import zope.interface
from zLOG import LOG, INFO from zLOG import LOG, INFO
from Products.ERP5Type import Permissions, PropertySheet, interfaces from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type.XMLObject import XMLObject from Products.ERP5Type.XMLObject import XMLObject
from Products import ERP5Security from Products import ERP5Security
#Product Module from erp5.component.module.SMSGatewayError import SMSGatewayError
from Products.ERP5ShortMessage.SMSGatewayError import SMSGatewayError from erp5.component.interface.ISmsSendingGateway import ISmsSendingGateway
from erp5.component.interface.ISmsReceivingGateway import ISmsReceivingGateway
class EssendexGateway(XMLObject): class EssendexGateway(XMLObject):
...@@ -62,8 +61,8 @@ class EssendexGateway(XMLObject): ...@@ -62,8 +61,8 @@ class EssendexGateway(XMLObject):
add_permission = Permissions.AddPortalContent add_permission = Permissions.AddPortalContent
zope.interface.implements( zope.interface.implements(
interfaces.ISmsSendingGateway, ISmsSendingGateway,
interfaces.ISmsReceivingGateway) ISmsReceivingGateway)
# Declarative security # Declarative security
security = ClassSecurityInfo() security = ClassSecurityInfo()
...@@ -330,7 +329,7 @@ class EssendexGateway(XMLObject): ...@@ -330,7 +329,7 @@ class EssendexGateway(XMLObject):
type_mapping = {'Text': 'text/plain'} type_mapping = {'Text': 'text/plain'}
now = DateTime() now = DateTime()
for key, value in result.items(): for key, value in result.items():
if type(key) == int: if isinstance(key, int):
reception_date = self._parseDate(value['ReceivedAt']) reception_date = self._parseDate(value['ReceivedAt'])
#Take only message received more than 10s #Take only message received more than 10s
if self._convertTimeDeltaToSeconds(now - reception_date) > 10: if self._convertTimeDeltaToSeconds(now - reception_date) > 10:
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>EssendexGateway</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5ShortMessage.Document.EssendexGateway</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.EssendexGateway</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2011 Nexedi SA and Contributors. All Rights Reserved.
# Francois-Xavier Algrain <fxalgrain@tiolive.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
"""Receive or send SMS"""
#Import python module
import urllib
from DateTime import DateTime
#Import Zope module
from AccessControl import ClassSecurityInfo
from AccessControl.SecurityManagement import getSecurityManager, \
setSecurityManager, \
newSecurityManager
import zope.interface
from zLOG import LOG, INFO
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type.XMLObject import XMLObject
from Products import ERP5Security
from erp5.component.module.SMSGatewayError import SMSGatewayError
from erp5.component.interface.ISmsSendingGateway import ISmsSendingGateway
from erp5.component.interface.ISmsReceivingGateway import ISmsReceivingGateway
class MobytGateway(XMLObject):
"""Mobyt SMS Gateway Implementation"""
meta_type='Mobyt Gateway'
portal_type = 'Mobyt Gateway'
security = ClassSecurityInfo()
add_permission = Permissions.AddPortalContent
zope.interface.implements(
ISmsSendingGateway,
ISmsReceivingGateway)
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative properi ties
property_sheets = ( PropertySheet.Base
, PropertySheet.XMLObject
, PropertySheet.Reference
, PropertySheet.SMSGateway
)
# see https://web.archive.org/web/20111125005954/http://www.mobyt.fr/doc/mobyt_module_http.pdf
# for documentation of this old API
api_url = "https://multilevel.mobyt.fr/sms"
security.declarePrivate("_fetchSendResponseAsDict")
def _fetchSendResponseAsDict(self,page):
"""Page result is like Key=value in text format.
We transform it to a more powerfull dictionnary"""
result = {}
lines = page.readlines()
assert len(lines) == 1, "Multi lines response is not managed %s" % lines
line = lines[0]
parts = line.split(' ')
#Format is 'Status Message'
result['status'] = parts[0]
result['status_info'] = ' '.join(parts[1:])
return result
security.declarePrivate("_fetchStatusResponseAsDict")
def _fetchStatusResponseAsDict(self,page):
"""Page result is like Key=value in text format.
We transform it to a more powerfull dictionnary"""
result = {}
lines = page.readlines()
#First line is special : CSV column title or error inform
line = lines[0]
if line[0:1] == "KO":
result['status'] = "KO"
result['status_info'] = line[2:]
return result
def _cleanText(s):
return s.replace('\r','').replace('\n','')
column_name_list = line.split(',')
column_count = len(column_name_list)
#Clean last colum
column_name_list[-1] = _cleanText(column_name_list[-1])
result['status'] = "OK"
row_list = []
#Batch other line to get all status
for line in lines[1:]:
row = {}
column_value_list = line.split(',')
column_value_list[-1] = _cleanText(column_value_list[-1])
for i in range(0,column_count):
row[column_name_list[i]] = column_value_list[i]
row_list.append(row)
result['status_info'] = row_list
return result
security.declarePrivate("_transformPhoneUrlToGatewayNumber")
def _transformPhoneUrlToGatewayNumber(self,phone):
"""Transform url of phone number to a valid phone number (gateway side)"""
phone = phone.replace('tel:', '').replace('(0)','').replace('-','')
# Check that phone number can not be something not existing
assert not(phone.startswith('99000'))
return phone
security.declareProtected(Permissions.ManagePortal, 'send')
def send(self, text, recipient, sender):
"""Send a message.
"""
traverse = self.getPortalObject().restrictedTraverse
#Check messsage type
message_type = self.getProperty('mobyt_message_type', 'MULTITEXT')
if message_type not in ('TEXT', 'MULTITEXT', 'WAPPUSH', 'UCS2', 'MULTIUCS2'):
raise ValueError("Type of message in not allowed")
#Check message quality
quality = self.getProperty('mobyt_quality', 'n') #Allow sender personalization and status of SMS
assert quality in ('n','l','ll'), "Unknown quality : '%s'" % quality
#Recipient
recipient = self._transformPhoneUrlToGatewayNumber(
traverse(recipient).getDefaultMobileTelephoneValue().asURL())
base_url = self.api_url + "/send.php"
#Common params
params = { "user" : self.getGatewayUser(),
"pass" : self.getGatewayPassword(),
"rcpt" : recipient,
"data" : text,
"qty" : quality,
"return_id": 1}
if self.isTitleMode():
params['sender'] = traverse(sender).getDefaultMobileTelephoneValue().getTitle()
else:
params['sender'] = self._transformPhoneUrlToGatewayNumber(
traverse(sender).getDefaultMobileTelephoneValue().asURL()) or self.getDefaultSender()
#Define type of message
if message_type != "text":
assert quality == 'n', "This type of message require top level messsage quality"
params['operation'] = message_type
#Send message (or test)
if self.isSimulationMode():
LOG("MobytGateway", INFO, params)
result = {'status': "Test"}
else:
params = urllib.urlencode(params)
page = urllib.urlopen(base_url, params)
result = self._fetchSendResponseAsDict(page)
#Check result and return
if result['status'] == "OK":
return [result.get('status_info', "")] #return message id (gateway side)
elif result['status'] == "KO":
#we get an error when call the gateway
raise SMSGatewayError, urllib.unquote(result.get('status_info', "Impossible to send the SMS"))
elif result['status'] == "Test":
#just a test, no message id
return None
else:
raise ValueError("Unknown result", 0, result)
security.declareProtected(Permissions.ManagePortal, 'getMessageStatus')
def getMessageStatus(self, message_id):
"""Retrive the status of a message"""
base_url = self.api_url + "/batch-status.php"
params = { "user" : self.getGatewayUser(),
"pass" : self.getGatewayPassword(),
"id" : message_id,
"type" : 'notify',
"schema" : 1 }
params = urllib.urlencode(params)
page = urllib.urlopen(base_url, params)
result = self._fetchStatusResponseAsDict(page)
if result['status'] == "OK":
row_list = result.get('status_info')
#return only status_text list
if len(row_list) == 1:
return row_list[0].get('status_text').lower()
else:
status_list = []
for row in row_list:
status_list.append(row.get('status_text').lower())
return status_list
elif result['status'] == "KO":
#we get an error when call the gateway
raise SMSGatewayError, urllib.unquote(result.get('status_info', "Impossible to get the message status"))
security.declarePublic('receive')
def receive(self,REQUEST):
"""Receive push notification from the gateway"""
#Get current user
sm = getSecurityManager()
try:
#Use SUPER_USER
portal_membership = self.getPortalObject().portal_membership
newSecurityManager(None, portal_membership.getMemberById(ERP5Security.SUPER_USER))
#Mobyt notify only new SMS
self.notifyReception(REQUEST.get("orig"),
REQUEST.get("text"),
REQUEST.get("ticket"))
finally:
#Restore orinal user
setSecurityManager(sm)
security.declareProtected(Permissions.ManagePortal, 'notifyReception')
def notifyReception(self, sender, text, message_id):
"""The gateway inform what we ha a new message.
"""
#Convert phone as erp5 compliant
def parsePhoneNumber(number):
#XXX: Should register well formatted number or brut number ?
#return number
return "+%s(%s)-%s" % (number[0:2],0,number[2:])
#Create the new sms in activities
self.activate(activity='SQLQueue').SMSTool_pushNewSMS(
message_id=message_id,
sender=parsePhoneNumber(sender),
recipient=None,
text_content=text,
message_type='text/plain',
reception_date=DateTime())
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>MobytGateway</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5ShortMessage.Document.MobytGateway</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.MobytGateway</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Interface Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>ISmsReceivingGateway</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5ShortMessage.interfaces.sms_receiving_gateway</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>interface.erp5.ISmsReceivingGateway</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Interface Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Interface Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>ISmsSendingGateway</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5ShortMessage.interfaces.sms_sending_gateway</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>interface.erp5.ISmsSendingGateway</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Interface Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SMSGatewayError</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5ShortMessage.SMSGatewayError</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.SMSGatewayError</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -27,33 +27,23 @@ ...@@ -27,33 +27,23 @@
############################################################################## ##############################################################################
import unittest import unittest
import os
from zope.interface.verify import verifyObject from zope.interface.verify import verifyObject
from DateTime import DateTime
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
class ShortMessageTestCase(ERP5TypeTestCase): class ShortMessageTestCase(ERP5TypeTestCase):
pass
def getBusinessTemplateList(self):
return ('erp5_full_text_mroonga_catalog',
'erp5_core_proxy_field_legacy',
'erp5_base',
'erp5_crm',
'erp5_short_message'
)
class TestShortMessageGateway(ShortMessageTestCase): class TestShortMessageGateway(ShortMessageTestCase):
def _verifyGatewayPortalType(self, portal_type): def _verifyGatewayPortalType(self, portal_type):
import Products.ERP5Type.interfaces
gateway = self.portal.portal_sms.newContent(portal_type=portal_type) gateway = self.portal.portal_sms.newContent(portal_type=portal_type)
verifyObject(Products.ERP5Type.interfaces.ISmsSendingGateway, gateway) from erp5.component.interface.ISmsSendingGateway import ISmsSendingGateway
verifyObject(Products.ERP5Type.interfaces.ISmsReceivingGateway, gateway) verifyObject(ISmsSendingGateway, gateway)
from erp5.component.interface.ISmsReceivingGateway import ISmsReceivingGateway
verifyObject(ISmsReceivingGateway, gateway)
def test_EssendexGateway(self): def test_EssendexGateway(self):
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Test Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>testShortMessage</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5ShortMessage.tests.testShortMessage</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>test.erp5.testShortMessage</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Test Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -31,8 +31,7 @@ from AccessControl import ClassSecurityInfo ...@@ -31,8 +31,7 @@ from AccessControl import ClassSecurityInfo
from Products.ERP5Type.Tool.BaseTool import BaseTool from Products.ERP5Type.Tool.BaseTool import BaseTool
from Products.ERP5Type.Permissions import ManagePortal from Products.ERP5Type.Permissions import ManagePortal
from Products.ERP5Type.Globals import DTMLFile #from Products.ERP5ShortMessage import _dtmldir
from Products.ERP5ShortMessage import _dtmldir
class SMSTool(BaseTool): class SMSTool(BaseTool):
""" """
...@@ -47,7 +46,7 @@ class SMSTool(BaseTool): ...@@ -47,7 +46,7 @@ class SMSTool(BaseTool):
# Declarative Security # Declarative Security
security = ClassSecurityInfo() security = ClassSecurityInfo()
security.declareProtected(ManagePortal, 'manage_overview') security.declareProtected(ManagePortal, 'manage_overview')
manage_overview = DTMLFile('explainSMSTool', _dtmldir ) #manage_overview = DTMLFile('explainSMSTool', _dtmldir )
security.declareProtected(ManagePortal, 'send') security.declareProtected(ManagePortal, 'send')
def send(self, text, recipient, sender, gateway_reference='default', def send(self, text, recipient, sender, gateway_reference='default',
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Tool Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SMSTool</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5ShortMessage.Tool.SMSTool</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>tool.erp5.SMSTool</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Tool Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
document.erp5.DummyGateway
document.erp5.EssendexGateway
document.erp5.MobytGateway
\ No newline at end of file
interface.erp5.ISmsReceivingGateway
interface.erp5.ISmsSendingGateway
\ No newline at end of file
module.erp5.SMSGatewayError
\ No newline at end of file
test.erp5.testShortMessage
\ No newline at end of file
tool.erp5.SMSTool
\ No newline at end of file
erp5_full_text_mroonga_catalog
\ No newline at end of file
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2011 Nexedi SA and Contributors. All Rights Reserved.
# Francois-Xavier Algrain <fxalgrain@tiolive.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
"""Receive or send SMS"""
#Import python module
import urllib
from DateTime import DateTime
#Import Zope module
from AccessControl import ClassSecurityInfo
from AccessControl.SecurityManagement import getSecurityManager, \
setSecurityManager, \
newSecurityManager
import zope.interface
from zLOG import LOG, INFO
from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5Type.XMLObject import XMLObject
from Products import ERP5Security
#Product Module
from Products.ERP5ShortMessage.SMSGatewayError import SMSGatewayError
class MobytGateway(XMLObject):
"""Mobyt SMS Gateway Implementation"""
meta_type='Mobyt Gateway'
portal_type = 'Mobyt Gateway'
security = ClassSecurityInfo()
add_permission = Permissions.AddPortalContent
zope.interface.implements(
interfaces.ISmsSendingGateway,
interfaces.ISmsReceivingGateway)
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative properi ties
property_sheets = ( PropertySheet.Base
, PropertySheet.XMLObject
, PropertySheet.Reference
, PropertySheet.SMSGateway
)
# see https://web.archive.org/web/20111125005954/http://www.mobyt.fr/doc/mobyt_module_http.pdf
# for documentation of this old API
api_url = "https://multilevel.mobyt.fr/sms"
security.declarePrivate("_fetchSendResponseAsDict")
def _fetchSendResponseAsDict(self,page):
"""Page result is like Key=value in text format.
We transform it to a more powerfull dictionnary"""
result = {}
lines = page.readlines()
assert len(lines) == 1, "Multi lines response is not managed %s" % lines
line = lines[0]
parts = line.split(' ')
#Format is 'Status Message'
result['status'] = parts[0]
result['status_info'] = ' '.join(parts[1:])
return result
security.declarePrivate("_fetchStatusResponseAsDict")
def _fetchStatusResponseAsDict(self,page):
"""Page result is like Key=value in text format.
We transform it to a more powerfull dictionnary"""
result = {}
lines = page.readlines()
#First line is special : CSV column title or error inform
line = lines[0]
if line[0:1] == "KO":
result['status'] = "KO"
result['status_info'] = line[2:]
return result
def _cleanText(s):
return s.replace('\r','').replace('\n','')
column_name_list = line.split(',')
column_count = len(column_name_list)
#Clean last colum
column_name_list[-1] = _cleanText(column_name_list[-1])
result['status'] = "OK"
row_list = []
#Batch other line to get all status
for line in lines[1:]:
row = {}
column_value_list = line.split(',')
column_value_list[-1] = _cleanText(column_value_list[-1])
for i in range(0,column_count):
row[column_name_list[i]] = column_value_list[i]
row_list.append(row)
result['status_info'] = row_list
return result
security.declarePrivate("_transformPhoneUrlToGatewayNumber")
def _transformPhoneUrlToGatewayNumber(self,phone):
"""Transform url of phone number to a valid phone number (gateway side)"""
phone = phone.replace('tel:', '').replace('(0)','').replace('-','')
# Check that phone number can not be something not existing
assert not(phone.startswith('99000'))
return phone
security.declareProtected(Permissions.ManagePortal, 'send')
def send(self, text, recipient, sender):
"""Send a message.
"""
traverse = self.getPortalObject().restrictedTraverse
#Check messsage type
message_type = self.getProperty('mobyt_message_type', 'MULTITEXT')
if message_type not in ('TEXT', 'MULTITEXT', 'WAPPUSH', 'UCS2', 'MULTIUCS2'):
raise ValueError("Type of message in not allowed")
#Check message quality
quality = self.getProperty('mobyt_quality', 'n') #Allow sender personalization and status of SMS
assert quality in ('n','l','ll'), "Unknown quality : '%s'" % quality
#Recipient
recipient = self._transformPhoneUrlToGatewayNumber(
traverse(recipient).getDefaultMobileTelephoneValue().asURL())
base_url = self.api_url + "/send.php"
#Common params
params = { "user" : self.getGatewayUser(),
"pass" : self.getGatewayPassword(),
"rcpt" : recipient,
"data" : text,
"qty" : quality,
"return_id": 1}
if self.isTitleMode():
params['sender'] = traverse(sender).getDefaultMobileTelephoneValue().getTitle()
else:
params['sender'] = self._transformPhoneUrlToGatewayNumber(
traverse(sender).getDefaultMobileTelephoneValue().asURL()) or self.getDefaultSender()
#Define type of message
if message_type != "text":
assert quality == 'n', "This type of message require top level messsage quality"
params['operation'] = message_type
#Send message (or test)
if self.isSimulationMode():
LOG("MobytGateway", INFO, params)
result = {'status': "Test"}
else:
params = urllib.urlencode(params)
page = urllib.urlopen(base_url, params)
result = self._fetchSendResponseAsDict(page)
#Check result and return
if result['status'] == "OK":
return [result.get('status_info', "")] #return message id (gateway side)
elif result['status'] == "KO":
#we get an error when call the gateway
raise SMSGatewayError, urllib.unquote(result.get('status_info', "Impossible to send the SMS"))
elif result['status'] == "Test":
#just a test, no message id
return None
else:
raise ValueError("Unknown result", 0, result)
security.declareProtected(Permissions.ManagePortal, 'getMessageStatus')
def getMessageStatus(self, message_id):
"""Retrive the status of a message"""
base_url = self.api_url + "/batch-status.php"
params = { "user" : self.getGatewayUser(),
"pass" : self.getGatewayPassword(),
"id" : message_id,
"type" : 'notify',
"schema" : 1 }
params = urllib.urlencode(params)
page = urllib.urlopen(base_url, params)
result = self._fetchStatusResponseAsDict(page)
if result['status'] == "OK":
row_list = result.get('status_info')
#return only status_text list
if len(row_list) == 1:
return row_list[0].get('status_text').lower()
else:
status_list = []
for row in row_list:
status_list.append(row.get('status_text').lower())
return status_list
elif result['status'] == "KO":
#we get an error when call the gateway
raise SMSGatewayError, urllib.unquote(result.get('status_info', "Impossible to get the message status"))
security.declarePublic('receive')
def receive(self,REQUEST):
"""Receive push notification from the gateway"""
#Get current user
sm = getSecurityManager()
try:
#Use SUPER_USER
portal_membership = self.getPortalObject().portal_membership
newSecurityManager(None, portal_membership.getMemberById(ERP5Security.SUPER_USER))
#Mobyt notify only new SMS
self.notifyReception(REQUEST.get("orig"),
REQUEST.get("text"),
REQUEST.get("ticket"))
finally:
#Restore orinal user
setSecurityManager(sm)
security.declareProtected(Permissions.ManagePortal, 'notifyReception')
def notifyReception(self, sender, text, message_id):
"""The gateway inform what we ha a new message.
"""
#Convert phone as erp5 compliant
def parsePhoneNumber(number):
#XXX: Should register well formatted number or brut number ?
#return number
return "+%s(%s)-%s" % (number[0:2],0,number[2:])
#Create the new sms in activities
self.activate(activity='SQLQueue').SMSTool_pushNewSMS(
message_id=message_id,
sender=parsePhoneNumber(sender),
recipient=None,
text_content=text,
message_type='text/plain',
reception_date=DateTime())
##############################################################################
#
# Copyright (c) 2010 Nexedi SA and Contributors. All Rights Reserved.
# Francois-Xavier Algrain <fxalgrain@tiolive.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
# This file is kept for backward compatibility only
from Products.ERP5ShortMessage.SMSGatewayError import SMSGatewayError
##############################################################################
#
# Copyright (c) 2010 Nexedi SA and Contributors. All Rights Reserved.
# Francois-Xavier Algrain <fxalgrain@tiolive.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
\ No newline at end of file
ERP5ShortMessage
The ERP5ShortMessage product provides support for sending or receiving SMS from
within the Zope environment.
##############################################################################
#
# Copyright (c) 2010 Nexedi SA and Contributors. All Rights Reserved.
# Francois-Xavier Algrain <fxalgrain@tiolive.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
"""
ERP5ShortMessage is a product containing everything needed to implement
Short Message management in ERP5.
"""# Update ERP5 Globals
from Products.ERP5Type.Utils import initializeProduct, updateGlobals
import sys, Permissions
this_module = sys.modules[ __name__ ]
document_classes = updateGlobals(this_module, globals(),
permissions_module=Permissions)
from Tool import SMSTool
# Define object classes and tools
object_classes = ()
portal_tools = (SMSTool.SMSTool,
)
content_classes = ()
content_constructors = ()
# Finish installation
def initialize(context):
import Document
initializeProduct(context, this_module, globals(),
document_module=Document,
document_classes=document_classes,
object_classes=object_classes,
portal_tools=portal_tools,
content_constructors=content_constructors,
content_classes=content_classes)
from AccessControl.SecurityInfo import allow_module
allow_module('Products.ERP5ShortMessage.Errors')
<dtml-var manage_page_header>
<dtml-var manage_tabs>
<h3>Explain SMS Tool</h3>
<p>
SMS Tool provides all to send and receive sms with one or more sms gateway.
</p>
<p>
You need to have a SMS Gateway with reference egal to "default" to send sms.
Other reference can be used for specific send.
</p>
<dtml-var manage_page_footer>
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2010 Nexedi SA and Contributors. All Rights Reserved.
# François-Xavier Algrain <fxalgrain@tiolive.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
# This file has been kept for backward compatiblity only
from Products.ERP5ShortMessage.interfaces.sms_receiving_gateway import ISmsReceivingGateway
from Products.ERP5ShortMessage.interfaces.sms_sending_gateway import ISmsSendingGateway
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment