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
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