Upgraded reporting to weasyprint & python3.

Caution!!. pycha does not supports python3. Right now, we have patched
pycha on our servers, and will look for an updated alternative.
This commit is contained in:
Adolfo Gómez García 2018-02-08 08:05:18 +01:00
parent 8f38ae8f4a
commit 54136ae077
15 changed files with 188 additions and 435 deletions

View File

@ -39,14 +39,15 @@ from uds.core.ui.UserInterface import UserInterface
from uds.core.util import encoders
from . import stock
import six
from weasyprint import HTML, CSS, default_url_fetcher
from datetime import datetime
import logging
import six
logger = logging.getLogger(__name__)
__updated__ = '2018-02-07'
__updated__ = '2018-02-08'
class Report(UserInterface):
@ -103,8 +104,8 @@ class Report(UserInterface):
mime_type='image/png')
elif url.startswith('image://'):
if isinstance(images, dict):
logger.debug('Getting image {} --> {}'.format(url[8:], images.get(url[8:])))
img = images.get(url[8:])
img = images.get(url[8:], None)
logger.debug('Getting image {}? {}'.format(url[8:], img != None))
return dict(string=img,
mime_type='image/png')
else:

View File

@ -1,38 +0,0 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2015 Virtual Cable S.L.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
"""
from __future__ import unicode_literals
from .geraldo_graphics import UDSImage
from .report import UDSGeraldoReport
__updated__ = '2015-06-21'

View File

@ -1,27 +0,0 @@
from geraldo.base import BAND_WIDTH, BAND_HEIGHT, Element
from geraldo.utils import cm, black
from geraldo import Image
import logging
logger = logging.getLogger(__name__)
class UDSImage(Image):
def _get_height(self):
ret = self._height or (self.image and (self.image.size[1] * cm / 118) or 0)
return ret
def _set_height(self, value):
self._height = value
height = property(_get_height, _set_height)
def _get_width(self):
ret = self._width or (self.image and (self.image.size[0] * cm / 118) or 0)
return ret
def _set_width(self, value):
self._width = value
width = property(_get_width, _set_width)

View File

@ -1,97 +0,0 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2015 Virtual Cable S.L.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
"""
from __future__ import unicode_literals
from django.utils.translation import ugettext, ugettext_lazy as _
from uds.core.reports import stock
from geraldo import Report, landscape, ReportBand, ObjectValue, SystemField, BAND_WIDTH, Label, SubReport, Rect, Line
from uds.core.reports.tools.geraldo_graphics import UDSImage
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import cm, mm
from reportlab.lib.enums import TA_RIGHT, TA_CENTER
from reportlab.lib import colors
import logging
logger = logging.getLogger(__name__)
__updated__ = '2016-05-17'
class UDSGeraldoReport(Report):
author = 'UDS Enterprise'
title = 'UDS Report'
print_if_empty = True
page_size = A4
margin_left = 0.5 * cm
margin_top = 0.5 * cm
margin_right = 0.5 * cm
margin_bottom = 0.5 * cm
header_elements = []
header_height = 1.8 * cm
class band_page_header(ReportBand):
height = 1.8 * cm
bElements = [
SystemField(expression='%(report_title)s', top=0.5 * cm, left=0, width=BAND_WIDTH,
style={'fontName': 'Helvetica-Bold', 'fontSize': 14, 'alignment': TA_CENTER}),
SystemField(expression=_('Page %(page_number)d of %(page_count)d'), top=0.1 * cm,
width=BAND_WIDTH, style={'alignment': TA_RIGHT}),
UDSImage(filename=stock.getStockImagePath(stock.LOGO), left=0.0 * cm, top=0.0 * cm, width=2.0 * cm, height=2.0 * cm),
]
borders = {'bottom': Line(stroke_color=colors.red, stroke_width=3)}
class band_page_footer(ReportBand):
height = 0.5 * cm
bElements = [
Label(text=_('Generated by UDS'), top=0.1 * cm),
SystemField(expression=_('Printed in %(now:%Y, %b %d)s at %(now:%H:%M)s'), top=0.1 * cm,
width=BAND_WIDTH, style={'alignment': TA_RIGHT}),
]
borders = {'top': True}
def __init__(self, queryset=None):
self.band_page_header.elements = self.band_page_header.bElements + self.header_elements
self.band_page_header.height = self.header_height
Report.__init__(self, queryset=queryset)
@staticmethod
def viewSize():
return (
UDSGeraldoReport.page_size - UDSGeraldoReport.mar
)

