combo-plugin-gnm/combo_plugin_gnm/management/commands/gnm_reporting.py

77 lines
3.5 KiB
Python

# combo-plugin-gnm - Combo GNM plugin
# Copyright (C) 2017-2020 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 html
import os
import re
import xml.etree.ElementTree as ET
import zipfile
from io import BytesIO
from combo.data.models import TextCell
from combo.utils import requests
from django.conf import settings
from django.contrib.auth import get_user_model
from django.core.files.storage import default_storage
from django.core.management.base import BaseCommand, CommandError
class Command(BaseCommand):
def handle(self, *args, **options):
if not getattr(settings, 'GNM_REPORTING', False):
return
reporting_user_email = settings.TEMPLATE_VARS.get('reporting_user_email')
reporting_user = None
if reporting_user_email:
reporting_user = get_user_model().objects.get(email=reporting_user_email)
for cell in TextCell.objects.filter(slug='reporting', page__snapshot__isnull=True):
if not reporting_user:
raise CommandError('missing reporting user (%s)' % reporting_user_email)
sheets = []
for url in re.findall('href="(.*?)"', cell.text):
url = html.unescape(url)
url = re.sub(
r'/backoffice/management/([a-z0-9_-]+)(/[a-z0-9_-]+)?/?(\?)?',
r'/api/forms/\1/ods\2\3',
url,
)
resp = requests.get(url, remote_service='auto', user=reporting_user)
if not resp.ok:
continue
zipf = zipfile.ZipFile(BytesIO(resp.content))
sheets.append(
ET.parse(zipf.open('content.xml')).findall(
'.//{urn:oasis:names:tc:opendocument:xmlns:table:1.0}table'
)[0]
)
if sheets:
if not os.path.exists(default_storage.path('reporting')):
os.mkdir(default_storage.path('reporting'))
filepath = default_storage.path('reporting/%s.ods' % cell.id)
with zipfile.ZipFile(filepath, 'w') as new_ods:
for f in zipf.namelist():
if f != 'content.xml':
new_ods.writestr(f, zipf.read(f))
OFFICE_NS = 'urn:oasis:names:tc:opendocument:xmlns:office:1.0'
root = ET.Element('{%s}document-content' % OFFICE_NS)
ET.SubElement(root, '{%s}scripts' % OFFICE_NS)
ET.SubElement(root, '{%s}font-face-decls' % OFFICE_NS)
body = ET.SubElement(root, '{%s}body' % OFFICE_NS)
spreadsheet = ET.SubElement(body, '{%s}spreadsheet' % OFFICE_NS)
for sheet in sheets:
spreadsheet.append(sheet)
new_ods.writestr('content.xml', ET.tostring(root))