예제 #1
0
    def _get_style(self):
        tblstyle = TableStyle([
                               ('SPAN', (0, 0), (-1, 0)),
                               ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
                               ('FONTSIZE', (0, 0), (-1, -1), 9),
                               ('TEXTCOLOR', (0, 0), (-1, -1), colors.black),
                               ('LINEBELOW', (0, 0), (-1, 0), 1, colors.black),
                               ('LINEBELOW', (0, 1), (-1, 1), 1, colors.black),
#                            ('ALIGN', (2, 0), (2, 0), 'LEFT'),
                               ('LINEBELOW', (0, 3), (-1, 3), 1.5, colors.black),
                               # ('LINEBELOW', (0, 0), (-1, -1), 1, colors.red),

#                               ('LINEBEFORE', (0, 0), (-1, -1), 1, colors.black),
                               ('ALIGN', (2, 0), (-1, -1), 'CENTER')
                              ])

        for ir in self.int_plat_age_rowids:
            tblstyle.add('SPAN', (1, ir), (3, ir))
            tblstyle.add('SPAN', (1, ir + 1), (2, ir + 1))

        for si in self.sample_rowids:
            tblstyle.add('SPAN', (1, si), (-1, si))
예제 #2
0
파일: reports.py 프로젝트: cmjatai/cmj
    def build_pdf(self, response):

        cleaned_data = self.filterset.form.cleaned_data

        agrupamento = cleaned_data['agrupamento']

        elements = []

        #print('data ini', datetime.now())
        data = self.get_data()
        #print('data fim', datetime.now())

        style = TableStyle([
            ('FONTSIZE', (0, 0), (-1, -1), 8),
            ('LEADING', (0, 0), (-1, -1), 7),
            ('GRID', (0, 0), (-1, -1), 0.1, colors.black),
            ('INNERGRID', (0, 0), (-1, -1), 0.1, colors.black),
            ('TOPPADDING', (0, 0), (-1, -1), 0),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 0),
            ('LEFTPADDING', (0, 0), (-1, -1), 3),
            ('RIGHTPADDING', (0, 0), (-1, -1), 3),
        ])
        style.add('VALIGN', (0, 0), (-1, -1), 'MIDDLE')

        #print('enumerate ini', datetime.now())
        for i, value in enumerate(data):
            if len(value) <= 1:
                style.add('SPAN', (0, i), (-1, i))

            if len(value) == 0:
                style.add('INNERGRID', (0, i), (-1, i), 0, colors.black),
                style.add('GRID', (0, i), (-1, i), -1, colors.white)
                style.add('LINEABOVE', (0, i), (-1, i), 0.1, colors.black)

            if len(value) == 1:
                style.add('LINEABOVE', (0, i), (-1, i), 0.1, colors.black)

        #print('enumerate fim', datetime.now())
        # if not agrupamento or agrupamento == 'sem_agrupamento':
        #    style.add('ALIGN', (0, 0), (0, -1), 'CENTER')

        #print('table ini', datetime.now())
        rowHeights = 20
        t = LongTable(data, rowHeights=rowHeights, splitByRow=True)
        t.setStyle(style)
        if len(t._argW) == 5:
            t._argW[0] = 1.8 * cm
            t._argW[1] = 6 * cm
            t._argW[2] = 6.5 * cm
            t._argW[3] = 9.5 * cm
            t._argW[4] = 2.4 * cm
        elif len(t._argW) == 4:
            t._argW[0] = 2 * cm
            t._argW[1] = 10 * cm
            t._argW[2] = 11.5 * cm
            t._argW[3] = 3 * cm

        for i, value in enumerate(data):
            if len(value) == 0:
                t._argH[i] = 7
                continue
            for cell in value:
                if isinstance(cell, list):
                    t._argH[i] = (rowHeights) * (
                        len(cell) - (0 if len(cell) > 1 else 0))
                    break

        elements.append(t)
        #print('table fim', datetime.now())

        #print('build ini', datetime.now())
        doc = SimpleDocTemplate(
            response,
            pagesize=landscape(A4),
            rightMargin=1.25 * cm,
            leftMargin=1.25 * cm,
            topMargin=1.1 * cm,
            bottomMargin=0.8 * cm)
        doc.build(elements)
