示例#1
0
    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)
示例#2
0
文件: bank.py 项目: coopengo/bank
    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)
示例#3
0
文件: bank.py 项目: coopengo/bank
 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)
示例#4
0
 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)
示例#5
0
 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
示例#6
0
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()
    }
示例#7
0
 def caption(self, value):
     return iban.format(value)
示例#8
0
    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
示例#9
0
    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()
示例#10
0
 def caption(self, value: str) -> str:
     return cast(str, iban.format(value))
示例#11
0
def pre_save_account(sender, instance, **kwargs):

    instance.iban = iban.format(instance.iban)