def print_order_parts_make_procedures(order_parts_ids): global dao s = ParagraphStyle(name = "zouzz", fontName = 'Helvetica', fontSize=14, leading=16) #, borderWidth=1, borderColor=colors.black) filename = make_pdf_filename("PartsProcedure_{}_".format(123321)) ladderDoc = changing_headers_PDF(filename) complete_document = [] for order_id, parts_ids in dao.order_part_dao.sort_part_id_on_order(order_parts_ids).iteritems(): complete_document.append(Paragraph('Header',s)) complete_document.append(FrameBreak()) complete_document.append(Paragraph('SubHeader',s)) complete_document.append(FrameBreak()) # complete_document.append(NextPageTemplate('content')) for part_id in parts_ids: part = dao.order_part_dao.find_by_id(part_id) # print_one_part(part,complete_document) # complete_document.append(NextPageTemplate('begin_section')) complete_document.append(PageBreak()) ladderDoc.build(complete_document,canvasmaker=NumberedCanvas) open_pdf(filename)
def print_preorder(preorder_id): preorder = dao.order_dao.find_by_id(preorder_id) # open transaction ! filename = make_pdf_filename("PreOrder_{}".format(preorder.preorder_label)) _make_preorder_report(preorder,filename) session().close() open_pdf(filename) return True
def print_employees_badges(dao): global header_text global sub_header_text header_text = "" sub_header_text = _("Employees badges") s = ParagraphStyle(name="zou", fontName='Helvetica', alignment=TA_CENTER) badges_per_line = 3 array = [] row = [] employees = dao.employee_dao.all() if len(employees) == 0: return i = 0 for employee in employees: row.append([ Paragraph(employee.fullname, s), platypus.Spacer(0, 0.25 * cm), createBarcodeDrawing('EAN13', value=str( BarCodeIdentifier.code_for(employee)), barHeight=1 * cm) ]) i = i + 1 if i == badges_per_line: array.append(row) row = [] i = 0 if i > 0: array.append(row) t = platypus.Table(array, repeatRows=0, colWidths=[6 * cm] * badges_per_line, rowHeights=[3 * cm] * len(array)) # Repeat the table header ts = platypus.TableStyle([('FONT', (0, 0), (-1, -1), 'Helvetica', 8)]) ts.add('ALIGN', (0, 0), (-1, -1), 'CENTER') ts.add('VALIGN', (0, 0), (-1, -1), 'MIDDLE') ts.add("LEFTPADDING", (0, 0), (-1, -1), 0) ts.add("RIGHTPADDING", (0, 0), (-1, -1), 0) ts.add('INNERGRID', (0, 0), (-1, -1), 0.25, colors.black) ts.add('BOX', (0, 0), (-1, -1), 0.25, colors.black) t.setStyle(ts) complete_document = [] complete_document.append(t) filename = make_pdf_filename("EmployeeBadges") ladderDoc = start_PDF(filename) ladderDoc.build(complete_document, canvasmaker=NumberedCanvas) open_pdf(filename)
def print_monthly_report(dao, month_date): strip_style = ParagraphStyle(name="regular", fontName='Helvetica-Bold', fontSize=16, spaceAfter=0, spaceBefore=0) s = ParagraphStyle(name="regular", fontName='Courrier', fontSize=7) order_style = ParagraphStyle(name="regular", fontName='Helvetica-Bold', fontSize=14, spaceAfter=6, spaceBefore=12) small = ParagraphStyle(name="regular", fontName='Helvetica', fontSize=8) small_right = ParagraphStyle(name="regular", fontName='Helvetica', fontSize=8, alignment=TA_RIGHT) client = ParagraphStyle(name="regular", fontName='Helvetica-Bold', fontSize=9) right_align = ParagraphStyle(name="right_align", fontName='Courier', fontSize=8, alignment=TA_RIGHT) right_align_bold = ParagraphStyle(name="right_align", fontName='Courier-Bold', fontSize=8, alignment=TA_RIGHT) complete_document = [] spacer = platypus.Spacer(1, 50) ts_begin = _first_moment_of_month(month_date) ts_end = _last_moment_of_month(month_date) # mainlog.debug("Turnover from {} to {} ({})".format(ts_begin, ts_end, month_date)) # data_ops = [[crlf_to_br(h) for h in [_('Ord.'),_('Description'),_('Hours'),_('Qties'),_('Sell\nprice'),_('To bill\nthis month'),_('Encours')]]] data_ops = [[ _('Ord.'), _('Description'), _('Hours'), _('Qties'), _('Sell\nprice'), _('To bill\nthis month'), _('Encours') ]] ts = platypus.TableStyle([('FONT', (0, 0), (-1, -1), 'Courier', 8)]) last_order_id = None total_sell_price = 0 total_encours = 0 total_to_facture = 0 sub_total_sell_price = 0 sub_total_encours = 0 sub_total_h_done = sub_total_h_planned = 0 sub_total_to_facture = 0 row = 1 first_row = True row_in_order = 0 mainlog.debug("dao.order_dao.order_parts_for_monthly_report(month_date):") for part_data in dao.order_dao.order_parts_for_monthly_report(month_date): if last_order_id != part_data.order_id: last_order_id = part_data.order_id if not first_row and row_in_order >= 2: # Display sums only if there is more than one row # for the order (if only one row, then showing a # sum doesn't add any information to the user) ts.add('LINEABOVE', (5, row), (-1, row), 0.5, colors.black) ts.add('LINEABOVE', (2, row), (2, row), 0.5, colors.black) data_ops.append([ '', '', Paragraph( '{} / {}'.format(duration_to_s(sub_total_h_done), duration_to_s(sub_total_h_planned)), small_right), '', '', # Paragraph(amount_to_short_s(sub_total_sell_price) or "0,00" ,right_align), Paragraph( amount_to_short_s(sub_total_to_facture) or "0,00", right_align_bold), Paragraph( amount_to_short_s(sub_total_encours) or "0,00", right_align) ]) row += 1 sub_total_sell_price = 0 sub_total_encours = 0 sub_total_h_done = sub_total_h_planned = 0 sub_total_to_facture = 0 row_in_order = 0 ts.add('LINEABOVE', (0, row), (-1, row), 0.5, colors.black) data_ops.append([ '', Paragraph(part_data.customer_name, client), '', '', '', '', '' ]) row += 1 facture_explain = "" q_out_this_month = part_data.part_qty_out - part_data.q_out_last_month # Only give an explanation if all the qty were not done # together if part_data.q_out_last_month > 0 and q_out_this_month > 0 and q_out_this_month < part_data.qty: facture_explain = "({}) ".format(q_out_this_month) if part_data.total_estimated_time > 0: qty_work = "{} / {}".format( duration_to_s(part_data.part_worked_hours) or "0,00", duration_to_s(part_data.total_estimated_time)) else: qty_work = "-" if part_data.qty > 0: qty_str = "{} / {}".format(part_data.part_qty_out, part_data.qty) else: qty_str = "-" data_ops.append([ Paragraph(part_data.human_identifier, small), Paragraph(part_data.description, small), Paragraph(qty_work, small_right), Paragraph(qty_str, small_right), Paragraph(amount_to_short_s(part_data.total_sell_price), right_align), Paragraph( facture_explain + amount_to_short_s(part_data.bill_this_month), right_align_bold), Paragraph(amount_to_short_s(part_data.encours), right_align) ]) # if part_data.bill_this_month or True: # print("{} {} {}".format(part_data.human_identifier, part_data.part_qty_out, amount_to_short_s(part_data.bill_this_month))) row_in_order += 1 row += 1 sub_total_sell_price += total_sell_price sub_total_to_facture += part_data.bill_this_month sub_total_encours += part_data.encours sub_total_h_done += part_data.part_worked_hours or 0 sub_total_h_planned += part_data.total_estimated_time or 0 total_to_facture += part_data.bill_this_month total_encours += part_data.encours first_row = False data_ops.append([ '', '', '', '', '', # Removed total_sell_price because it is misleading Paragraph(amount_to_short_s(total_to_facture), right_align_bold), Paragraph(amount_to_short_s(total_encours), right_align) ]) ts.add('LINEABOVE', (0, len(data_ops) - 1), (-1, len(data_ops) - 1), 1, colors.black) ts.add('FONT', (0, 0), (-1, 0), 'Helvetica-Bold', 9) ts.add('LINEBELOW', (0, 0), (-1, 0), 1, colors.black) t = platypus.Table(data_ops, repeatRows=1, colWidths=[ 1.50 * cm, 6 * cm, 2.5 * cm, 1.75 * cm, 2.25 * cm, 2.25 * cm ]) t.setStyle(ts) t.hAlign = "LEFT" complete_document.append(t) complete_document.append(platypus.Spacer(0, 10)) filename = make_pdf_filename("MonthlyOverview_") ladderDoc = basic_PDF(filename) ladderDoc.subject = _("Monthly financial report") ladderDoc.title = date_to_my(month_date, True) ladderDoc.build(complete_document, canvasmaker=NumberedCanvas) open_pdf(filename) return True
def print_machines_barcodes(): global header_text global sub_header_text s = ParagraphStyle(name="zou", fontName='Helvetica', fontSize=14, alignment=TA_CENTER) title_style = ParagraphStyle(name="regular", fontName='Helvetica', fontSize=24, spaceBefore=34, spaceAfter=34) zone_style = ParagraphStyle(name="zone-style", fontName='Helvetica-Bold', fontSize=24, spaceBefore=34, spaceAfter=34) badges_per_line = 3 smachines = sort_machines(machine_service.all_machines()) # I need an instance to call barcode identifier barcode_machine = Machine() if len(smachines) == 0: return complete_document = [] for clock_zone in sorted(smachines.keys()): complete_document.append( Paragraph(u">>> {}".format(clock_zone or _("Without zone")), zone_style)) machines = smachines[clock_zone] if not machines: continue for operation_name, machines in machines.items(): array = [] row = [] i = 0 for machine in machines: barcode_machine.resource_id = machine.resource_id bc = createBarcodeDrawing( 'EAN13', value=str(BarCodeIdentifier.code_for(barcode_machine)), width=5.5 * cm, barHeight=1.5 * cm) row.append([ Paragraph(u"{}".format(machine.fullname), s), platypus.Spacer(0, 0.25 * cm), bc ]) i = i + 1 if i == badges_per_line: array.append(row) row = [] i = 0 # Handle the last non complete row if i > 0: array.append(row) t = platypus.Table(array, repeatRows=0, colWidths=[6.5 * cm] * badges_per_line, rowHeights=[3 * cm] * len(array)) ts = platypus.TableStyle([('FONT', (0, 0), (-1, -1), 'Helvetica', 8)]) ts.add('ALIGN', (0, 0), (-1, -1), 'CENTER') ts.add('VALIGN', (0, 0), (-1, -1), 'MIDDLE') ts.add("LEFTPADDING", (0, 0), (-1, -1), 0) ts.add("RIGHTPADDING", (0, 0), (-1, -1), 0) ts.add('INNERGRID', (0, 0), (-1, -1), 0.25, colors.black) ts.add('BOX', (0, 0), (-1, -1), 0.25, colors.black) t.setStyle(ts) complete_document.append( KeepTogether([Paragraph(operation_name, title_style), t])) # complete_document.append( Paragraph(_("Operation {}").format(opid), title_style)) # complete_document.append(t) complete_document.append(PageBreak()) filename = make_pdf_filename("MachineBarcodes_") ladderDoc = basic_PDF(filename) ladderDoc.title = "" ladderDoc.subject = _(u"Machines bar codes") ladderDoc.build(complete_document, canvasmaker=NumberedCanvas) open_pdf(filename)
def print_delivery_slip(dao, slip_id): filename = make_pdf_filename("DeliverySlip_{}_".format(slip_id)) _make_delivery_slip(dao, slip_id, filename) open_pdf(filename) return True
def print_iso_status(dao, order_id): filename = make_pdf_filename("ISOReport_") _print_iso_status(dao, order_id, filename) open_pdf(filename)
def print_production_status_detailed(dao): strip_style = ParagraphStyle(name="regular", fontName='Helvetica-Bold', fontSize=16, spaceAfter=0, spaceBefore=0) s = ParagraphStyle(name="regular", fontName='Courrier', fontSize=7) order_style = ParagraphStyle(name="regular", fontName='Helvetica-Bold', fontSize=14, spaceAfter=6, spaceBefore=12) small = ParagraphStyle(name="regular", fontName='Helvetica', fontSize=8) right_align = ParagraphStyle(name="right_align", fontName='Helvetica', fontSize=12, alignment=TA_RIGHT) complete_document = [] spacer = platypus.Spacer(1, 50) # Pay attention ! Since this query is quite big, I got correlation # issues. These were solved by disabling correlation on Operation.description # In SQLA, outerjoin = LEFT outer join (all lefts, null on right if necessary) # Operation.task.of_type(TaskOnOperation) : join along task over TaskOnOperation subtype (cf. SQLA documentation) # I also had issue when moving SQLA 8.x to 9.x. I had to replace the contains_eager(...,Operation.task.of_type(TaskOnOperation),...) # with contains_eager(...,Operation.task,...). A few test have shown it works, but I'm not 100% sure # why... I think using of_type(...) in contains_eager is faulty but SQLA didn't complain... # outerjoin(Operation.task.of_type(TaskOnOperation)).\ r = session().query(Order).\ outerjoin(OrderPart).\ outerjoin(ProductionFile).\ outerjoin(Operation).\ outerjoin(TaskOnOperation).\ outerjoin(TimeTrack).join(Customer).\ options(contains_eager(Order.parts,OrderPart.production_file,ProductionFile.operations, Operation.tasks, TaskOnOperation.timetracks)).\ filter(Order.state == OrderStatusType.order_ready_for_production).\ order_by(Customer.fullname,Order.accounting_label,OrderPart.position,Operation.position).\ all() orders = [] for order in r: if order not in orders: orders.append(order) opdefs = dao.operation_definition_dao.all_direct() opdef_from_id = dict() for opdef in opdefs: opdef_from_id[opdef.short_id] = opdef operations_columns = 10 data_ops = [] data_ops.append([_("NOrd"), _("Customer (d/l-Price)")] + [str(i) for i in range(1, operations_columns + 1)] + [_('Tot')]) data_ops.append([_("QLft"), _("Designation")] + [''] * operations_columns + [""]) highlights = [] current_line = 0 orders_separators_rows = [] for order in orders: for part in order.parts: qty_left_to_do = part.qty - part.tex2 if qty_left_to_do > 0 and part.operations: dl = "-" if part.deadline: dl = date_to_dm(part.deadline) data1 = [ part.human_identifier, u"{} ({},{}€)".format( order.customer.fullname[0:10], dl, nice_round(part.sell_price, 1) or "-") ] data2 = [part.qty, part.description[0:26].replace('\t', ' ')] # qty_left_to_do total_planned_hours = total_done_hours = 0 total_planned_hours_left = 0 for op in part.operations: done_hours = 0 employee = None multi_employee = "" if op.tasks: for task in op.tasks: for t in task.timetracks: done_hours += t.duration if not employee: # We take the first employee employee = t.employee elif employee != t.employee: multi_employee = "+" total_done_hours += done_hours if op.operation_model: if not employee: employee = "" else: employee = employee.fullname[0:2] + multi_employee time_planned = op.planned_hours * qty_left_to_do total_planned_hours_left += time_planned total_planned_hours += op.planned_hours * part.qty data1.append(u"{}-{}".format( op.operation_model.short_id, nice_round(time_planned, 10))) data2.append(u"{} {}".format( employee, nice_round(done_hours, 10))) if done_hours > time_planned: r, c = len(data_ops) + 1, len(data1) - 1 highlights.append((c, r, c, r)) if len(data1) >= 2 + operations_columns: # Too many operations for one line, so I break the line. data_ops.append(data1) data_ops.append(data2) data1 = ["", "--->"] data2 = ["", "--->"] r = 2 + operations_columns - len(data1) if r > 0: data1 += [""] * r data2 += [""] * r data1.append(nice_round(total_planned_hours_left, 1)) data2.append(nice_round(total_done_hours, 1)) if total_done_hours > 0 and total_done_hours >= 0.6 * total_planned_hours: c = len(data2) - 1 r = len(data_ops) + 1 highlights.append((c, r, c, r)) data_ops.append(data1) data_ops.append(data2) orders_separators_rows.append(len(data_ops) - 1) t = platypus.Table(data_ops, repeatRows=2) ts = platypus.TableStyle([('FONT', (0, 0), (-1, -1), 'Courier', 8)]) ts.add("LEFTPADDING", (0, 0), (-1, -1), 0.5 * mm) ts.add("RIGHTPADDING", (0, 0), (-1, -1), 0.5 * mm) ts.add("TOPPADDING", (0, 0), (-1, -1), 1 * mm) ts.add("BOTTOMPADDING", (0, 0), (-1, -1), 1 * mm) ts.add('INNERGRID', (0, 0), (-1, -1), 0.5, colors.gray) ts.add('ALIGN', (2, 0), (-1, -1), 'RIGHT') ts.add('FONT', (0, 0), (-1, 1), 'Courier-Bold', 8) ts.add('BOX', (0, 0), (0, -1), 1, colors.black) ts.add('BOX', (1, 0), (1, -1), 1, colors.black) ts.add('BOX', (-1, 0), (-1, -1), 1, colors.black) # Totals ts.add('BOX', (0, 0), (-1, 1), 1, colors.black) # Header ts.add('BOX', (0, 0), (-1, -1), 1, colors.black) ts.add('BACKGROUND', (0, 0), (-1, 1), (0.9, 0.9, 0.9)) for i in range(int(len(data_ops) / 2)): if i % 2 == 0: # ts.add('BOX', (0, i*2), (-1, i*2+1), 1, colors.black) ts.add('BACKGROUND', (0, i * 2), (-1, i * 2 + 1), (0.95, 0.95, 0.95)) for h in highlights: ts.add('BOX', (h[0], h[1]), (h[2], h[3]), 2, colors.black) for i in orders_separators_rows: ts.add('LINEBELOW', (0, i), (-1, i), 1, colors.black) t.setStyle(ts) t.hAlign = "LEFT" complete_document.append(t) complete_document.append(platypus.Spacer(0, 10)) session().close() filename = make_pdf_filename("ProductionDetails_") ladderDoc = basic_PDF(filename) ladderDoc.title = "" ladderDoc.subject = _("Order production details") ladderDoc.build(complete_document, canvasmaker=NumberedCanvas) open_pdf(filename) return True
def print_order_report(dao, order_id, test_mode=False): global header_text,sub_header_text mainlog.debug('print_order_report order_id={}'.format(order_id)) o = dao.order_dao.find_by_id(order_id) header_text = u"{} [{}]".format(o.customer.fullname, o.customer_order_name) sub_header_text = u"Mode op\u00E9ratoire" big_order_nr = ParagraphStyle(name = "subtitle", fontName = 'Helvetica-Bold', fontSize=24, leading=26) topstyle = ParagraphStyle(name = "zou", fontName = 'Helvetica', fontSize=16) p = platypus.Paragraph(u"<b>Client {}, commande #{}</b>".format(o.customer.customer_id,o.accounting_label),topstyle) spacer = platypus.Spacer(1,50) centered = ParagraphStyle(name = "zou", fontName = 'Helvetica-bold', alignment=TA_CENTER, fontSize=14) #, borderWidth=1, borderColor=colors.black) s = ParagraphStyle(name = "zou", fontName = 'Helvetica', fontSize=14, leading=16) #, borderWidth=1, borderColor=colors.black) page_number_style = ParagraphStyle(name = "page_number_style", fontName = 'Helvetica', alignment=TA_RIGHT, fontSize=12, leading=12) #, borderWidth=1, borderColor=colors.black) opNumberStyle = ParagraphStyle(name = "zou", fontName = 'Helvetica-bold', alignment=TA_CENTER, fontSize=28,leading=28) #, borderWidth=1, borderColor=colors.black) complete_document = [] global satisfied satisfied = False sections.clear() headings_frame = HeadingsFrame(*basic_frame_dimensions) # complete_document.append(DocAssign("i",0)) for part in o.parts: # Build up a table with accompanying style # data_ops = [ ['Poste',None,u'Op\u00E9ration',None] ] # We build up a data model and the appropriate styling information titles_row = [] if part.production_file and len(part.production_file[0].operations) > 0: data_ops = [[Paragraph(part.human_identifier,big_order_nr), Paragraph(escape_html(part.description),subtitle_style)], [SubSectionNumber(part.human_identifier, page_number_style), Paragraph(_("Quantity : {} - Deadline: {}").format(part.qty, date_to_dmy(part.deadline)),subtitle_style)]] ts = platypus.TableStyle() ts.add('GRID',(0,0),(-1,-1),0.5,colors.black) ts.add('VALIGN', (0, 0), (-1, -1), 'TOP') ts.add('ALIGN', (0, 1), (-1, 1), 'RIGHT') start_mark = PageMarker() complete_document.append( start_mark) header_maker = HeaderMaker(data_ops, ts, col_widths=compute_strut([3.8*cm, None], A4[0]-1*cm)) complete_document.append(HeaderSetter( header_maker)) operation_ndx = 1 for op in part.production_file[0].operations: complete_document.append( KeepTogether( [ make_boxes(operation_ndx, op, test_mode), platypus.Spacer(1,0.1*cm) ] )) operation_ndx += 1 end_mark = PageMarker() complete_document.append( end_mark) sections[part.human_identifier] = (start_mark, end_mark) complete_document.append(HeaderSetter(None)) complete_document.append(PageBreak()) # complete_document.append(platypus.Spacer(1,30)) session().close() # FIXME Dirty if len(complete_document) > 0: filename = make_pdf_filename("OrderAndParts_{}_".format(order_id)) ladderDoc = basic_PDF(filename,body_frame=headings_frame) ladderDoc.subject = u"Mode op\u00E9ratoire" ladderDoc.title = u"Client {}".format(o.customer.customer_id) ladderDoc.multiBuild(complete_document,canvasmaker=NumberedCanvas) open_pdf(filename) return True else: raise ServerException( ServerErrors.printing_an_empty_report)
def print_supply_order(supply_order_id): filename = make_pdf_filename("SupplyOrder_{}_".format(supply_order_id)) _make_supply_order(supply_order_id,filename) open_pdf(filename) return True
def print_presence_tasks(dao): global header_text, sub_header_text header_text = "" sub_header_text = _("Presence tasks") s = ParagraphStyle(name="zou", fontName='Helvetica', alignment=TA_CENTER) topstyle = ParagraphStyle(name="zou", fontName='Helvetica-Bold', alignment=TA_CENTER, fontSize=24) array = [] row = [] row.append([ Paragraph(_("Clock IN"), topstyle), platypus.Spacer(0, 1 * cm), createBarcodeDrawing( 'EAN13', value=str(BarCodeIdentifier.code_for(TaskActionReportType.day_in)), width=10 * cm, height=4 * cm), platypus.Spacer(0, 0.5 * cm) ]) array.append(row) array.append([]) row = [] row.append([ Paragraph(_("Clock OUT"), topstyle), platypus.Spacer(0, 1 * cm), createBarcodeDrawing('EAN13', value=str( BarCodeIdentifier.code_for( TaskActionReportType.day_out)), width=10 * cm, height=4 * cm), platypus.Spacer(0, 0.5 * cm) ]) array.append(row) t = platypus.Table(array, repeatRows=1) # Repeat the table header ts = platypus.TableStyle([('FONT', (0, 0), (-1, -1), 'Helvetica', 8)]) ts.add('ALIGN', (0, 0), (-1, -1), 'CENTER') ts.add('VALIGN', (0, 0), (-1, -1), 'MIDDLE') ts.add("LEFTPADDING", (0, 0), (-1, -1), 0) ts.add("RIGHTPADDING", (0, 0), (-1, -1), 0) ts.add('INNERGRID', (0, 0), (-1, -1), 0.25, colors.black) ts.add('BOX', (0, 0), (-1, -1), 0.25, colors.black) t.setStyle(ts) complete_document = [] complete_document.append(t) filename = make_pdf_filename("NonBillableTasks") ladderDoc = start_PDF(filename) ladderDoc.build(complete_document, canvasmaker=NumberedCanvas) open_pdf(filename)
def print_non_billable_tasks(dao): global header_text, sub_header_text header_text = "" sub_header_text = _("Non billable tasks") s = ParagraphStyle(name="zou", fontName='Helvetica', alignment=TA_CENTER) complete_document = [] tasks_per_line = 3 array = [] row = [] operation_definitions_list = dao.operation_definition_dao.all_imputable_unbillable( date.today()) # FIXME If I don't do this, then accesing opdef description # after session close reopens the session... operation_definitions = [(opdef.description, BarCodeIdentifier.code_for(opdef)) for opdef in operation_definitions_list] session().commit() if len(operation_definitions) > 0: i = 0 for description, barcode in operation_definitions: row.append([ Paragraph(description, s), platypus.Spacer(0, 0.5 * cm), createBarcodeDrawing('EAN13', value=str(barcode), width=5 * cm, height=2 * cm), platypus.Spacer(0, 0.5 * cm) ]) i = i + 1 if i == tasks_per_line: array.append(row) row = [] i = 0 t = platypus.Table(array, repeatRows=1, colWidths=[6 * cm] * tasks_per_line) # Repeat the table header ts = platypus.TableStyle([('FONT', (0, 0), (-1, -1), 'Helvetica', 8)]) ts.add('ALIGN', (0, 0), (-1, -1), 'CENTER') ts.add('VALIGN', (0, 0), (-1, -1), 'MIDDLE') ts.add("LEFTPADDING", (0, 0), (-1, -1), 0) ts.add("RIGHTPADDING", (0, 0), (-1, -1), 0) ts.add('INNERGRID', (0, 0), (-1, -1), 0.25, colors.black) ts.add('BOX', (0, 0), (-1, -1), 0.25, colors.black) t.setStyle(ts) complete_document.append(t) else: complete_document.append( Paragraph( _("There currently are no unbillable operations defined"), s)) filename = make_pdf_filename("NonBillableTasks") ladderDoc = start_PDF(filename) ladderDoc.build(complete_document, canvasmaker=NumberedCanvas) open_pdf(filename)