Beispiel #1
0
def store_hudorainvoice(invoice, netto=True):
    """
    Übertrage eine Eingangsrechnung von HUDORA an Cyberlogi an xero.com

    Der Rückgabewert ist die xero.com InvoiceID
    """

    SKONTO_ACCOUNT = '3736'
    VERSANDKOSTEN_ACCOUNT = '3801'
    WAREN_ACCOUNT = '3400'

    invoice = make_struct(invoice)

    root = ET.Element('Invoices')
    invoice_element = ET.SubElement(root, 'Invoice')
    # Reference-Tag kann nur bei Type == 'ACCREC' gesetzt werden
    # Bei 'ACCPAY' bleibt wohl nur der Weg, die InvoiceNumber zu setzen
    # ET.SubElement(invoice, 'Reference').text = invoice.guid

    ET.SubElement(invoice_element, 'InvoiceNumber').text = "%s %s" % (invoice.guid, invoice.kundenauftragsnr)
    ET.SubElement(invoice_element, 'Type').text = 'ACCPAY'
    ET.SubElement(invoice_element, 'Status').text = 'SUBMITTED'
    ET.SubElement(invoice_element, 'LineAmountTypes').text = 'Exclusive' if netto else 'Inclusive'

    if invoice.leistungszeitpunkt:  # das Feld heisst in SoftM "leistungszeitpunkt"
        leistungsdatum = _convert_to_date(invoice.leistungszeitpunkt)
    elif invoice.rechnungsdatum:    # das Feld heisst in EDIhub "rechnungsdatum"
        leistungsdatum = _convert_to_date(invoice.rechnungsdatum)
    else:
        raise Exception('es konnte kein Leistungs-/ Rechnungsdatum gefunden werden!')

    # das Feld heisst in SoftM "zahlungsziel", in EDIhub aber "zahlungstage"
    zahlungstage = invoice.zahlungsziel or invoice.zahlungstage
    if zahlungstage:
        timedelta = datetime.timedelta(days=zahlungstage)
        ET.SubElement(invoice_element, 'DueDate').text = (leistungsdatum + timedelta).strftime('%Y-%m-%d')
    ET.SubElement(invoice_element, 'Date').text = leistungsdatum.strftime('%Y-%m-%d')

    lineitems = ET.SubElement(invoice_element, 'LineItems')
    if invoice.infotext_kunde:
        add_orderline(lineitems, invoice.infotext_kunde, 0, 0, '')
    if invoice.kundenauftragsnr:
        add_orderline(lineitems, "Kundenauftragsnr: %s" % invoice.kundenauftragsnr, 0, 0, '')

    total = Decimal(0)
    for item in invoice.orderlines:
        item = make_struct(item)
        preis = 0
        if item.menge:
            if item.preis:          # das Feld heisst "preis" in den Daten aus SoftM
                preis = cent_to_euro(item.preis / item.menge)
            elif item.warenwert:    # das Feld heisst "warenwert" in den Daten aus EDIhub
                preis = cent_to_euro(item.warenwert / item.menge)

        # Versandkosten mit spezieller AccountID verbuchen
        if 'ersandkosten' in item.infotext_kunde:
            add_orderline(lineitems, 'Paketversand DPD', item.menge, preis, VERSANDKOSTEN_ACCOUNT)
        else:
            add_orderline(lineitems, u"%s - %s" % (item.artnr, item.infotext_kunde), item.menge, preis, WAREN_ACCOUNT)

        total += preis * item.menge

    # 2 Prozent Skonto innerhalb von 8 Tagen
    add_orderline(lineitems, 'Skonto bis %s' % (datetime.date.today() + datetime.timedelta(days=8)).strftime('%Y-%m-%d'),
                             '0.02', -total, SKONTO_ACCOUNT)

    contact = ET.SubElement(invoice_element, 'Contact')
    ET.SubElement(contact, 'Name').text = 'HUDORA GmbH'
    ET.SubElement(contact, 'EmailAddress').text = '*****@*****.**'
    addresses = ET.SubElement(contact, 'Addresses')
    address = ET.SubElement(addresses, 'Address')
    ET.SubElement(address, 'AddressType').text = 'STREET'
    ET.SubElement(address, 'AttentionTo').text = 'Buchhaltung'
    ET.SubElement(address, 'City').text = 'Remscheid'
    ET.SubElement(address, 'PostalCode').text = '42897'
    ET.SubElement(address, 'Country').text = 'DE'

    body = ET.tostring(root, encoding='utf-8')
    content = xero_request(URL_BASE, "PUT", body=body, headers={'content-type': 'text/xml; charset=utf-8'})
    tree = ET.fromstring(content)
    return tree.find('Invoices/Invoice/InvoiceID').text
