report.py 10.8 KB
import os
import sys
import ntpath
import csv
import io
from datetime import datetime
# from z3c.rml import rml2pdf
import subprocess
import logging

from pypdf import PdfReader, PdfWriter

from ..tools import get_settings, get_params, get_random_string

log = logging.getLogger(__name__)


# def get_root_path():
#     _here = os.path.dirname(__file__)
#     return _here


def get_logo(base_path=""):
    if not base_path:
        import opensipkd.base
        base_path = os.path.dirname(os.path.abspath(opensipkd.base.__file__))
    path = get_params('report_img', os.path.join(base_path, 'static/img'))
    return path + "/logo.png", path + "/line.png"


def waktu():
    return datetime.now().strftime('%d-%m-%Y %H:%M')


def open_rml_row(row_tpl_filename):
    f = open(row_tpl_filename)
    row_rml = f.read()
    f.close()
    return row_rml


def open_rml_pdf(tpl_filename, **kwargs):
    # out_filename = 'out_filename' in kwargs and kwargs['out_filename'] or tpl_filename
    # log.warning("Not Supported")
    # return
    pdf_filename = tpl_filename + '.pdf'
    f = open(tpl_filename)
    rml = f.read()
    f.close()
    base_path = kwargs.get('base_path')
    logo, line = get_logo(base_path)
    params = {}

    for key, value in kwargs.items():
        params[key] = value
    rml = rml.format(waktu=waktu(),
                     logo=logo,
                     line=line, **kwargs
                     )
    from z3c.rml import rml2pdf
    pdf = rml2pdf.parseString(rml)
    return pdf, pdf_filename


def openfile_response(request, filepath):
    response = request.response
    # import magic
    # ctype = magic.from_file(filepath, mime=True)
    f = open(filepath, 'rb')
    filename = ntpath.basename(filepath)
    import mimetypes
    ctype = mimetypes.MimeTypes().guess_type(filename)[0]
    response.content_type = str(ctype)
    response.content_disposition = 'filename=' + filename
    response.write(f.read())
    return response


def file_response(request, f=None, filename=None, filetype=None):
    """
    :param request:
    :param f:  object file
    :param filename:
    :param filetype: type of file
    :return: object response
    """
    import ntpath
    if not f:
        f = open(filename, 'rb')
        fname = ntpath.basename(filename)
    else:
        fname = filename

    if not filetype:
        t = fname.split('.')
        filetype = ''.join(t[-1:])

    response = request.response
    response.content_type = f"application/{filetype}"
    response.content_disposition = 'filename=' + fname
    if filetype == "txt":
        response.charset = "UTF-8"
    response.write(f.read())
    return response


def set_response(request, filename):
    ext = filename.split('.')[-1]
    if ext in ['gif', 'png', 'jpeg', 'jpg']:
        ext = 'image/' + ext
    elif ext in ['pdf']:
        ext = 'application/' + ext
    with open(filename, 'rb') as f:
        return file_response(request, f, filename, ext)


def pdf_response(request, f=None, filename=None):
    return file_response(request, f, filename, 'pdf')


def odt_response(request, f, filename):
    return file_response(request, f, filename, 'odt')


def odt_export1(request, filename, file_type):
    settings = get_settings()
    if 'unoconv_py' in settings and settings['unoconv_py']:
        unoconv_py = settings['unoconv_py']
        if 'unoconv_bin' in settings and settings['unoconv_bin']:
            unoconv_bin = settings['unoconv_bin']
            f = '.'.join([filename, 'odt'])
            subprocess.call([unoconv_py, unoconv_bin, file_type, f])
            out_filename = '.'.join([filename, file_type])
            with open(out_filename, 'rb') as f:
                return file_response(request, f, out_filename, file_type)


def odt_export_(filename, file_type, password=None):
    log.info("Start Export {}".format(filename))
    settings = get_settings()
    import getpass
    username = getpass.getuser()
    odt_file = '.'.join([filename, 'odt'])
    out_dir = os.path.dirname(filename)
    if 'unoconv_py' in settings and settings['unoconv_py']:
        log.info("Unoconv PY {}".format(filename))
        unoconv_py = settings['unoconv_py']
        if 'unoconv_bin' in settings and settings['unoconv_bin']:
            unoconv_bin = settings['unoconv_bin']
        else:
            unoconv_bin = ''

        params = [unoconv_py, unoconv_bin, '-f', file_type]
        if password:
            params.extend(['-e', 'EncryptFile=True',
                           '-e', 'DocumentOpenPassword=' + password])

        params.append(odt_file)
        log.info("DEBUG EXPORT>>{}".format(' '.join(params)))
        subprocess.call(params)

    # convert using bin
    else:
        log.info("Unoconv BIN {}".format(filename))
        if 'unoconv_bin' in settings and settings['unoconv_bin']:
            unoconv_bin = settings['unoconv_bin']
            params = [unoconv_bin,
                      '-env:UserInstallation=file:///tmp/' + username,
                      '--headless', '--convert-to', 'pdf']
            params.extend(['--outdir', out_dir, file_type, odt_file])
            log.info("DEBUG EXPORT>>{}".format(' '.join(params)))
            subprocess.call(params)

    out_file = '.'.join([filename, file_type])
    if not os.path.isfile(odt_file):
        log.error("ODT FILE NOTFOUND")
        return dict(error=dict(code=-1,
                               message='File  %s tidak ditemukan ' % odt_file))
    else:
        if not os.path.isfile(out_file):
            log.error("PDF FILE NOTFOUND")
            return dict(error=dict(code=-1,
                                   message='File  %s tidak ditemukan ' % out_file))
        os.remove(odt_file)
    return dict(filename=out_file)