예제 #3
0
    def build_pdf(self, response):

        cleaned_data = self.filterset.form.cleaned_data

        agrupamento = cleaned_data['agrupamento']

        elements = []

        #print('data ini', datetime.now())
        data = self.get_data()
        #print('data fim', datetime.now())

        style = TableStyle([
            ('FONTSIZE', (0, 0), (-1, -1), 8),
            ('LEADING', (0, 0), (-1, -1), 7),
            ('GRID', (0, 0), (-1, -1), 0.1, colors.black),
            ('INNERGRID', (0, 0), (-1, -1), 0.1, colors.black),
            ('TOPPADDING', (0, 0), (-1, -1), 0),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 0),
            ('LEFTPADDING', (0, 0), (-1, -1), 3),
            ('RIGHTPADDING', (0, 0), (-1, -1), 3),
        ])
        style.add('VALIGN', (0, 0), (-1, -1), 'MIDDLE')

        #print('enumerate ini', datetime.now())
        for i, value in enumerate(data):
            if len(value) <= 1:
                style.add('SPAN', (0, i), (-1, i))

            if len(value) == 0:
                style.add('INNERGRID', (0, i), (-1, i), 0, colors.black),
                style.add('GRID', (0, i), (-1, i), -1, colors.white)
                style.add('LINEABOVE', (0, i), (-1, i), 0.1, colors.black)

            if len(value) == 1:
                style.add('LINEABOVE', (0, i), (-1, i), 0.1, colors.black)

        #print('enumerate fim', datetime.now())
        # if not agrupamento or agrupamento == 'sem_agrupamento':
        #    style.add('ALIGN', (0, 0), (0, -1), 'CENTER')

        #print('table ini', datetime.now())
        rowHeights = 20
        t = LongTable(data, rowHeights=rowHeights, splitByRow=True)
        t.setStyle(style)
        if len(t._argW) == 5:
            t._argW[0] = 1.8 * cm
            t._argW[1] = 6 * cm
            t._argW[2] = 6.5 * cm
            t._argW[3] = 9.5 * cm
            t._argW[4] = 2.4 * cm
        elif len(t._argW) == 4:
            t._argW[0] = 2 * cm
            t._argW[1] = 10 * cm
            t._argW[2] = 11.5 * cm
            t._argW[3] = 3 * cm

        for i, value in enumerate(data):
            if len(value) == 0:
                t._argH[i] = 7
                continue
            for cell in value:
                if isinstance(cell, list):
                    t._argH[i] = (rowHeights) * (len(cell) -
                                                 (0 if len(cell) > 1 else 0))
                    break

        elements.append(t)
        #print('table fim', datetime.now())

        #print('build ini', datetime.now())
        doc = SimpleDocTemplate(response,
                                pagesize=landscape(A4),
                                rightMargin=1.25 * cm,
                                leftMargin=1.25 * cm,
                                topMargin=1.1 * cm,
                                bottomMargin=0.8 * cm)
        doc.build(elements)
