173 lines
5.4 KiB
Python
173 lines
5.4 KiB
Python
# lingo - payment and billing system
|
|
# Copyright (C) 2022 Entr'ouvert
|
|
#
|
|
# 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/>.
|
|
|
|
import json
|
|
|
|
from django.conf import settings
|
|
from django.utils.translation import ugettext_lazy as _
|
|
from requests.exceptions import RequestException
|
|
|
|
from lingo.agendas.models import Agenda
|
|
from lingo.utils import requests
|
|
|
|
|
|
class ChronoError(Exception):
|
|
pass
|
|
|
|
|
|
def is_chrono_enabled():
|
|
return hasattr(settings, 'KNOWN_SERVICES') and settings.KNOWN_SERVICES.get('chrono')
|
|
|
|
|
|
def get_chrono_service():
|
|
if not is_chrono_enabled():
|
|
return {}
|
|
return list(settings.KNOWN_SERVICES.get('chrono').values())[0]
|
|
|
|
|
|
def get_chrono_json(path, params=None, log_errors=True):
|
|
chrono_site = get_chrono_service()
|
|
if chrono_site is None:
|
|
return
|
|
try:
|
|
response = requests.get(
|
|
path,
|
|
params=params or {},
|
|
remote_service=chrono_site,
|
|
without_user=True,
|
|
headers={'accept': 'application/json'},
|
|
log_errors=log_errors,
|
|
)
|
|
response.raise_for_status()
|
|
except RequestException as e:
|
|
if e.response is not None:
|
|
try:
|
|
# return json if available (on 404 responses by example)
|
|
return e.response.json()
|
|
except json.JSONDecodeError:
|
|
pass
|
|
return
|
|
return response.json()
|
|
|
|
|
|
def collect_agenda_data():
|
|
result = get_chrono_json('api/agenda/')
|
|
if result is None:
|
|
return
|
|
if result.get('data') is None:
|
|
return
|
|
|
|
agenda_data = []
|
|
for agenda in result['data']:
|
|
if agenda['kind'] != 'events':
|
|
continue
|
|
agenda_data.append(
|
|
{
|
|
'slug': agenda['slug'],
|
|
'label': agenda['text'],
|
|
'category_slug': agenda['category'],
|
|
'category_label': agenda['category_label'],
|
|
}
|
|
)
|
|
return agenda_data
|
|
|
|
|
|
def refresh_agendas():
|
|
result = collect_agenda_data()
|
|
if result is None:
|
|
return
|
|
|
|
# fetch existing agendas
|
|
existing_agendas = {a.slug: a for a in Agenda.objects.all()}
|
|
seen_agendas = []
|
|
|
|
# build agendas from chrono
|
|
for agenda_data in result:
|
|
slug = agenda_data['slug']
|
|
agenda = existing_agendas.get(slug) or Agenda(slug=slug)
|
|
for key, value in agenda_data.items():
|
|
if key == 'slug':
|
|
continue
|
|
setattr(agenda, key, value)
|
|
agenda.save()
|
|
seen_agendas.append(agenda.slug)
|
|
|
|
# now check outdated agendas
|
|
for slug, agenda in existing_agendas.items():
|
|
if slug not in seen_agendas:
|
|
agenda.delete()
|
|
|
|
|
|
def get_event(event_slug):
|
|
return get_events(
|
|
[event_slug],
|
|
error_message=_('Unable to get event details'),
|
|
error_message_with_details=_('Unable to get event details (%s)'),
|
|
)[0]
|
|
|
|
|
|
def get_events(event_slugs, error_message=None, error_message_with_details=None):
|
|
error_message = error_message or _('Unable to get events details')
|
|
error_message_with_details = error_message_with_details or _('Unable to get events details (%s)')
|
|
result = get_chrono_json('api/agendas/events/', params={'slots': event_slugs})
|
|
if not result:
|
|
raise ChronoError(error_message)
|
|
if result.get('err'):
|
|
raise ChronoError(error_message_with_details % result['err_desc'])
|
|
if not result.get('data'):
|
|
raise ChronoError(error_message)
|
|
return result['data']
|
|
|
|
|
|
def get_subscriptions(agenda_slug, user_external_id=None, date_start=None, date_end=None):
|
|
url = 'api/agenda/%s/subscription/' % agenda_slug
|
|
params = {}
|
|
if user_external_id:
|
|
params['user_external_id'] = user_external_id
|
|
if date_start:
|
|
params['date_start'] = date_start
|
|
if date_end:
|
|
params['date_end'] = date_end
|
|
if params:
|
|
url += '?%s' % '&'.join(['%s=%s' % (k, v) for k, v in params.items()])
|
|
result = get_chrono_json(url)
|
|
if not result:
|
|
raise ChronoError(_('Unable to get subscription details'))
|
|
if result.get('err'):
|
|
raise ChronoError(_('Unable to get subscription details (%s)') % result['err_desc'])
|
|
if 'data' not in result:
|
|
raise ChronoError(_('Unable to get subscription details'))
|
|
return result['data']
|
|
|
|
|
|
def get_check_status(agenda_slugs, user_external_id, date_start, date_end):
|
|
result = get_chrono_json(
|
|
'api/agendas/events/check-status/?user_external_id=%s&agendas=%s&date_start=%s&date_end=%s'
|
|
% (
|
|
user_external_id,
|
|
','.join(agenda_slugs),
|
|
date_start,
|
|
date_end,
|
|
)
|
|
)
|
|
if not result:
|
|
raise ChronoError(_('Unable to get check status'))
|
|
if result.get('err'):
|
|
raise ChronoError(_('Unable to get check status (%s)') % result['err_desc'])
|
|
if 'data' not in result:
|
|
raise ChronoError(_('Unable to get check status'))
|
|
return result['data']
|