def write(cls, *args): actions = iter(args) args = [] for numbers, values in zip(actions, actions): values = values.copy() if values.get('type') == 'iban' and 'number' in values: values['number'] = iban.format(values['number']) values['number_compact'] = iban.compact(values['number']) args.extend((numbers, values)) super(BankAccountNumber, cls).write(*args) to_write = [] for number in sum(args[::2], []): if number.type == 'iban': formated_number = iban.format(number.number) compacted_number = iban.compact(number.number) if ((formated_number != number.number) or (compacted_number != number.number_compact)): to_write.extend(([number], { 'number': formated_number, 'number_compact': compacted_number, })) if to_write: cls.write(*to_write)
def write(cls, *args): actions = iter(args) args = [] for numbers, values in zip(actions, actions): values = values.copy() if values.get('type') == 'iban' and 'number' in values: values['number'] = iban.format(values['number']) values['number_compact'] = iban.compact(values['number']) args.extend((numbers, values)) super(BankAccountNumber, cls).write(*args) to_write = [] for number in sum(args[::2], []): if number.type == 'iban': formated_number = iban.format(number.number) compacted_number = iban.compact(number.number) if ((formated_number != number.number) or (compacted_number != number.number_compact)): to_write.extend(([number], { 'number': formated_number, 'number_compact': compacted_number, })) if to_write: cls.write(*to_write)
def create(cls, vlist): vlist = [v.copy() for v in vlist] for values in vlist: if values.get('type') == 'iban' and 'number' in values: values['number'] = iban.format(values['number']) values['number_compact'] = iban.compact(values['number']) return super(BankAccountNumber, cls).create(vlist)
def create(cls, vlist): vlist = [v.copy() for v in vlist] for values in vlist: if values.get('type') == 'iban' and 'number' in values: values['number'] = iban.format(values['number']) values['number_compact'] = iban.compact(values['number']) return super(BankAccountNumber, cls).create(vlist)
def _format_iban(self, cr, uid, acc_number): ''' This function removes all characters from given 'string' that isn't a alpha numeric and converts it to upper case, checks checksums and groups by 4 ''' res = '' if acc_number: _logger = logging.getLogger(__name__) _logger.dbug('FGF acc_number %s' % (acc_number)) try: a = iban.validate(acc_number) except: raise osv.except_osv(_('Error!'), (_('%s is not a valid IBAN.') % (acc_number))) res = iban.format(a) return res
def view_my_invoices(self, request): periods = {p.id.hex: p for p in request.app.periods if p.finalized} q = self.query() q = q.filter(Invoice.period_id.in_(periods.keys())) q = q.outerjoin(Period) q = q.outerjoin(InvoiceItem) q = q.options(contains_eager(Invoice.items)) q = q.order_by( Period.execution_start, Invoice.id, case([ (InvoiceItem.group == 'donation', 2), (InvoiceItem.family != None, 1), ], else_=0), InvoiceItem.group, InvoiceItem.text) invoices = tuple(q) users = users_for_select_element(request) user = request.session.query(User).filter_by(id=self.user_id).first() if request.current_user.id == self.user_id: title = _("Invoices") else: title = _("Invoices of ${user}", mapping={'user': user.title}) # make sure the invoice is set up with the latest configured reference, # which may result in a new reference record being added - this is done # ad-hoc on an invoice to invoice basis since we do not need a new # reference for an invoice that is never looked at for invoice in invoices: if not invoice.paid: self.schema.link(request.session, invoice) if self.schema.name == 'feriennet-v1': account = request.app.org.meta.get('bank_account') account = account and iban.format(account) else: account = request.app.org.meta.get('bank_esr_participant_number') beneficiary = request.app.org.meta.get('bank_beneficiary') payment_provider = request.app.default_payment_provider layout = InvoiceLayout(self, request, title) def payment_button(title, price): price = payment_provider.adjust_price(price) label = ': '.join((request.translate(_("Pay Online Now")), render_macro(layout.macros['price'], layout.request, { 'layout': layout, 'price': price, 'show_fee': True }))) return request.app.checkout_button(button_label=label, title=title, price=price, email=user.username, locale=request.locale) def user_select_link(user): return request.class_link(InvoiceCollection, { 'username': user.username, }) return { 'title': title, 'layout': layout, 'users': users, 'user': user, 'user_select_link': user_select_link, 'invoices': invoices, 'model': self, 'account': account, 'payment_provider': payment_provider, 'payment_button': payment_button, 'beneficiary': beneficiary, 'invoice_bucket': request.app.invoice_bucket() }
def caption(self, value): return iban.format(value)
def draw_bill(self, dwg): """Draw the bill in SVG format.""" margin = mm(5) payment_left = add_mm(RECEIPT_WIDTH, margin) payment_detail_left = add_mm(payment_left, mm(70)) grp = dwg.add(dwg.g()) # Receipt y_pos = 15 line_space = 3.5 grp.add( dwg.text(self.label("Receipt"), (margin, mm(10)), **self.title_font_info)) grp.add( dwg.text(self.label("Account / Payable to"), (margin, mm(y_pos)), **self.head_font_info)) y_pos += line_space grp.add( dwg.text(iban.format(self.account), (margin, mm(y_pos)), **self.font_info)) y_pos += line_space for line_text in self.creditor.as_paragraph( max_chars=MAX_CHARS_RECEIPT_LINE): grp.add(dwg.text(line_text, (margin, mm(y_pos)), **self.font_info)) y_pos += line_space if self.ref_number: y_pos += 1 grp.add( dwg.text(self.label("Reference"), (margin, mm(y_pos)), **self.head_font_info)) y_pos += line_space grp.add( dwg.text(format_ref_number(self), (margin, mm(y_pos)), **self.font_info)) y_pos += line_space y_pos += 1 grp.add( dwg.text( self.label("Payable by") if self.debtor else self.label("Payable by (name/address)"), (margin, mm(y_pos)), **self.head_font_info)) y_pos += line_space if self.debtor: for line_text in self.debtor.as_paragraph( max_chars=MAX_CHARS_RECEIPT_LINE): grp.add( dwg.text(line_text, (margin, mm(y_pos)), **self.font_info)) y_pos += line_space else: self.draw_blank_rect(dwg, grp, x=margin, y=mm(y_pos), width=mm(52), height=mm(25)) y_pos += 28 grp.add( dwg.text(self.label("Currency"), (margin, mm(72)), **self.head_font_info)) grp.add( dwg.text(self.label("Amount"), (add_mm(margin, mm(12)), mm(72)), **self.head_font_info)) grp.add(dwg.text(self.currency, (margin, mm(77)), **self.font_info)) if self.amount: grp.add( dwg.text(format_amount(self.amount), (add_mm(margin, mm(12)), mm(77)), **self.font_info)) else: self.draw_blank_rect(dwg, grp, x=add_mm(margin, mm(25)), y=mm(75), width=mm(27), height=mm(11)) # Right-aligned grp.add( dwg.text(self.label("Acceptance point"), (add_mm(RECEIPT_WIDTH, margin * -1), mm(91)), text_anchor='end', **self.head_font_info)) # Top separation line if self.top_line: grp.add( dwg.line(start=(0, mm(0.141)), end=(add_mm(RECEIPT_WIDTH, PAYMENT_WIDTH), mm(0.141)), stroke='black', stroke_dasharray='2 2')) # Separation line between receipt and payment parts if self.payment_line: grp.add( dwg.line(start=(mm(RECEIPT_WIDTH), 0), end=(mm(RECEIPT_WIDTH), mm(BILL_HEIGHT)), stroke='black', stroke_dasharray='2 2')) grp.add( dwg.text("✂", insert=(add_mm(RECEIPT_WIDTH, mm(-1.5)), 40), font_size=16, font_family='Helvetica', rotate=[90])) # Payment part grp.add( dwg.text(self.label("Payment part"), (payment_left, mm(10)), **self.title_font_info)) # Get QR code SVG from qrcode lib, read it and redraw path in svgwrite drawing. buff = BytesIO() im = self.qr_image() im.save(buff) m = re.search(r'<path [^>]*>', buff.getvalue().decode()) if not m: raise Exception( "Unable to extract path data from the QR code SVG image") m = re.search(r' d=\"([^\"]*)\"', m.group()) if not m: raise Exception( "Unable to extract path d attributes from the SVG QR code source" ) path_data = m.groups()[0] path = dwg.path( d=path_data, style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none", ) # Limit scaling to max dimension max_width = mm(45) scale_factor = min(3, (max_width / (im.width + 2))) # qr-code path doesn't start at (0,0), apply some x correction qr_left = payment_left - (3 * scale_factor) qr_top = 60 - (3 * scale_factor) path.translate(tx=qr_left, ty=qr_top) path.scale(scale_factor) grp.add(path) self.draw_swiss_cross(dwg, grp, (payment_left, 60), (im.width + 2) * scale_factor) grp.add( dwg.text(self.label("Currency"), (payment_left, mm(72)), **self.head_font_info)) grp.add( dwg.text(self.label("Amount"), (add_mm(payment_left, mm(12)), mm(72)), **self.head_font_info)) grp.add( dwg.text(self.currency, (payment_left, mm(77)), **self.font_info)) if self.amount: grp.add( dwg.text(format_amount(self.amount), (add_mm(payment_left, mm(12)), mm(77)), **self.font_info)) else: self.draw_blank_rect(dwg, grp, x=add_mm(RECEIPT_WIDTH, margin, mm(12)), y=mm(75), width=mm(40), height=mm(15)) # Right side of the bill y_pos = 10 line_space = 3.5 def add_header(text): nonlocal dwg, grp, payment_detail_left, y_pos y_pos += 1 grp.add( dwg.text(text, (payment_detail_left, mm(y_pos)), **self.head_font_info)) y_pos += line_space add_header(self.label("Account / Payable to")) grp.add( dwg.text(iban.format(self.account), (payment_detail_left, mm(y_pos)), **self.font_info)) y_pos += line_space for line_text in self.creditor.as_paragraph(): grp.add( dwg.text(line_text, (payment_detail_left, mm(y_pos)), **self.font_info)) y_pos += line_space if self.ref_number: add_header(self.label("Reference")) grp.add( dwg.text(format_ref_number(self), (payment_detail_left, mm(y_pos)), **self.font_info)) y_pos += line_space if self.extra_infos: add_header(self.label("Additional information")) if '##' in self.extra_infos: extra_infos = self.extra_infos.split('##') extra_infos[1] = '##' + extra_infos[1] else: extra_infos = [self.extra_infos] # TODO: handle line breaks for long infos (mandatory 5mm margin) for info in wrap_infos(extra_infos): grp.add( dwg.text(info, (payment_detail_left, mm(y_pos)), **self.font_info)) y_pos += line_space if self.debtor: add_header(self.label("Payable by")) for line_text in self.debtor.as_paragraph(): grp.add( dwg.text(line_text, (payment_detail_left, mm(y_pos)), **self.font_info)) y_pos += line_space else: add_header(self.label("Payable by (name/address)")) # The specs recomment at least 2.5 x 6.5 cm self.draw_blank_rect(dwg, grp, x=payment_detail_left, y=mm(y_pos), width=mm(65), height=mm(25)) y_pos += 28 if self.final_creditor: add_header(self.label("In favor of")) for line_text in self.final_creditor.as_paragraph(): grp.add( dwg.text(line_text, (payment_detail_left, mm(y_pos)), **self.font_info)) y_pos += line_space if self.due_date: add_header(self.label("Payable by ")) grp.add( dwg.text(format_date(self.due_date), (payment_detail_left, mm(y_pos)), **self.font_info)) y_pos += line_space # Bottom section y_pos = mm(94) for alt_proc_line in self.alt_procs: grp.add( dwg.text(alt_proc_line, (payment_left, y_pos), **self.proc_font_info)) y_pos += mm(2.2) return grp
def as_svg(self, file_name): bill_height = '105mm' receipt_width = '62mm' payment_width = '148mm' margin = '5mm' payment_left = add_mm(receipt_width, margin) payment_detail_left = add_mm(payment_left, '70mm') title_font_info = { 'font_size': 11, 'font_family': 'helvetica', 'font_weight': 'bold' } font_info = {'font_size': 10, 'font_family': 'helvetica'} head_font_info = { 'font_size': 8, 'font_family': 'helvetica', 'font_weight': 'bold' } dwg = svgwrite.Drawing( size=(add_mm(receipt_width, payment_width), bill_height), # A4 width, A6 height. filename=file_name, ) dwg.add(dwg.rect(insert=(0, 0), size=('100%', '100%'), fill='white')) # Force white background # Receipt y_pos = 15 line_space = 3.5 dwg.add( dwg.text(self.label("Receipt"), (margin, '10mm'), **title_font_info)) dwg.add( dwg.text(self.label("Account / Payable to"), (margin, '%smm' % y_pos), **head_font_info)) y_pos += line_space dwg.add( dwg.text(iban.format(self.account), (margin, '%smm' % y_pos), **font_info)) y_pos += line_space for line_text in self.creditor.as_paragraph(): dwg.add(dwg.text(line_text, (margin, '%smm' % y_pos), **font_info)) y_pos += line_space if self.ref_number: y_pos += 1 dwg.add( dwg.text(self.label("Reference"), (margin, '%smm' % y_pos), **head_font_info)) y_pos += line_space dwg.add( dwg.text(format_ref_number(self), (margin, '%smm' % y_pos), **font_info)) y_pos += line_space y_pos += 1 dwg.add( dwg.text( self.label("Payable by") if self.debtor else self.label("Payable by (name/address)"), (margin, '%smm' % y_pos), **head_font_info)) y_pos += line_space if self.debtor: for line_text in self.debtor.as_paragraph(): dwg.add( dwg.text(line_text, (margin, '%smm' % y_pos), **font_info)) y_pos += line_space else: self.draw_blank_rect(dwg, x=margin, y='%smm' % y_pos, width='52mm', height='25mm') y_pos += 28 dwg.add( dwg.text(self.label("Currency"), (margin, '80mm'), **head_font_info)) dwg.add( dwg.text(self.label("Amount"), (add_mm(margin, '12mm'), '80mm'), **head_font_info)) dwg.add(dwg.text(self.currency, (margin, '85mm'), **font_info)) if self.amount: dwg.add( dwg.text(format_amount(self.amount), (add_mm(margin, '12mm'), '85mm'), **font_info)) else: self.draw_blank_rect(dwg, x=add_mm(margin, '25mm'), y='77mm', width='27mm', height='11mm') # Right-aligned dwg.add( dwg.text(self.label("Acceptance point"), (add_mm(receipt_width, '-' + margin), '91mm'), text_anchor='end', **head_font_info)) # Separation line between receipt and payment parts dwg.add( dwg.line(start=(receipt_width, 0), end=(receipt_width, bill_height), stroke='black', stroke_dasharray='2 2')) dwg.add( dwg.text("✂", insert=(add_mm(receipt_width, '-1.5mm'), 40), font_size=16, font_family='helvetica', rotate=[90])) # Payment part dwg.add( dwg.text(self.label("Payment part"), (payment_left, '10mm'), **title_font_info)) # Get QR code SVG from qrcode lib, read it and redraw path in svgwrite drawing. buff = BytesIO() im = self.qr_image() im.save(buff) m = re.search(r'<path [^>]*>', buff.getvalue().decode()) if not m: raise Exception( "Unable to extract path data from the QR code SVG image") m = re.search(r' d=\"([^\"]*)\"', m.group()) if not m: raise Exception( "Unable to extract path d attributes from the SVG QR code source" ) path_data = m.groups()[0] path = dwg.path( d=path_data, style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none", ) path.translate(tx=250, ty=60) # Limit scaling to some max dimensions scale_factor = 3 - (max(im.width - 60, 0) * 0.05) path.scale(sx=scale_factor, sy=scale_factor) dwg.add(path) self.draw_swiss_cross(dwg, im.width * scale_factor) dwg.add( dwg.text(self.label("Currency"), (payment_left, '80mm'), **head_font_info)) dwg.add( dwg.text(self.label("Amount"), (add_mm(payment_left, '12mm'), '80mm'), **head_font_info)) dwg.add(dwg.text(self.currency, (payment_left, '85mm'), **font_info)) if self.amount: dwg.add( dwg.text(format_amount(self.amount), (add_mm(payment_left, '12mm'), '85mm'), **font_info)) else: self.draw_blank_rect(dwg, x=add_mm(receipt_width, margin, '12mm'), y='83mm', width='40mm', height='15mm') # Right side of the bill y_pos = 10 line_space = 3.5 def add_header(text): nonlocal dwg, payment_detail_left, y_pos y_pos += 1 dwg.add( dwg.text(text, (payment_detail_left, '%smm' % y_pos), **head_font_info)) y_pos += line_space add_header(self.label("Account / Payable to")) dwg.add( dwg.text(iban.format(self.account), (payment_detail_left, '%smm' % y_pos), **font_info)) y_pos += line_space for line_text in self.creditor.as_paragraph(): dwg.add( dwg.text(line_text, (payment_detail_left, '%smm' % y_pos), **font_info)) y_pos += line_space if self.ref_number: add_header(self.label("Reference")) dwg.add( dwg.text(format_ref_number(self), (payment_detail_left, '%smm' % y_pos), **font_info)) y_pos += line_space if self.extra_infos: add_header(self.label("Additional information")) if '##' in self.extra_infos: extra_infos = self.extra_infos.split('##') extra_infos[1] = '##' + extra_infos[1] else: extra_infos = [self.extra_infos] # TODO: handle line breaks for long infos (mandatory 5mm margin) for info in wrap_infos(extra_infos): dwg.add( dwg.text(info, (payment_detail_left, '%smm' % y_pos), **font_info)) y_pos += line_space if self.debtor: add_header(self.label("Payable by")) for line_text in self.debtor.as_paragraph(): dwg.add( dwg.text(line_text, (payment_detail_left, '%smm' % y_pos), **font_info)) y_pos += line_space else: add_header(self.label("Payable by (name/address)")) # The specs recomment at least 2.5 x 6.5 cm self.draw_blank_rect(dwg, x=payment_detail_left, y='%smm' % y_pos, width='65mm', height='25mm') y_pos += 28 if self.final_creditor: add_header(self.label("In favor of")) for line_text in self.final_creditor.as_paragraph(): dwg.add( dwg.text(line_text, (payment_detail_left, '%smm' % y_pos), **font_info)) y_pos += line_space if self.due_date: add_header(self.label("Payable by ")) dwg.add( dwg.text(format_date(self.due_date), (payment_detail_left, '%smm' % y_pos), **font_info)) y_pos += line_space dwg.save()
def caption(self, value: str) -> str: return cast(str, iban.format(value))
def pre_save_account(sender, instance, **kwargs): instance.iban = iban.format(instance.iban)