예제 #4
0
def appendEvaluationList(obj, document):
    elemList = []
    if hasattr(obj, 'requirement') \
       and obj.requirement is not None:
        my_catalog = zapi.getUtility(ICatalog)
        res = my_catalog.searchResults(oid_index=obj.requirement)
        if len(res) > 0:
            requirementObj = iter(res).next()
            reqTitle = requirementObj.ikName
            reqComment = requirementObj.ikComment
            elemList.append(RptPara(reqTitle,
                                    doc=document))
            elemList.append(RptPara(reqComment,
                                    doc=document))
            elemList.append(Spacer(0, 4 * mm))
    # Evaluations Done
    evaluations = getEvaluationsDone(obj)
    if len(evaluations) > 0:
        styleSheet = getRptStyleSheet()
        style1 = styleSheet['Small']
        style2 = styleSheet['Infobox']
        elemList.append(
            RptPara('Evaluations Done: ', style=style2, doc=document))
        colWidths = [15 * mm, 60 * mm, 20 * mm, 40 * mm]
        data = [[
            RptPara('<b>Pos</b>', style=style1, doc=document),
            RptPara('<b>Requirement</b>', style=style1, doc=document),
            RptPara('<b>Value</b>', style=style1, doc=document),
            RptPara('<b>Evaluator</b>', style=style1, doc=document)
        ]]
        rowColor = getTabBackgroundColor()
        rowColorLight = getTabBackgroundColorLight()
        ik_tbl_style = TableStyle([\
            ('BACKGROUND', (0, 0), (-1, 0), rowColor),
            ('LEFTPADDING', (0, 0), (-1, -1), 1 * mm),
            ('RIGHTPADDING', (0, 0), (-1, -1), 1 * mm),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 1 * mm),
            ('TOPPADDING', (0, 0), (-1, -1), 2 * mm),
            ('FONTSIZE', (0, 0), (-1, -1), 8),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
            ('ROWBACKGROUNDS',(0,0),(-1,-1),[rowColor, rowColorLight]),
            ('INNERGRID', (0, 0), (-1, -1), 0.25, colors.black),
            ('BOX', (0, 0), (-1, -1), 0.25, colors.black),
        ])
        pos = 0
        for evaluation in evaluations.values():
            pos = pos + 1
            if evaluation.value == 'Pass':
                ik_tbl_style.add('BACKGROUND', (2, pos), (2, pos), colors.green)
            elif evaluation.value == 'Fail':
                ik_tbl_style.add('BACKGROUND', (2, pos), (2, pos), colors.red)
            else:
                pass
            if len(evaluation.requirement) == 0:
                data.append([
                    RptPara(evaluation.requirement.getIndexString(),
                            style=style1,
                            doc=document),
                    RptPara(evaluation.requirement.ikName,
                            style=style1,
                            doc=document),
                    RptPara(evaluation.value,
                            style=style1, 
                            doc=document),
                    RptPara(evaluation.evaluator.title,
                            style=style1, 
                            doc=document),
                ])
        t0 = Table(data,
                   hAlign='RIGHT',
                   style=ik_tbl_style,
                   colWidths=colWidths)
        elemList.append(t0)
        elemList.append(Spacer(0, 3 * mm))
    # Evaluations ToDo
    evaluations = getEvaluationsTodo(obj)
    if len(evaluations) > 0:
        styleSheet = getRptStyleSheet()
        style1 = styleSheet['Small']
        style2 = styleSheet['Infobox']
        elemList.append(
            RptPara('Evaluations ToDo: ', style=style2, doc=document))
        #colWidths = [75 * mm, 20 * mm, 40 * mm]
        colWidths = [15 * mm, 120 * mm]
        data = [[
            RptPara('<b>Pos</b>', style=style1, doc=document),
            RptPara('<b>Requirement</b>', style=style1, doc=document),
            #RptPara('<b>Value</b>', style=style1, doc=document),
            #RptPara('<b>Evaluator</b>', style=style1, doc=document)
        ]]
        rowColor = getTabBackgroundColor()
        rowColorLight = getTabBackgroundColorLight()
        ik_tbl_style = TableStyle([\
            ('BACKGROUND', (0, 0), (-1, 0), rowColor),
            ('LEFTPADDING', (0, 0), (-1, -1), 1 * mm),
            ('RIGHTPADDING', (0, 0), (-1, -1), 1 * mm),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 1 * mm),
            ('TOPPADDING', (0, 0), (-1, -1), 2 * mm),
            ('FONTSIZE', (0, 0), (-1, -1), 8),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
            ('ROWBACKGROUNDS',(0,0),(-1,-1),[rowColor, rowColorLight]),
            ('INNERGRID', (0, 0), (-1, -1), 0.25, colors.black),
            ('BOX', (0, 0), (-1, -1), 0.25, colors.black),
        ])
        #pos = 0
        for evaluation in evaluations:
#            pos = pos + 1
#            if evaluation.value == 'Pass':
#                ik_tbl_style.add('BACKGROUND', (1, pos), (1, pos), colors.green)
#            elif evaluation.value == 'Fail':
#                ik_tbl_style.add('BACKGROUND', (1, pos), (1, pos), colors.red)
#            else:
#                pass
            if len(evaluation.keys()) == 0:
                data.append([
                    RptPara(evaluation.getIndexString(),
                            style=style1,
                            doc=document),
                    RptPara(evaluation.ikName,
                            style=style1,
                            doc=document),
#                RptPara(evaluation.value,
#                        style=style1, 
#                        doc=document),
#                RptPara(evaluation.evaluator.title,
#                        style=style1, 
#                        doc=document),
            ])
        t0 = Table(data,
                   hAlign='RIGHT',
                   style=ik_tbl_style,
                   colWidths=colWidths)
        elemList.append(t0)
        elemList.append(Spacer(0, 3 * mm))
    return elemList