def odt_export(request, filename, file_type):
    results = odt_export_(filename, file_type)
    # bug key error: code
    # if not results['code']:
    if 'error' in results:
        return results

    # out_filename = '.'.join([filename, file_type])
    # out_filename = '.'.join([results['filename'], file_type])
    out_filename = results['filename']

    if not os.path.isfile(out_filename):
        return dict(error=True,
                    msg='Error %s tidak ditemukan ' % out_filename)

    with open(out_filename, 'rb') as f:
        return file_response(request, f, out_filename, file_type)


def odt_export2(request, filename, file_type):
    settings = get_settings()
    if 'unoconv_py' in settings and settings['unoconv_py']:
        if 'unoconv_bin' in settings and settings['unoconv_bin']:
            unoconv_py = settings['unoconv_py']
            unoconv_bin = settings['unoconv_bin']
            f = '.'.join([filename, 'odt'])
            subprocess.call([unoconv_bin,
                             '-env:UserInstallation=file:///tmp/libO_udir',
                             '--headless', '--convert-to', file_type,
                             '--outdir', '/tmp', f])
            out_filename = '.'.join([filename, file_type])
            with open(out_filename, 'rb') as f:
                return file_response(request, f, out_filename, file_type)


def csv_rows(query):
    row = query.first()
    header = row.keys()
    rows = []
    for item in query.all():
        rows.append(list(item))
    return dict(header=header,
                rows=rows)


def csv_response(request, value, filename=None):
    if not filename:
        filename = get_random_string(20)+".csv"
    response = request.response
    response.content_type = 'text/csv'
    # response.content_disposition = 'attachment;filename=' + filename
    response.content_disposition = 'filename=' + filename
    if sys.version_info < (3,):
        import StringIO
        fout = StringIO.StringIO()
    else:
        fout = io.StringIO()

    fcsv = csv.writer(fout, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
    fcsv.writerow(value.get('header', []))
    fcsv.writerows(value.get('rows', []))
    response.write(fout.getvalue())
    return response


def terbilang(bil):
    angka = ["", "Satu", "Dua", "Tiga", "Empat", "Lima", "Enam", "Tujuh", "Delapan", "Sembilan", "Sepuluh", "Sebelas"]
    hasil = " "
    n = int(bil)
    if 0 <= n <= 11:
        hasil = hasil + angka[n]
    elif n < 20:
        hasil = terbilang(n % 10) + " Belas"
    elif n < 100:
        hasil = terbilang(n / 10) + " Puluh" + terbilang(n % 10)
    elif n < 200:
        hasil = " Seratus" + terbilang(n - 100)
    elif n < 1000:
        hasil = terbilang(n / 100) + " Ratus" + terbilang(n % 100)
    elif n < 2000:
        hasil = " Seribu" + terbilang(n - 1000)
    elif n < 1000000:
        hasil = terbilang(n / 1000) + " Ribu" + terbilang(n % 1000)
    elif n < 1000000000:
        hasil = terbilang(n / 1000000) + " Juta" + terbilang(n % 1000000)
    else:
        hasil = terbilang(n / 1000000000) + " Miliar" + terbilang(n % 1000000000)
    return hasil


def ods_export(request, filename, file_type):
    settings = get_settings()
    if 'unoconv_py' in settings and settings['unoconv_py']:
        if 'unoconv_bin' in settings and settings['unoconv_bin']:
            unoconv_py = settings['unoconv_py']
            unoconv_bin = settings['unoconv_bin']
            f = '.'.join([filename, 'ods'])
            subprocess.call([unoconv_py, unoconv_bin, '-f', file_type, f])
            out_filename = '.'.join([filename, file_type])
            with open(out_filename, 'rb') as f:
                return file_response(request, f, out_filename, file_type)


# use
# pdf_compress("/tmp/original.pdf", "/tmp/compressed.tmp")
# return None
def pdf_compress(original_filename, compressed_filename=None):
    if compressed_filename is None:
        ori_dir = os.path.dirname(original_filename)
        ori_filename = os.path.basename(original_filename)
        filenames = ori_filename.split('.')
        ext = filenames[-1]
        filename = "".join(filenames[:-1])
        compressed_filename = os.path.join(ori_dir, f"{filename}_compressed.{ext}")

    reader = PdfReader(original_filename)
    writer = PdfWriter()

    for page in reader.pages:
        writer.add_page(page)

    if reader.metadata is not None:
        writer.add_metadata(reader.metadata)

    with open(compressed_filename, "wb") as fp:
        writer.write(fp)

    return compressed_filename

# use:
# tmp_reports(module_dirname="pbb/pendataan")
# tmp_reports(settings=get_settings(), module_dirname="pbb/pendataan")
# tmp_reports(settings=get_settings(), tmp_path="/home/user/tmp", module_dirname="pbb/pendataan")
# return "string of path"
def tmp_reports(settings = None, tmp_path = None, module_dirname = None):
    default_tmp = '/tmp'

    if settings is None:
        settings = get_settings()

    if not settings:
        return default_tmp

    if tmp_path is None:
        tmp_path = 'tmp_report' in settings and settings['tmp_report'] or default_tmp

    if module_dirname:
        tmp_path = os.path.join(tmp_path, module_dirname)

    if not os.path.exists(tmp_path):
        os.makedirs(tmp_path)

    return tmp_path


class Item(object):
    pass