remove support for clicrdv (#5484)

This commit is contained in:
Frédéric Péters 2019-11-26 14:00:58 +01:00
parent caff073548
commit 813372abb3
3 changed files with 1 additions and 423 deletions

View File

@ -23,7 +23,7 @@ from .abelium_domino_ui import AbeliumDominoDirectory
class PanelDirectory(Directory):
_q_exports = ['', 'update', 'announces', 'permissions',
'announce_themes', 'strongbox', 'clicrdv', 'domino']
'announce_themes', 'strongbox', 'domino']
label = N_('Control Panel')
domino = AbeliumDominoDirectory()
@ -160,60 +160,6 @@ class PanelDirectory(Directory):
cfg_submit(form, 'misc', ('aq-strongbox',))
return redirect('..')
def clicrdv(self):
if not get_publisher().has_site_option('clicrdv'):
raise errors.TraversalError()
misc_cfg = get_cfg('misc', {})
form = Form(enctype='multipart/form-data')
form.add(SingleSelectWidget, 'aq-clicrdv-server', title=_('ClicRDV Server'),
value=misc_cfg.get('aq-clicrdv-server', 'sandbox.clicrdv.com'), required=True,
options=[(str('www.clicrdv.com'), _('Production Server')),
(str('sandbox.clicrdv.com'), _('Sandbox Server'))])
form.add(StringWidget, 'aq-clicrdv-api-key', title=_('API Key'),
value=misc_cfg.get('aq-clicrdv-api-key'), required=False,
size=40, hint=_('Empty to disable ClicRDV support'))
form.add(StringWidget, 'aq-clicrdv-api-username', title=_('Username'),
value=misc_cfg.get('aq-clicrdv-api-username'), required=False)
form.add(StringWidget, 'aq-clicrdv-api-password', title=_('Password'),
value=misc_cfg.get('aq-clicrdv-api-password'), required=False)
form.add_submit('submit', _('Submit'))
form.add_submit('cancel', _('Cancel'))
if form.get_widget('cancel').parse():
return redirect('..')
if not form.is_submitted() or form.has_errors():
get_response().breadcrumb.append(('aq/clicrdv', _('ClicRDV Integration')))
html_top('settings', _('ClicRDV Integration'))
r = TemplateIO(html=True)
r += htmltext('<h2>%s</h2>') % _('ClicRDV Integration')
r += form.render()
r += htmltext('<p>%s</p>') % _('Available Interventions: ')
try:
from clicrdv import get_all_intervention_sets
intervention_sets = get_all_intervention_sets()
r += htmltext('<ul>')
for s in intervention_sets:
r += htmltext('<li><strong>clicrdv_get_interventions_in_set(%s)</strong> - %s') % (
s['id'], s['name'])
r += htmltext('<ul>')
for n, intervention in s['interventions']:
r += htmltext('<li>%s (id: %s)</li>') % (intervention, n)
r += htmltext('</ul></li>')
r += htmltext('</ul>')
except Exception, e:
r += htmltext('<p>%s (%s)</p>') % (
_('Cannot access to ClicRDV service'), str(e))
return r.getvalue()
else:
from wcs.admin.settings import cfg_submit
cfg_submit(form, 'misc', ('aq-clicrdv-server',
'aq-clicrdv-api-key',
'aq-clicrdv-api-username',
'aq-clicrdv-api-password'))
return redirect('..')
class SettingsDirectory(wcs.admin.settings.SettingsDirectory):
def _q_index(self):
@ -234,8 +180,6 @@ class SettingsDirectory(wcs.admin.settings.SettingsDirectory):
r += htmltext('<li><a href="aq/announce_themes">%s</a></li>') % _('Announce Themes')
if get_publisher().has_site_option('strongbox'):
r += htmltext('<li><a href="aq/strongbox">%s</a></li>') % _('Strongbox Support')
if get_publisher().has_site_option('clicrdv'):
r += htmltext('<li><a href="aq/clicrdv">%s</a></li>') % _('ClicRDV Integration')
if get_publisher().has_site_option('domino'):
r += htmltext('<li><a href="aq/domino">%s</a></li>') % _('Abelium Domino Integration')
r += htmltext('</ul>')