예제 #5
0
def pdf(group, username, list, show_header=True, show_footer=True):
    """PDF version of list"""

    content = BytesIO()

    columns = list.column_set.all()
    accounts = list.accounts()

    margin = 0.5 * cm

    font_name = "Times-Roman"
    font_name_bold = "Times-Bold"
    font_size = 12
    font_size_small = 10
    font_size_min = 8

    head_height = 30  # pt
    foot_height = 15  # pt
    logo_height = 25  # pt

    font_size_name = font_size_small
    font_size_short_name = font_size_small
    font_size_balance = font_size_small

    if list.orientation == list.LANDSCAPE:
        height, width = A4
    else:
        width, height = A4

    grid_style = TableStyle(parent=GRID_STYLE)

    # Create canvas for page and set fonts
    p = canvas.Canvas(content, (width, height))

    show_logo = bool(group.logo and group.logo.storage.exists(group.logo.path))

    if show_logo:
        # Find scaling ratio
        ratio = group.logo.width / group.logo.height

        # Load logo with correct scaling
        logo = Image(
            group.logo.path, width=logo_height * ratio, height=logo_height
        )

    def draw_header():
        if not show_header:
            return

        if show_logo:
            logo.drawOn(
                p,
                width - margin - logo_height * ratio,
                height - margin - logo_height,
            )

        # Setup rest of header
        p.setFont(font_name, font_size)
        p.drawString(
            margin, height - margin - font_size, f"{group}: {list.name}"
        )
        p.setFont(font_name, font_size_small)
        p.drawString(
            margin,
            height - margin - font_size - font_size + 2,
            "%s: %s %s %s"
            % (_("Printed"), str(date.today()), _("by"), username),
        )

    footer = []
    if group.email:
        footer.append(group.email)
    if group.account_number:
        footer.append(group.get_account_number_display())
    if list.comment.strip():
        footer.append(list.comment.replace("\n", " ").replace("\r", " "))

    def draw_footer():
        if not show_footer:
            return

        p.drawString(margin, margin, " - ".join(footer))

        blacklisted_note = _("Blacklisted accounts are marked with: ")

        p.drawRightString(width - margin - 10, margin, blacklisted_note)
        p.setFillColor(BLACKLISTED_COLOR)
        p.rect(width - margin - 10, margin, 8, 8, fill=1, stroke=0)

        p.setFont(font_name, font_size)

    if not accounts:
        no_accounts_message = _("Sorry, this list is empty.")
        draw_header()
        p.drawString(
            margin,
            height - font_size - margin - head_height,
            no_accounts_message,
        )
        draw_footer()
        p.save()

        return content

    elif not columns:
        no_columns_message = _(
            "Sorry, this list isn't set up correctly, "
            "please add some columns."
        )
        draw_header()
        p.drawString(
            margin,
            height - font_size - margin - head_height,
            no_columns_message,
        )
        draw_footer()
        p.save()

        return content

    # Store col widths
    col_width = []
    header = [_("Name")]

    if list.account_width:
        col_width.append(list.account_width)

    if list.short_name_width:
        col_width.append(list.short_name_width)

    if list.account_width and list.short_name_width:
        header.append("")

    if list.balance_width:
        header.append(_("Balance"))
        col_width.append(list.balance_width)

    if list.short_name_width > 0 and list.account_width > 0:
        grid_style.add("SPAN", (0, 0), (1, 0))

    base_x = len(header)

    for c in columns:
        header.append(c.name)
        col_width.append(c.width)

    # Calculate relative col widths over to absolute points
    for i, w in enumerate(col_width):
        col_width[i] = (
            float(w)
            / float(
                (list.listcolumn_width or 0)
                + list.balance_width
                + (list.account_width or 0)
                + (list.short_name_width or 0)
            )
            * (width - 2 * margin)
        )

    # Intialise table with header
    data = [header]

    for i, a in enumerate(accounts):
        color = ALTERNATE_COLORS[(i + 1) % len(ALTERNATE_COLORS)]

        if list.double:
            i *= 2
            extra_row_height = 1
        else:
            extra_row_height = 0

        i += 1

        grid_style.add("BACKGROUND", (0, i), (-1, i + extra_row_height), color)

        row = []

        if list.account_width:
            row.append(a.name)

            # Check if we need to reduce col font size
            while (
                col_width[len(row) - 1]
                < p.stringWidth(row[-1], font_name, font_size_name) + 12
                and font_size_name > font_size_min
            ):
                font_size_name -= 1

        if list.short_name_width:
            short_name = a.short_name

            if not short_name and a.owner:
                short_name = a.owner.username

            row.append(short_name or a.name)

            # Check if we need to reduce col font size
            while (
                col_width[len(row) - 1]
                < p.stringWidth(row[-1], font_name, font_size_name) + 12
                and font_size_short_name > font_size_min
            ):
                font_size_short_name -= 1

        if list.balance_width:
            row.append("%d" % a.normal_balance())

            # XXX: currently warnings are only shown if balance is shown, this
            # if needs to be moved if you want to change that
            if a.needs_warning():
                grid_style.add(
                    "FONTNAME", (0, i), (base_x - 1, i), font_name_bold
                )
                grid_style.add(
                    "TEXTCOLOR",
                    (base_x - 1, i),
                    (base_x - 1, i),
                    WARN_TEXT_COLOR,
                )

            # Check if we need to reduce col font size
            while (
                col_width[len(row) - 1]
                < p.stringWidth(str(row[-1]), font_name, font_size_balance) + 12
                and font_size_balance > font_size_min
            ):
                font_size_balance -= 1

        if a.is_blocked():
            if list.balance_width:
                grid_style.add(
                    "TEXTCOLOR",
                    (base_x - 1, i),
                    (base_x - 1, i),
                    BLACKLISTED_TEXT_COLOR,
                )
                grid_style.add(
                    "FONTNAME", (0, i), (base_x - 1, i), font_name_bold
                )
            grid_style.add(
                "BACKGROUND",
                (base_x, i),
                (-1, i + extra_row_height),
                BLACKLISTED_COLOR,
            )

            row.extend([""] * len(header[base_x:]))

        else:
            row.extend(header[base_x:])

        data.append(row)

        if list.double:
            data.append([""] * len(row))

            grid_style.add("SPAN", (0, i), (0, i + extra_row_height))

            if list.balance_width:
                grid_style.add("SPAN", (1, i), (1, i + extra_row_height))

    grid_style.add("FONTSIZE", (0, 0), (-1, -1), font_size_small)

    # Set font size for names
    grid_style.add("FONTSIZE", (0, 1), (0, -1), font_size_name)
    grid_style.add("ALIGN", (0, 0), (-1, -1), "LEFT")
    grid_style.add("ALIGN", (base_x, 0), (-1, -1), "RIGHT")

    grid_style.add("FONTNAME", (0, 0), (-1, 0), font_name_bold)

    # Set font size for balance
    if list.balance_width:
        grid_style.add(
            "FONTSIZE", (base_x - 1, 1), (base_x - 1, -1), font_size_balance
        )
        grid_style.add("ALIGN", (base_x - 1, 1), (base_x - 1, -1), "RIGHT")

    grid_style.add("TEXTCOLOR", (base_x, 1), (-1, -1), FAINT_COLOR)

    if list.double:
        grid_style.add("TOPPADDING", (base_x, 1), (-1, -1), 2)
        grid_style.add("BOTTOMPADDING", (base_x, 1), (-1, -1), 2)

    grid_style.add("VALIGN", (0, 1), (-1, -1), "TOP")
    grid_style.add("GRID", (0, 0), (-1, -1), 0.25, BORDER_COLOR)

    # Create table
    t = Table(data, colWidths=col_width, style=grid_style, repeatRows=1)

    rest = None
    avail_w = width - 2 * margin
    avail_h = height - 2 * margin - head_height - foot_height

    while t:
        # Figure out how big table will be
        t_width, t_height = t.wrapOn(p, avail_w, avail_h)

        if not rest and t_height > height - 2 * margin - head_height:
            t, rest = t.split(avail_w, avail_h)
            continue

        # Draw on canvas
        draw_header()
        t.drawOn(p, margin, height - t_height - margin - head_height)
        draw_footer()

        if rest:
            # set t to the second table and reset rest
            t, rest = (rest, None)

            # Show new page
            p.showPage()
        else:
            # Leave loop
            break

    p.save()

    return content