View File

@ -45,7 +45,7 @@ import logging
logger = logging.getLogger(__name__)
__updated__ = '2018-02-07'
__updated__ = '2018-02-08'
class ListReportUsers(ListReport):
@ -86,7 +86,7 @@ class ListReportUsers(ListReport):
'auth': auth.name,
},
header=ugettext('Users List for {}').format(auth.name),
water=ugettext('UDS Report of users in {}'.format(auth.name))
water=ugettext('UDS Report of users in {}').format(auth.name)
)

View File

@ -31,10 +31,16 @@
@author: Adolfo Gómez, dkmaster at dkmon dot com
"""
# from .usage import StatsReportUsage
from .login import StatsReportLogin, StatsReportLoginCSV
# from .pool_performance import PoolPerformanceReport
# We just need to import. Report loader will look for Report subclasses
# from . import usage
from . import login
from . import pools_performance
from . import pools_usage_day
from . import usage_by_pool
from . import pool_usage_summary
# from .login import StatsReportLogin, StatsReportLoginCSV
# from .pools_performance import PoolPerformanceReport
# from .pools_usage_day import CountersPoolAssigned
# from .usage_by_pool import UsageByPool
# from .pools_usage import CountersPoolAssigned
# from .usage_summary_pool import UsageSummaryByPool
# from .pool_usage_summary import UsageSummaryByPool

View File

@ -54,7 +54,7 @@ import logging
logger = logging.getLogger(__name__)
__updated__ = '2018-02-07'
__updated__ = '2018-02-08'
# several constants as Width height
WIDTH, HEIGHT = 1920, 1080
@ -230,7 +230,7 @@ class StatsReportLogin(StatsReport):
surface.write_to_png(graph1)
del chart
del surface # calls finish, flushing to SVG
del surface # calls finish, flushing to image
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT) # @UndefinedVariable
@ -263,7 +263,7 @@ class StatsReportLogin(StatsReport):
surface.write_to_png(graph2)
del chart
del surface # calls finish, flushing to SVG
del surface # calls finish, flushing to image
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT) # @UndefinedVariable
@ -291,17 +291,17 @@ class StatsReportLogin(StatsReport):
surface.write_to_png(graph3)
del chart
del surface # calls finish, flushing to SVG
with open('/home/dkmaster/kk/kk.png', 'wb') as f:
f.write(graph3.getvalue())
with open('/home/dkmaster/kk/g1.svg', 'wb') as f:
f.write(graph1.getvalue())
del chart
del surface # calls finish, flushing to image
return self.templateAsPDF(
'uds/reports/stats/user-access.html',
dct={
'data': reportData,
'begining': self.startDate.date(),
'beginning': self.startDate.date(),
'ending': self.endDate.date(),
'intervals': self.samplingPoints.num(),
},

View File

@ -35,7 +35,6 @@ from __future__ import unicode_literals
from django.utils.translation import ugettext, ugettext_lazy as _
from uds.core.ui.UserInterface import gui
from uds.core.reports.tools import UDSGeraldoReport
from uds.core.util.stats import events
import six
@ -45,44 +44,16 @@ import six
from .base import StatsReport
from uds.models import ServicePool
from geraldo.generators.pdf import PDFGenerator
from geraldo import ReportBand, ObjectValue, Label
from reportlab.lib.units import cm, mm
import datetime
import logging
logger = logging.getLogger(__name__)
__updated__ = '2017-05-09'
__updated__ = '2018-02-08'
# several constants as Width height, margins, ..
WIDTH, HEIGHT = 1800, 1000
GERALDO_WIDTH = 120 * mm
GERALDO_HEIGHT = GERALDO_WIDTH * HEIGHT / WIDTH
class UsersSumaryReport(UDSGeraldoReport):
title = ''
author = 'UDS'
header_elements = [
Label(text=_('User'), top=2.0 * cm, left=0.5 * cm),
Label(text=_('Sessions'), top=2.0 * cm, left=5.5 * cm),
Label(text=_('Hours'), top=2.0 * cm, left=7.5 * cm),
Label(text=_('Average'), top=2.0 * cm, left=12 * cm),
]
header_height = 2.5 * cm
class band_detail(ReportBand):
height = 0.5 * cm
elements = (
ObjectValue(attribute_name='user', left=0.5 * cm, style={'fontName': 'Helvetica', 'fontSize': 8}),
ObjectValue(attribute_name='sessions', left=5.5 * cm, style={'fontName': 'Helvetica', 'fontSize': 8}),
ObjectValue(attribute_name='hours', left=7.5 * cm, style={'fontName': 'Helvetica', 'fontSize': 8}),
ObjectValue(attribute_name='average', left=12 * cm, style={'fontName': 'Helvetica', 'fontSize': 8}),
)
WIDTH, HEIGHT = 1920, 1080
class UsageSummaryByPool(StatsReport):
@ -174,12 +145,17 @@ class UsageSummaryByPool(StatsReport):
def generate(self):
items, poolName = self.getData()
output = six.StringIO()
report = UsersSumaryReport(queryset=items)
report.title = _('Users usage list for {}').format(poolName)
report.generate_by(PDFGenerator, filename=output)
return output.getvalue()
return self.templateAsPDF(
'uds/reports/stats/pool-usage-summary.html',
dct={
'data': items,
'pool': poolName,
'beginning': self.startDate.date(),
'ending': self.endDate.date(),
},
header=ugettext('Users usage list for {}').format(poolName),
water=ugettext('UDS Report of users in {}').format(poolName)
)
class UsageSummaryByPoolCSV(UsageSummaryByPool):

View File

@ -37,95 +37,30 @@ from django.db.models import Count
import django.template.defaultfilters as filters
from uds.core.ui.UserInterface import gui
from uds.core.reports.tools import UDSImage, UDSGeraldoReport
from uds.core.util.stats import events
import csv
import six
import cairo
import pycha.line
import pycha.bar
# import pycha.line
# import pycha.bar
import pycha.stackedbar
from .base import StatsReport
from uds.core.util import tools
from uds.models import ServicePool
from geraldo.generators.pdf import PDFGenerator
from geraldo import ReportBand, ObjectValue, BAND_WIDTH, Label, SubReport, SystemField, Line
from reportlab.lib.units import cm, mm
from reportlab.lib.enums import TA_RIGHT, TA_CENTER
# from reportlab.lib import colors
from PIL import Image as PILImage
import datetime
import logging
logger = logging.getLogger(__name__)
__updated__ = '2017-05-04'
__updated__ = '2018-02-08'
# several constants as Width height, margins, ..
WIDTH, HEIGHT = 1800, 1000
GERALDO_WIDTH = 120 * mm
GERALDO_HEIGHT = GERALDO_WIDTH * HEIGHT / WIDTH
class AccessReport(UDSGeraldoReport):
header_elements = []
class band_detail(ReportBand):
height = 400 * mm # Height bigger than a page, so a new page is launched for listings
# auto_expand_height = True
elements = (
Label(text=_('Distinct users by pool'), top=0.6 * cm, left=0, width=BAND_WIDTH,
style={'fontName': 'Helvetica-Bold', 'fontSize': 10, 'alignment': TA_CENTER}),
UDSImage(left=4 * cm, top=1 * cm,
width=GERALDO_WIDTH, height=GERALDO_HEIGHT,
get_image=lambda x: x.instance['image']),
Label(text=_('Accesses by pool'), top=GERALDO_HEIGHT + 1.2 * cm, left=0, width=BAND_WIDTH,
style={'fontName': 'Helvetica-Bold', 'fontSize': 10, 'alignment': TA_CENTER}),
UDSImage(left=4 * cm, top=GERALDO_HEIGHT + 1.6 * cm,
width=GERALDO_WIDTH, height=GERALDO_HEIGHT,
get_image=lambda x: x.instance['image2']),
)
subreports = [
SubReport(
queryset_string='%(object)s["data"]',
band_header=ReportBand(
height=1 * cm,
auto_expand_height=True,
elements=(
# Label(text=_('Users access by date'), top=0.2 * cm, left=0, width=BAND_WIDTH,
# style={'fontName': 'Helvetica-Bold', 'fontSize': 12, 'alignment': TA_CENTER}),
Label(text=_('Pool'), top=1.0 * cm, left=1.2 * cm,
style={'fontName': 'Helvetica-Bold', 'fontSize': 9}),
Label(text=_('Date range'), top=1.0 * cm, left=8 * cm,
style={'fontName': 'Helvetica-Bold', 'fontSize': 9}),
Label(text=_('Users'), top=1.0 * cm, left=14 * cm,
style={'fontName': 'Helvetica-Bold', 'fontSize': 9}),
Label(text=_('Accesses'), top=1.0 * cm, left=16 * cm,
style={'fontName': 'Helvetica-Bold', 'fontSize': 9}),
),
# borders={'bottom': True}
),
band_detail=ReportBand(
height=0.5 * cm,
elements=(
ObjectValue(attribute_name='name', top=0, left=1.2 * cm, width=12 * cm, style={'fontName': 'Helvetica', 'fontSize': 8}),
ObjectValue(attribute_name='date', top=0, left=8 * cm, width=12 * cm, style={'fontName': 'Helvetica', 'fontSize': 8}),
ObjectValue(attribute_name='users', top=0, left=14 * cm, style={'fontName': 'Helvetica', 'fontSize': 8}),
ObjectValue(attribute_name='accesses', top=0, left=16 * cm, style={'fontName': 'Helvetica', 'fontSize': 8}),
)
),
),
]
WIDTH, HEIGHT = 1920, 1080
class PoolPerformanceReport(StatsReport):
@ -174,10 +109,13 @@ class PoolPerformanceReport(StatsReport):
def initGui(self):
logger.debug('Initializing gui')
vals = [
gui.choiceItem(v.uuid, v.name) for v in ServicePool.objects.all()
gui.choiceItem(v.uuid, v.name) for v in ServicePool.objects.all().order_by('name')
]
self.pools.setValues(vals)
def getPools(self):
return [(v.id, v.name) for v in ServicePool.objects.filter(uuid__in=self.pools.value)]
def getRangeData(self):
start = self.startDate.stamp()
end = self.endDate.stamp()
@ -191,7 +129,8 @@ class PoolPerformanceReport(StatsReport):
samplingPoints = self.samplingPoints.num()
pools = [(v.id, v.name) for v in ServicePool.objects.filter(uuid__in=self.pools.value)]
pools = self.getPools()
if len(pools) == 0:
raise Exception(_('Select at least a service pool for the report'))
@ -206,7 +145,7 @@ class PoolPerformanceReport(StatsReport):
# Generate samplings interval
samplingIntervals = []
prevVal = None
for val in range(start, end, (end - start) / (samplingPoints + 1)):
for val in range(start, end, int((end - start) / (samplingPoints + 1))):
if prevVal is None:
prevVal = val
continue
@ -255,6 +194,9 @@ class PoolPerformanceReport(StatsReport):
xLabelFormat, poolsData, reportData = self.getRangeData()
graph1 = six.BytesIO()
graph2 = six.BytesIO()
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT) # @UndefinedVariable
options = {
@ -262,7 +204,7 @@ class PoolPerformanceReport(StatsReport):
'axis': {
'x': {
'ticks': [
dict(v=i, label=filters.date(datetime.datetime.fromtimestamp(l), xLabelFormat)) for i, l in enumerate(range(start, end, (end - start) / self.samplingPoints.num()))
dict(v=i, label=filters.date(datetime.datetime.fromtimestamp(l), xLabelFormat)) for i, l in enumerate(range(start, end, int((end - start) / self.samplingPoints.num())))
],
'range': (0, self.samplingPoints.num()),
'showLines': True,
@ -279,7 +221,7 @@ class PoolPerformanceReport(StatsReport):
'lineColor': '#187FF2'
},
'colorScheme': {
'name': 'rainbow',
'name': 'gradient',
'args': {
'initialColor': 'blue',
},
@ -317,7 +259,12 @@ class PoolPerformanceReport(StatsReport):
chart.render()
img = PILImage.frombuffer("RGBA", (surface.get_width(), surface.get_height()), surface.get_data(), "raw", "BGRA", 0, 1)
surface.write_to_png(graph1)
del chart
del surface # calls finish, flushing to image
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT) # @UndefinedVariable
# Accesses
chart = pycha.stackedbar.StackedVerticalBarChart(surface, options)
@ -334,26 +281,26 @@ class PoolPerformanceReport(StatsReport):
chart.render()
img2 = PILImage.frombuffer("RGBA", (surface.get_width(), surface.get_height()), surface.get_data(), "raw", "BGRA", 0, 1)
surface.write_to_png(graph2)
del chart
del surface # calls finish, flushing to image
# Generate Data for pools, basically joining all pool data
queryset = [
{'image': img, 'image2': img2, 'data': reportData }
]
logger.debug(queryset)
output = six.StringIO()
try:
report = AccessReport(queryset=queryset)
report.title = ugettext('UDS Pools Performance Report')
report.generate_by(PDFGenerator, filename=output)
return output.getvalue()
except Exception:
logger.exception('Errool')
return None
return self.templateAsPDF(
'uds/reports/stats/pools-performance.html',
dct={
'data': reportData,
'pools': [i[1] for i in self.getPools()],
'beginning': self.startDate.date(),
'ending': self.endDate.date(),
'intervals': self.samplingPoints.num(),
},
header=ugettext('UDS Pools Performance Report'),
water=ugettext('Pools Performance'),
images={'graph1': graph1.getvalue(), 'graph2': graph2.getvalue()},
)
class PoolPerformanceReportCSV(PoolPerformanceReport):
@ -369,7 +316,7 @@ class PoolPerformanceReportCSV(PoolPerformanceReport):
samplingPoints = PoolPerformanceReport.samplingPoints
def generate(self):
output = StringIO.StringIO()
output = six.StringIO()
writer = csv.writer(output)
reportData = self.getRangeData()[2]

View File

@ -35,28 +35,19 @@ from __future__ import unicode_literals
from django.utils.translation import ugettext, ugettext_lazy as _
from uds.core.ui.UserInterface import gui
from uds.core.reports.tools import UDSGeraldoReport, UDSImage
from uds.core.util.stats import counters
import six
import csv
from .base import StatsReport
from uds.models import ServicePool
from geraldo.generators.pdf import PDFGenerator
from geraldo import ReportBand, ObjectValue, Label, BAND_WIDTH, SubReport
from reportlab.lib.units import cm, mm
from reportlab.lib.enums import TA_RIGHT, TA_CENTER
import cairo
import pycha.line
import pycha.bar
# import pycha.line
# import pycha.bar
import pycha.stackedbar
from PIL import Image as PILImage
import datetime
import logging
@ -64,60 +55,10 @@ import six
logger = logging.getLogger(__name__)
__updated__ = '2017-05-03'
__updated__ = '2018-02-08'
# several constants as Width height, margins, ..
WIDTH, HEIGHT = 1800, 1000
GERALDO_WIDTH = 120 * mm
GERALDO_HEIGHT = GERALDO_WIDTH * HEIGHT / WIDTH
class CountersPoolsReport(UDSGeraldoReport):
title = ''
author = 'UDS'
header_elements = []
header_height = 2.5 * cm
class band_detail(ReportBand):
height = 400 * mm # Height bigger than a page, so a new page is launched for listings
elements = (
Label(text=_('Services Asignation'), top=0.6 * cm, left=0, width=BAND_WIDTH,
style={'fontName': 'Helvetica-Bold', 'fontSize': 10, 'alignment': TA_CENTER}),
UDSImage(left=4 * cm, top=1 * cm,
width=GERALDO_WIDTH, height=GERALDO_HEIGHT,
get_image=lambda x: x.instance['image']),
)
subreports = [
SubReport(
queryset_string='%(object)s["data"]',
band_header=ReportBand(
height=1 * cm,
auto_expand_height=True,
elements=(
Label(text=_('Service asignation by hour'), top=0.2 * cm, left=0, width=BAND_WIDTH,
style={'fontName': 'Helvetica-Bold', 'fontSize': 12, 'alignment': TA_CENTER}),
Label(text=_('Pool'), top=1.0 * cm, left=1.2 * cm,
style={'fontName': 'Helvetica-Bold', 'fontSize': 10}),
Label(text=_('Hour'), top=1.0 * cm, left=10 * cm,
style={'fontName': 'Helvetica-Bold', 'fontSize': 10}),
Label(text=_('Services'), top=1.0 * cm, left=14 * cm,
style={'fontName': 'Helvetica-Bold', 'fontSize': 10}),
),
# borders={'bottom': True}
),
band_detail=ReportBand(
height=0.5 * cm,
elements=(
ObjectValue(attribute_name='name', top=0, left=1.2 * cm, width=8.8 * cm, style={'fontName': 'Helvetica', 'fontSize': 9}),
ObjectValue(attribute_name='time', top=0, left=10 * cm, width=4 * cm, style={'fontName': 'Helvetica', 'fontSize': 9}),
ObjectValue(attribute_name='value', top=0, left=14 * cm, width=4 * cm, style={'fontName': 'Helvetica', 'fontSize': 9}),
)
),
)
]
WIDTH, HEIGHT = 1920, 1080
class CountersPoolAssigned(StatsReport):
@ -130,7 +71,7 @@ class CountersPoolAssigned(StatsReport):
order=2,
label=_('Date'),
tooltip=_('Date for report'),
defvalue=datetime.date.min,
defvalue='',
required=True
)
@ -147,7 +88,7 @@ class CountersPoolAssigned(StatsReport):
def initGui(self):
logger.debug('Initializing gui')
vals = [
gui.choiceItem(v.uuid, v.name) for v in ServicePool.objects.all()
gui.choiceItem(v.uuid, v.name) for v in ServicePool.objects.all().order_by('name')
]
self.pools.setValues(vals)
@ -176,7 +117,6 @@ class CountersPoolAssigned(StatsReport):
data.append({'uuid':pool.uuid, 'name': pool.name, 'hours': hours})
logger.debug('data: {}'.format(data))
return data
@ -184,6 +124,8 @@ class CountersPoolAssigned(StatsReport):
def generate(self):
items = self.getData()
graph1 = six.BytesIO()
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT) # @UndefinedVariable
options = {
@ -208,7 +150,7 @@ class CountersPoolAssigned(StatsReport):
'lineColor': '#187FF2'
},
'colorScheme': {
'name': 'rainbow',
'name': 'gradient',
'args': {
'initialColor': 'blue',
},
@ -238,30 +180,32 @@ class CountersPoolAssigned(StatsReport):
for pool in items:
logger.debug(pool['hours'])
ds = list((i, pool['hours'][i]) for i in range(24))
logger.debug(ds)
# logger.debug(ds)
dataset.append((ugettext('Services for {}').format(pool['name']), ds))
logger.debug('Dataset: {}'.format(dataset))
# logger.debug('Dataset: {}'.format(dataset))
chart.addDataset(dataset)
chart.render()
img = PILImage.frombuffer("RGBA", (surface.get_width(), surface.get_height()), surface.get_data(), "raw", "BGRA", 0, 1)
surface.write_to_png(graph1)
output = six.StringIO()
del chart
del surface # calls finish, flushing to image
# Regenerate data
logger.debug('Items: {}'.format(items))
# Generate data
data = []
for i in items:
for j in range(24):
data.append({'name': i['name'], 'time': '{:02d}'.format(j), 'value': i['hours'][j]})
report = CountersPoolsReport(queryset=[{'data': data, 'image': img}])
report.title = six.text_type(_('Services usage report'))
report.generate_by(PDFGenerator, filename=output)
return output.getvalue()
return self.templateAsPDF(
'uds/reports/stats/pools-usage-day.html',
dct={
'data': items,
'pools': [v.name for v in ServicePool.objects.filter(uuid__in=self.pools.value)],
'beginning': self.startDate.date(),
},
header=ugettext('Services usage report for a day'),
water=ugettext('Service usage report'),
images={'graph1': graph1.getvalue()},
)
class CountersPoolAssignedCSV(CountersPoolAssigned):

View File

@ -35,54 +35,24 @@ from __future__ import unicode_literals
from django.utils.translation import ugettext, ugettext_lazy as _
from uds.core.ui.UserInterface import gui
from uds.core.reports.tools import UDSGeraldoReport
from uds.core.util.stats import events
import six
import csv
from .base import StatsReport
from uds.models import ServicePool
from geraldo.generators.pdf import PDFGenerator
from geraldo import ReportBand, ObjectValue, Label
from reportlab.lib.units import cm, mm
import datetime
import logging
logger = logging.getLogger(__name__)
__updated__ = '2016-05-17'
__updated__ = '2018-02-08'
# several constants as Width height, margins, ..
WIDTH, HEIGHT = 1800, 1000
GERALDO_WIDTH = 120 * mm
GERALDO_HEIGHT = GERALDO_WIDTH * HEIGHT / WIDTH
class UsersReport(UDSGeraldoReport):
title = ''
author = 'UDS'
header_elements = [
Label(text=_('Access Datetime'), top=2.0 * cm, left=0.5 * cm),
Label(text=_('User'), top=2.0 * cm, left=5.5 * cm),
Label(text=_('Duration(seconds)'), top=2.0 * cm, left=12 * cm),
]
header_height = 2.5 * cm
class band_detail(ReportBand):
height = 0.5 * cm
elements = (
ObjectValue(attribute_name='date', left=0.5 * cm, style={'fontName': 'Helvetica', 'fontSize': 8}),
ObjectValue(attribute_name='name', left=5.5 * cm, style={'fontName': 'Helvetica', 'fontSize': 8}),
ObjectValue(attribute_name='time', left=12 * cm, style={'fontName': 'Helvetica', 'fontSize': 8}),
)
WIDTH, HEIGHT = 1920, 1080
class UsageByPool(StatsReport):
@ -153,19 +123,22 @@ class UsageByPool(StatsReport):
'time': total
})
logger.debug('data')
logger.debug('data: {}'.format(data))
return data, pool.name
def generate(self):
items, poolName = self.getData()
output = six.StringIO()
report = UsersReport(queryset=items)
report.title = _('Users usage list for {}').format(poolName)
report.generate_by(PDFGenerator, filename=output)
return output.getvalue()
return self.templateAsPDF(
'uds/reports/stats/usage-by-pool.html',
dct={
'data': items,
'pool': poolName,
},
header=ugettext('Users usage list for {}').format(poolName),
water=ugettext('UDS Report of users in {}').format(poolName)
)
class UsageByPoolCSV(UsageByPool):
@ -180,7 +153,7 @@ class UsageByPoolCSV(UsageByPool):
endDate = UsageByPool.endDate
def generate(self):
output = StringIO.StringIO()
output = six.StringIO()
writer = csv.writer(output)
reportData, poolName = self.getData()

View File

@ -0,0 +1,35 @@
{% load l10n i18n %}
<html lang="en">
<head>
<title>Users usage summary for {{ pool }}</title>
<meta name="author" content="UDS">
<meta name="description" content="Users usage summary for {{ pool }} from {{ beginning }} to {{ ending }}">
<meta name="keywords" content="uds,report,usage,users,summary">
<meta name="generator" content="UDS Reporting">
</head>
<body>
<table style="width: 100%; font-size: 0.8em;">
<thead>
<tr>
<th style="width: 25%">{% trans 'User' %}</th>
<th style="width: 50%">{% trans 'Sessions' %}</th>
<th style="width: 25%">{% trans 'Hours' %}</th>
<th style="width: 25%">{% trans 'Average' %}</th>
</tr>
</thead>
<tbody>
{% for d in data %}
<tr>
<td>{{ d.user }}</td>
<td>{{ d.sessions }}</td>
<td>{{ d.hours }}</td>
<td>{{ d.average }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<!-- <p style="page-break-before: always">
This is a new page
</p> -->
</body>
</html>

View File

@ -6,7 +6,7 @@
</title>
<meta name="author" content="UDS">
<meta name="description" content="Report of pools usage of {{ pools|join:", " }}, for day {{ beginning }}">
<meta name="keywords" content="uds,report,access">
<meta name="keywords" content="uds,report,usage,pools">
<meta name="generator" content="UDS Reporting">
</head>
<body>

View File

@ -0,0 +1,33 @@
{% load l10n i18n %}
<html lang="en">
<head>
<title>Users usage list for {{ pool }}</title>
<meta name="author" content="UDS">
<meta name="description" content="Users usage list for {{ pool }}">
<meta name="keywords" content="uds,report,usage,users,list">
<meta name="generator" content="UDS Reporting">
</head>
<body>
<table style="width: 100%; font-size: 0.8em;">
<thead>
<tr>
<th style="width: 25%">{% trans 'Access date/time' %}</th>
<th style="width: 50%">{% trans 'User' %}</th>
<th style="width: 25%">{% trans 'Duration' %}</th>
</tr>
</thead>
<tbody>
{% for user in data %}
<tr>
<td>{{ user.date }}</td>
<td>{{ user.name }}</td>
<td>{{ user.time }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<!-- <p style="page-break-before: always">
This is a new page
</p> -->
</body>
</html>

View File

@ -4,7 +4,7 @@
<title>Users Access Report</title>
<meta name="author" content="UDS">
<meta name="description" content="List of UDS accesses from {{ beginning }} to {{ ending }} with {{ intervals }} intervals">
<meta name="keywords" content="uds,report,access">
<meta name="keywords" content="uds,report,access,user">
<meta name="generator" content="UDS Reporting">
</head>
<body>