View File

@ -1,365 +0,0 @@
import base64
import datetime
import urllib2
try:
import json
except ImportError:
import simplejson as json
import time
import vobject
from wcs.qommon import _
from wcs.qommon import get_cfg
from wcs.qommon.misc import format_time
from wcs.qommon.form import *
from wcs.data_sources import register_data_source_function
from wcs.formdata import Evolution
from wcs.forms.common import FormStatusPage
from wcs.workflows import Workflow, WorkflowStatusItem, register_item_class
def get_clicrdv_req(url):
misc_cfg = get_cfg('misc', {})
url = 'https://%s/api/v1/%s' % (
misc_cfg.get('aq-clicrdv-server', 'sandbox.clicrdv.com'), url)
if '?' in url:
url = url + '&apikey=%s&format=json' % misc_cfg.get('aq-clicrdv-api-key')
else:
url = url + '?apikey=%s&format=json' % misc_cfg.get('aq-clicrdv-api-key')
req = urllib2.Request(url)
username = misc_cfg.get('aq-clicrdv-api-username')
password = misc_cfg.get('aq-clicrdv-api-password')
authheader = 'Basic ' + base64.encodestring('%s:%s' % (username, password))[:-1]
req.add_header('Authorization', authheader)
return req
def get_json(url):
return json.load(urllib2.urlopen(get_clicrdv_req(url)))
def as_str(s):
if type(s) is unicode:
return s.encode(get_publisher().site_charset)
return s
def get_all_intervention_sets():
interventions_set = []
for interventionset in sorted(get_json('interventionsets').get('records'),
lambda x,y: cmp(x['sort'],y['sort'])):
interventions = []
for intervention in sorted(get_json('interventionsets/%s/interventions' % interventionset.get('id')).get('records'),
lambda x,y: cmp(x['sort'], y['sort'])):
if intervention.get('deleted') == True:
continue
name = '%s' % as_str(intervention.get('publicname'))
if not name:
name = '%s' % as_str(intervention.get('name'))
interventions.append((intervention.get('id'), as_str(name)))
interventions_set.append({
'id': interventionset.get('id'),
'group_id': interventionset.get('group_id'),
'name': as_str(interventionset.get('name')),
'publicname': as_str(interventionset.get('publicname')) or '',
'description': as_str(interventionset.get('description')) or '',
'interventions': interventions
})
return interventions_set
def get_all_interventions():
interventions = []
for s in get_all_intervention_sets():
for i, publicname in s['interventions']:
intervention_label = '%s - %s' % (s['publicname'], publicname)
interventions.append((i, as_str(intervention_label)))
return interventions
def get_interventions_in_set(interventionset_id):
interventions = []
interventions_json = get_json('interventionsets/%s/interventions' % interventionset_id)
for intervention in interventions_json.get('records'):
if intervention.get('deleted') != True:
name = '%s' % as_str(intervention.get('publicname'))
if not name:
name = '%s' % as_str(intervention.get('name'))
interventions.append((intervention.get('id'), name))
return interventions
def get_available_timeslots(intervention, date_start=None, date_end=None):
timeslots = []
iid = intervention
gid = get_json('interventions/%s' % iid).get('group_id')
request_url = 'availabletimeslots?intervention_ids[]=%s&group_id=%s' % (iid, gid)
if date_start is None:
date_start = datetime.datetime.today().strftime('%Y-%m-%d')
if date_end is None:
date_end = (datetime.datetime.today() + datetime.timedelta(366)).strftime('%Y-%m-%d')
if date_start:
request_url = request_url + '&start=%s' % urllib2.quote(date_start)
if date_end:
request_url = request_url + '&end=%s' % urllib2.quote(date_end)
for timeslot in get_json(request_url).get('availabletimeslots'):
timeslots.append(timeslot.get('start'))
timeslots.sort()
return timeslots
def get_available_dates(intervention):
dates = []
for timeslot in get_available_timeslots(intervention):
parsed = time.strptime(timeslot, '%Y-%m-%d %H:%M:%S')
date_tuple = (time.strftime('%Y-%m-%d', parsed),
format_time(parsed, '%(weekday_name)s %(day)0.2d/%(month)0.2d/%(year)s'))
if date_tuple in dates:
continue
dates.append(date_tuple)
return dates
def get_available_times(intervention, date):
times = []
timeslots = get_available_timeslots(intervention,
date_start='%s 00:00:00' % date,
date_end='%s 23:59:59' % date)
for timeslot in timeslots:
parsed = time.strptime(timeslot, '%Y-%m-%d %H:%M:%S')
time_tuple = (time.strftime('%H:%M:%S', parsed),
time.strftime('%Hh%M', parsed))
times.append(time_tuple)
times.sort()
return times
register_data_source_function(get_all_interventions, 'clicrdv_get_all_interventions')
register_data_source_function(get_interventions_in_set, 'clicrdv_get_interventions_in_set')
register_data_source_function(get_available_dates, 'clicrdv_get_available_dates')
register_data_source_function(get_available_times, 'clicrdv_get_available_times')
def form_download_event(self):
self.check_receiver()
found = False
for evo in self.filled.evolution:
if evo.parts:
for p in evo.parts:
if not isinstance(p, AppointmentPart):
continue
cal = vobject.iCalendar()
cal.add('prodid').value = '-//Entr\'ouvert//NON SGML Publik'
vevent = vobject.newFromBehavior('vevent')
vevent.add('uid').value = 'clicrdv-%s' % p.id
vevent.add('summary').value = p.json_dict.get('group_name')
vevent.add('dtstart').value = datetime.datetime.strptime(
p.json_dict.get('start'), '%Y-%m-%d %H:%M:%S')
vevent.add('dtend').value = datetime.datetime.strptime(
p.json_dict.get('end'), '%Y-%m-%d %H:%M:%S')
vevent.add('location').value = p.json_dict.get('location')
cal.add(vevent)
response = get_response()
response.set_content_type('text/calendar')
return cal.serialize()
raise TraversalError()
class AppointmentPart(object):
def __init__(self, json_dict):
self.id = json_dict.get('id')
self.json_dict = json_dict
def view(self):
return htmltext('<p class="appointment"><a href="clicrdvevent">%s</a></p>' % (
_('Download Appointment')))
class AppointmentErrorPart(object):
def __init__(self, msg):
self.msg = msg
def view(self):
return htmltext('<p class="appointment-error">%s</p>' % str(self.msg))
class ClicRdvCreateAppointment(WorkflowStatusItem):
description = N_('Create a ClicRDV Appointment')
key = 'clicrdv-create'
category = 'interaction'
endpoint = False
var_firstname = None
var_lastname = None
var_email = None
var_firstphone = None
var_secondphone = None
var_datetime = None
var_intervention_id = None
status_on_success = None
status_on_failure = None
def init(cls):
FormStatusPage._q_extra_exports.append('clicrdvevent')
FormStatusPage.clicrdvevent = form_download_event
init = classmethod(init)
def is_available(self, workflow=None):
return get_publisher().has_site_option('clicrdv')
is_available = classmethod(is_available)
def render_as_line(self):
return _('Create an appointment in ClicRDV')
def get_parameters(self):
return ('var_firstname', 'var_lastname', 'var_email', 'var_firstphone',
'var_secondphone', 'var_datetime', 'var_intervention_id',
'status_on_success', 'status_on_failure')
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
parameter_labels = {
'var_firstname': N_('First Name'),
'var_lastname': N_('Last Name'),
'var_email': N_('Email'),
'var_firstphone': N_('Phone (1st)'),
'var_secondphone': N_('Phone (2nd)'),
'var_datetime': N_('Date/time'),
'var_intervention_id': N_('Intervention Id'),
}
for parameter in self.get_parameters():
if not parameter in parameter_labels:
continue
if parameter in parameters:
form.add(StringWidget, '%s%s' % (prefix, parameter),
title=_(parameter_labels.get(parameter)),
value=getattr(self, parameter),
required=False)
if 'status_on_success' in parameters:
form.add(SingleSelectWidget, '%sstatus_on_success' % prefix,
title=_('Status On Success'), value=self.status_on_success,
options = [(None, '---')] + [(x.id, x.name) for x in self.parent.parent.possible_status])
if 'status_on_failure' in parameters:
form.add(SingleSelectWidget, '%sstatus_on_failure' % prefix,
title=_('Status On Failure'), value=self.status_on_failure,
options = [(None, '---')] + [(x.id, x.name) for x in self.parent.parent.possible_status])
def perform(self, formdata):
args = {}
for parameter in self.get_parameters():
args[parameter] = self.compute(getattr(self, parameter))
if not args.get(parameter):
del args[parameter]
message = {'appointment':
{'fiche': {'firstname': args.get('var_firstname', '-'),
'lastname': args.get('var_lastname', '-'),
'email': args.get('var_email'),
'firstphone': args.get('var_firstphone'),
'secondphone': args.get('var_secondphone'),
},
'date': args.get('var_datetime'),
'intervention_ids': [int(args.get('var_intervention_id'))],
# 'comments': '-',
'websource': 'Publik'}
}
req = get_clicrdv_req('appointments')
req.add_data(json.dumps(message))
req.add_header('Content-Type', 'application/json')
try:
fd = urllib2.urlopen(req)
except urllib2.HTTPError, e:
success = False
try:
msg = json.load(e.fp)[0].get('error')
except:
msg = _('unknown error')
if formdata.evolution:
evo = formdata.evolution[-1]
else:
formdata.evolution = []
evo = Evolution()
evo.time = time.localtime()
evo.status = formdata.status
formdata.evolution.append(evo)
evo.add_part(AppointmentErrorPart(msg))
else:
success = True
response = json.load(fd)
appointment_id = response.get('records')[0].get('id')
# add a message in formdata.evolution
if formdata.evolution:
evo = formdata.evolution[-1]
else:
formdata.evolution = []
evo = Evolution()
evo.time = time.localtime()
evo.status = formdata.status
formdata.evolution.append(evo)
evo.add_part(AppointmentPart(response.get('records')[0]))
formdata.store()
if (success and self.status_on_success) or (success is False and self.status_on_failure):
if success:
formdata.status = 'wf-%s' % self.status_on_success
else:
formdata.status = 'wf-%s' % self.status_on_failure
register_item_class(ClicRdvCreateAppointment)
class ClicRdvCancelAppointment(WorkflowStatusItem):
description = N_('Cancel a ClicRDV Appointment')
key = 'clicrdv-cancel'
category = 'interaction'
endpoint = False
status_on_success = None
status_on_failure = None
def get_parameters(self):
return ('status_on_success', 'status_on_failure')
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
if 'status_on_success' in parameters:
form.add(SingleSelectWidget, '%sstatus_on_success' % prefix,
title=_('Status On Success'), value=self.status_on_success,
options = [(None, '---')] + [(x.id, x.name) for x in self.parent.parent.possible_status])
if 'status_on_failure' in parameters:
form.add(SingleSelectWidget, '%sstatus_on_failure' % prefix,
title=_('Status On Failure'), value=self.status_on_failure,
options = [(None, '---')] + [(x.id, x.name) for x in self.parent.parent.possible_status])
def is_available(self, workflow=None):
return get_publisher().has_site_option('clicrdv')
is_available = classmethod(is_available)
def render_as_line(self):
return _('Cancel an appointment in ClicRDV')
def perform(self, formdata):
success = True
for evo in [evo for evo in formdata.evolution if evo.parts]:
for part in [part for part in evo.parts if isinstance(part, AppointmentPart)]:
appointment_id = part.id
try:
req = get_clicrdv_req('appointments/%s' % appointment_id)
req.get_method = (lambda: 'DELETE')
fd = urllib2.urlopen(req)
none = fd.read()
except urllib2.URLError:
# clicrdv will return a "Bad Request" (HTTP 400) response
# when it's not possible to remove an appointment
# (for example because it's too late)
success = False
if (success and self.status_on_success) or (success is False and self.status_on_failure):
if success:
formdata.status = 'wf-%s' % self.status_on_success
else:
formdata.status = 'wf-%s' % self.status_on_failure
register_item_class(ClicRdvCancelAppointment)

View File

@ -1,2 +1 @@
from . import clicrdv
from . import abelium_domino_workflow