예제 #6
0
def appendEvaluationList(obj, document):
    elemList = []
    if hasattr(obj, 'requirement') \
       and obj.requirement is not None:
        my_catalog = zapi.getUtility(ICatalog)
        res = my_catalog.searchResults(oid_index=obj.requirement)
        if len(res) > 0:
            requirementObj = iter(res).next()
            reqTitle = requirementObj.ikName
            reqComment = requirementObj.ikComment
            elemList.append(RptPara(reqTitle, doc=document))
            elemList.append(RptPara(reqComment, doc=document))
            elemList.append(Spacer(0, 4 * mm))
    # Evaluations
    evaluations = getEvaluations(obj)
    if len(evaluations) > 0:
        styleSheet = getRptStyleSheet()
        style1 = styleSheet['Small']
        style2 = styleSheet['Infobox']
        elemList.append(RptPara('Evaluations: ', style=style2, doc=document))
        colWidths = [75 * mm, 20 * mm, 40 * mm]
        data = [[
            RptPara('<b>Requirement</b>', style=style1, doc=document),
            RptPara('<b>Value</b>', style=style1, doc=document),
            RptPara('<b>Evaluator</b>', style=style1, doc=document)
        ]]
        ik_tbl_style = TableStyle([\
            ('BACKGROUND', (0, 0), (-1, 0), colors.lightgrey),
            ('LEFTPADDING', (0, 0), (-1, -1), 2 * mm),
            ('RIGHTPADDING', (0, 0), (-1, -1), 2 * mm),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 2 * mm),
            ('TOPPADDING', (0, 0), (-1, -1), 2 * mm),
            ('FONTSIZE', (0, 0), (-1, -1), 8),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
            ('INNERGRID', (0, 0), (-1, -1), 0.25, colors.black),
            ('BOX', (0, 0), (-1, -1), 0.25, colors.black),
        ])
        pos = 0
        for evaluation in evaluations.values():
            pos = pos + 1
            if evaluation.value == 'Pass':
                ik_tbl_style.add('BACKGROUND', (1, pos), (1, pos),
                                 colors.green)
            elif evaluation.value == 'Fail':
                ik_tbl_style.add('BACKGROUND', (1, pos), (1, pos), colors.red)
            else:
                pass
            data.append([
                RptPara(evaluation.requirement.ikName,
                        style=style1,
                        doc=document),
                RptPara(evaluation.value, style=style1, doc=document),
                RptPara(evaluation.evaluator.title, style=style1,
                        doc=document),
            ])
        t0 = Table(data,
                   hAlign='RIGHT',
                   style=ik_tbl_style,
                   colWidths=colWidths)
        elemList.append(t0)
        elemList.append(Spacer(0, 4 * mm))
    return elemList