Beispiel #2
0
def store_invoice(invoice, tax_included=False, draft=False, xero_should_generate_invoice_number=False):
    """
    Erzeugt eine (Ausgangs-) Rechnung anhand des Simple Invoice Protocol.
    Siehe https://github.com/hudora/CentralServices/blob/master/doc/SimpleInvoiceProtocol.markdown
    """

    if draft:
        warnings.warn("draft=True is deprecated: SUBMITTED means 'submitted for approval' which is way to go for all auto-generated stuff",
                      DeprecationWarning)

    invoice = make_struct(invoice)
    root = ET.Element('Invoices')
    invoice_element = ET.SubElement(root, 'Invoice')
    ET.SubElement(invoice_element, 'Type').text = 'ACCREC'
    ET.SubElement(invoice_element, 'Status').text = 'DRAFT' if draft else 'SUBMITTED'
    ET.SubElement(invoice_element, 'LineAmountTypes').text = 'Inclusive' if tax_included else 'Exclusive'
    if invoice.kundenauftragsnr:
        ET.SubElement(invoice_element, 'Reference').text = invoice.kundenauftragsnr
    else:
        ET.SubElement(invoice_element, 'Reference').text = invoice.guid
    if not xero_should_generate_invoice_number:
        ET.SubElement(invoice_element, 'InvoiceNumber').text = invoice.guid

    leistungsdatum = _convert_to_date(invoice.leistungszeitpunkt)
    if invoice.zahlungsziel:
        leistungszeitpunkt = _convert_to_date(invoice.leistungszeitpunkt)
        timedelta = datetime.timedelta(days=invoice.zahlungsziel)
        ET.SubElement(invoice_element, 'DueDate').text = (leistungsdatum + timedelta).strftime('%Y-%m-%d')
    ET.SubElement(invoice_element, 'Date').text = leistungsdatum.strftime('%Y-%m-%d')

    lineitems = ET.SubElement(invoice_element, 'LineItems')
    if invoice.infotext_kunde:
        add_orderline(lineitems, invoice.infotext_kunde, 0, 0, '8404')
    for item in invoice.orderlines:
        item = make_struct(item) # XXX rekursives Verhalten mit in make_struct packen
    
        buchungskonto = '8404'  # default
        # wenn wir hier Ersatzteile von Neuware trenen könnten, könnten wir die Neuware auf Konto 8406
        # udn hoogoo Scooter auf Konto 8410 buchen.
        if item.buchungskonto:
            buchungskonto = item.buchungskonto
        text = unicode(item.artnr)
        if item.infotext_kunde:
            text = u"%s - %s" % (item.artnr, item.infotext_kunde)
        add_orderline(lineitems, text, item.menge, cent_to_euro(item.preis), buchungskonto)

    if invoice.versandkosten:
        add_orderline(lineitems, 'Verpackung & Versand', 1, cent_to_euro(invoice.versandkosten), '8402')

    # Adressdaten
    contact = ET.SubElement(invoice_element, 'Contact')
    ET.SubElement(contact, 'Name').text = ' '.join([invoice.name1, invoice.name2])
    ET.SubElement(contact, 'EmailAddress').text = huTools.unicode.deUmlaut(invoice.mail)
    addresses = ET.SubElement(contact, 'Addresses')
    address = ET.SubElement(addresses, 'Address')
    ET.SubElement(address, 'AddressType').text = 'POBOX' # Rechnungsadresse
    #ET.SubElement(address, 'AttentionTo').text = invoice.name1

    if invoice.name2:
        ET.SubElement(address, 'AddressLine1').text = invoice.name2
        ET.SubElement(address, 'AddressLine2').text = invoice.strasse
    else:
        ET.SubElement(address, 'AddressLine1').text = invoice.strasse

    ET.SubElement(address, 'City').text = invoice.ort
    ET.SubElement(address, 'PostalCode').text = invoice.plz
    ET.SubElement(address, 'Country').text = invoice.land
    body = ET.tostring(root, encoding='utf-8')

    content = xero_request(URL_BASE, "PUT", body=body, headers={'content-type': 'text/xml; charset=utf-8'})
    tree = ET.fromstring(content)
    return tree.find('Invoices/Invoice/InvoiceID').text