예제 #7
0
    def _get_style(self, rows):

        '''
            set TableStyle 
            add styles for row/col blocks
            
            style.add('SPAN', (col_s, row_s), (col_e, row_e))
            
            also set row heights
        '''
        _get_idxs = lambda x: self._get_idxs(rows, x)
        _get_se = lambda x: (x[0][0], x[-1][0])
        # (col, row)
        style = TableStyle()
        title_row = 0
        sample_row = 1
        sample_row2 = 2
        name_row = 3
        unit_row = 4

        style.add('GRID', (0, 0), (-1, -1), 0.25, colors.red)
        style.add('ALIGN', (0, unit_row), (-1, -1), 'LEFT')
        style.add('LEFTPADDING', (0, unit_row), (-1, -1), 1)


        # set style for title row
        if self.add_title:
            style.add('SPAN', (0, title_row), (-1, title_row))
            style.add('LINEBELOW', (0, 0), (-1, 0), 1.5, colors.black)

        # set style for sample row
        for s, e in self._sample_summary_row1.spans:
            style.add('SPAN', (s, sample_row), (e, sample_row))
            style.add('LINEBELOW', (s, sample_row), (e, sample_row), 1.5, colors.black)

        for s, e in self._sample_summary_row2.spans:
            style.add('SPAN', (s, sample_row2), (e, sample_row2))

        # set style for name header
        style.add('LINEABOVE', (0, name_row), (-1, name_row), 1.5, colors.black)

        # set style for unit header
        style.add('LINEBELOW', (0, unit_row), (-1, unit_row), 1.5, colors.black)

        # set style for summary rows
#        summary_idxs = [(i, v) for i, v in enumerate(rows)
#                      if isinstance(v, SummaryRow)]
        summary_idxs = _get_idxs(SummaryRow)
        for idx, summary in summary_idxs:
            style.add('LINEABOVE', (0, idx), (-1, idx), 1.5, colors.black)
            for si, se in summary.spans:
                style.add('SPAN', (si, idx), (se, idx))

        analysis_idxs = _get_idxs(AnalysisRow)
        sidx, eidx = _get_se(analysis_idxs)
#        sidx, eidx = analysis_idxs[0][0], analysis_idxs[-1][0]
        style.add('VALIGN', (0, sidx), (-1, eidx), 'MIDDLE')
        style.add('ALIGN', (0, sidx), (-1, eidx), 'CENTER')

        for idx, _analysis in analysis_idxs:
            if idx % 2 == 0:
                style.add('BACKGROUND', (0, idx), (-1, idx),
                          colors.lightgrey,
                          )

        # set for footnot rows
        footnote_idxs = _get_idxs(FootNoteRow)
        sidx, eidx = _get_se(footnote_idxs)
        style.add('VALIGN', (0, sidx), (-1, eidx), 'MIDDLE')
        for idx, _v in footnote_idxs:
            style.add('SPAN', (0, idx), (-1, idx))
#            style.add('VALIGN', (1, idx), (-1, idx), 'MIDDLE')

        footer_idxs = _get_idxs(FooterRow)
        sidx, eidx = _get_se(footer_idxs)
        style.add('VALIGN', (0, sidx), (-1, eidx), 'MIDDLE')
        for idx, v in footer_idxs:
            for si, se in v.spans:
                style.add('SPAN', (si, idx), (se, idx))

        return style
예제 #8
0
    def build_pdf(self, response):
        CONTATO = 0
        TELEFONES_PREFERENCIAL = 1

        CIDADE = 0
        ENDERECO = 1
        BAIRRO = 2
        NUMERO = 3
        GRUPO = 4
        ID = 5
        NOME = 6

        self.set_headings()
        self.set_styles()
        self.set_cabec(self.h5)
        estilo = self.h_style

        corpo_relatorio = []
        self.add_relat_title(corpo_relatorio)

        registros = self.get_data()
        for dados in registros:
            endereco = ','.join(dados[CONTATO][ENDERECO:NUMERO])

            item = [
                Paragraph(dados[CONTATO][CIDADE], estilo),
                Paragraph(dados[CONTATO][GRUPO], estilo),
                Paragraph(dados[CONTATO][NOME], estilo),
                Paragraph(endereco, estilo),
                Paragraph(dados[TELEFONES_PREFERENCIAL], estilo),
            ]
            corpo_relatorio.append(item)

        style = TableStyle([
            ('FONTSIZE', (0, 0), (-1, -1), 8),
            ('LEADING', (0, 0), (-1, -1), 7),
            ('GRID', (0, 0), (-1, -1), 0.1, colors.black),
            ('INNERGRID', (0, 0), (-1, -1), 0.1, colors.black),
            ('TOPPADDING', (0, 0), (-1, -1), 0),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 0),
            ('LEFTPADDING', (0, 0), (-1, -1), 3),
            ('RIGHTPADDING', (0, 0), (-1, -1), 3),
        ])
        style.add('VALIGN', (0, 0), (-1, -1), 'MIDDLE')

        for i, value in enumerate(corpo_relatorio):
            if len(value) <= 1:
                style.add('SPAN', (0, i), (-1, i))

            if len(value) == 0:
                style.add('INNERGRID', (0, i), (-1, i), 0, colors.black),
                style.add('GRID', (0, i), (-1, i), -1, colors.white)
                style.add('LINEABOVE', (0, i), (-1, i), 0.1, colors.black)

            if len(value) == 1:
                style.add('LINEABOVE', (0, i), (-1, i), 0.1, colors.black)

        rowHeights = 20
        t = LongTable(corpo_relatorio, rowHeights=rowHeights, splitByRow=True)
        t.setStyle(style)
        if len(t._argW) == 5:
            t._argW[0] = 1.8 * cm
            t._argW[1] = 6 * cm
            t._argW[2] = 6.5 * cm
            t._argW[3] = 9.5 * cm
            t._argW[4] = 2.4 * cm
        elif len(t._argW) == 4:
            t._argW[0] = 2 * cm
            t._argW[1] = 10 * cm
            t._argW[2] = 11.5 * cm
            t._argW[3] = 3 * cm

        for i, value in enumerate(corpo_relatorio):
            if len(value) == 0:
                t._argH[i] = 7
                continue
            for cell in value:
                if isinstance(cell, list):
                    t._argH[i] = (rowHeights) * (len(cell) -
                                                 (0 if len(cell) > 1 else 0))
                    break

        elements = [t]

        doc = SimpleDocTemplate(response,
                                pagesize=landscape(A4),
                                rightMargin=1.25 * cm,
                                leftMargin=1.25 * cm,
                                topMargin=1.1 * cm,
                                bottomMargin=0.8 * cm)
        doc.build(elements)
예제 #9
0
def pdf(request, guid):
    import settings
    import reportlab.pdfgen.canvas
    from reportlab.lib import pagesizes, units, colors, utils
    from reportlab.platypus import Paragraph, Image
    from reportlab.platypus.tables import Table, TableStyle
    from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet
    from django.contrib.humanize.templatetags.humanize import intcomma

    company = fact.models.Slot.company()
    invoice = get_object_or_404(fact.models.Invoice, pk=guid)
    if not invoice.date_posted or not invoice.date_due:
        return redirect(reverse('fact.views.detailed', kwargs={'guid':guid}))

    response = HttpResponse(mimetype='application/pdf')
    response['Content-Disposition'] = 'attachment; filename=' + _('invoice') + '-' + invoice.id + '.pdf'
    p = reportlab.pdfgen.canvas.Canvas(response, pagesize=pagesizes.A4)
    width, height = pagesizes.A4
    font = 'Helvetica'

    # Load options and payment text
    options = fact.models.Option.opt_list(request.LANGUAGE_CODE)
    for key, value in options.iteritems():
        options['payment_text'] = options['payment_text'].replace('%' + key + '%', value)
    options['payment_text'] = options['payment_text'].replace('\n', '<br/>')

    # Right-hand stuff
    x = units.cm * 14;
    p.setFont(font + '-Bold', 18)
    p.drawString(x, height-(units.cm*4.5), _('Invoice %s') % invoice.id)
    p.setFont(font, 10)
    p.drawString(x, height-(units.cm*5.5), _('Invoice date: %s') % invoice.date_invoice.strftime('%d.%m.%Y'))
    p.drawString(x, height-(units.cm*6), _('Due date: %s') % invoice.date_due.strftime('%d.%m.%Y'))

    # Logo
    img = utils.ImageReader(settings.FACT_LOGO)
    iw, ih = img.getSize()
    aspect = ih / float(iw)
    img = Image(settings.FACT_LOGO, width=units.cm*4, height=units.cm*4*aspect)
    img.drawOn(p, x+(units.cm*1), height-(units.cm*2.25))

    # Left-hand header stuff
    x = units.cm * 2;
    p.setFont(font + '-Oblique', 8)
    p.drawString(x, height-(units.cm*1.25), company['name'])
    address = company['address'].split("\n")
    base = 1.65
    for a in address:
        p.drawString(x, height-(units.cm*base), a)
        base += 0.4


    # Recipient name and address
    y = units.cm*4.5
    base = 0.5
    customer = invoice.customer
    p.setFont(font, 10)
    p.drawString(x, height-y, customer.addr_name); y += units.cm*base
    p.drawString(x, height-y, customer.addr_addr1); y += units.cm*base
    p.drawString(x, height-y, customer.addr_addr2); y += units.cm*base
    p.drawString(x, height-y, customer.addr_addr3); y += units.cm*base
    p.drawString(x, height-y, customer.addr_addr4); y += units.cm*base
    y += units.cm*2

    # Main
    p.setFont(font + '-Bold', 14)
    p.drawString(x, height-y, _('Specification'))
    y += units.cm*1
    p.setFont(font, 10)
    fmt = '{0:.2f}'

    # Get our invoice entries, headers, etc
    style = TableStyle()
    invoice_entries = []
    headers = [_('Description'), _('Amount'), _('Type'), _('Unit price'), _('VAT'), _('Net')]
    style.add('FONT', (0,0), (-1,0), font + '-Bold')
    style.add('LINEBELOW', (0,0), (-1,0), 1, colors.black)
    for entry in invoice.entries:
        invoice_entries.append([
            entry.description,
            intcomma(fmt.format(entry.quantity)),
            _(entry.action),
            intcomma(fmt.format(entry.unitprice)),
            intcomma(fmt.format(entry.tax_percent)) + '%',
            intcomma(fmt.format(entry.net))
        ])
    style.add('LINEBELOW', (0, len(invoice_entries)), (-1, len(invoice_entries)), 1, colors.black)
    sums = []
    sums.append([_('Net'), '', '', '', '', intcomma(fmt.format(invoice.net))])
    sums.append([_('VAT'), '', '', '', '', intcomma(fmt.format(invoice.tax))])
    if invoice.payments.count() > 0:
        sums.append([_('Subtotal'), '', '', '', '', intcomma(fmt.format(invoice.gross))])
        style.add('LINEBELOW', (0, len(invoice_entries)+3), (-1, len(invoice_entries)+3), 1, colors.black)
        for payment in invoice.payments.all():
            sums.append([_('Paid %s') + payment.post_date.strftime('%d.%m.%Y'), '', '', '', '', intcomma(fmt.format(payment.amount))])
        ln = len(invoice_entries) + len(sums)
        style.add('LINEBELOW', (0, ln), (-1, ln), 1, colors.black)
    else:
        style.add('LINEBELOW', (0, len(invoice_entries)+2), (-1, len(invoice_entries)+2), 1, colors.black)
    sums.append([_('Amount due'), '', '', '', '', intcomma(fmt.format(invoice.due))])
    ln = len(invoice_entries) + len(sums)
    style.add('BACKGROUND', (0, ln), (-1, ln), colors.wheat)
    style.add('FONT', (0, ln), (-1, ln), font + '-Bold')
    style.add('LINEBELOW', (0, ln), (-1, ln), 2, colors.black)

    # Draw the table
    t = Table([headers] + invoice_entries + sums,
            ([units.cm*6.5, units.cm*1.75, units.cm*2, units.cm*2.5, units.cm*2, units.cm*2.25])
            )
    t.setStyle(style)
    w, h = t.wrapOn(p, units.cm*19, units.cm*8)
    y += h
    t.drawOn(p, x, height-y)

    # Bank account number
    stylesheet = getSampleStyleSheet()
    if invoice.notes:
        txt = invoice.notes + '<br/><br/>'
    else:
        txt = ''
    txt += options['payment_text']
    pr = Paragraph(txt, stylesheet['BodyText'])
    w, h = pr.wrapOn(p, units.cm*17, units.cm*6)
    y += pr.height + (units.cm*1)
    pr.drawOn(p, x, height-y)

    # Footer stuff
    p.setFont(font + '-BoldOblique', 8)
    p.drawString(x, units.cm*2.8, company['name'])
    p.setFont(font + '-Oblique', 8)
    p.drawString(x, units.cm*2.4, address[0])
    p.drawString(x, units.cm*2, address[1])

    p.drawString(units.cm*8, units.cm*2.4, 'Web: ' + company['url'])
    p.drawString(units.cm*8, units.cm*2, 'E-post: ' + company['email'])

    p.drawString(units.cm*14, units.cm*2.4, 'Telefon: ' + company['phone'])
    p.drawString(units.cm*14, units.cm*2, 'Org.nr: ' + company['id'])

    # Close the PDF object cleanly, and we're done.
    p.showPage()
    p.save()

    return response