Ejemplo n.º 1
0
def get_changed_after(date):
    """Returns a list of all Kundennummern where the underlying Data has changed since <date>."""

    date = int(date.strftime('1%y%m%d'))
    rows1 = query('XKD00', fields=['KDKDNR'], condition="KDDTER>%d OR KDDTAE>=%d" % (date, date))
    rows2 = query('AKZ00', fields=['KZKDNR'], condition="KZDTAE>=%d" % (date))
    return list(set(["SC%s" % int(x[0]) for x in rows1]) | set(["SC%s" % int(x[0]) for x in rows2]))
Ejemplo n.º 2
0
def get_rechnung(rechnungsnr):
    """Findet eine Rechnung anhand ihrer Rechnungsnr"""

    conditions = ["FKSTAT <> 'X'",
                  "FKRGNR = %d" % remove_prefix(rechnungsnr, 'RG')]
    rows = query(tables=['AFK00'], condition=' AND '.join(conditions), limit=1, ua='husoftm2.rechnungen')
    if not rows:
        return
    rechnung = rows[0]

    # Rechnungspositionen
    conditions = ["FURGNR <> 'X'"]
    rows = query(tables=['AFU00'], condition='FURGNR = %d' % remove_prefix(rechnungsnr, 'RG'),
                 ua='husoftm2.rechnungen')

    rechnung['positionen'] = rows

    # Evtl. in Funktion auslagern wie in husoftm2.kunden:
    rechnung['rechnungsnr'] = add_prefix(rechnung['rechnungsnr'], 'RG')
    rechnung['auftragsnr'] = add_prefix(rechnung['auftragsnr'], 'SO')
    rechnung['kundennr_rechnungsempfaenger'] = add_prefix(rechnung['kundennr_rechnungsempfaenger'], 'SC')
    rechnung['kundennr_warenempfaenger'] = add_prefix(rechnung['kundennr_warenempfaenger'], 'SC')
    if rechnung['verbandsnr']:
        rechnung['verbandsnr'] = add_prefix(rechnung['verbandsnr'], 'SC')

    return rechnung
Ejemplo n.º 3
0
def abgabepreis_kunde(artnr, kundennr, auftragsdatum=None):
    """
    Verkaufspreis für einen Artikel in Abhängigkeit von kundennr und Auftragsdatum ermitteln.

    Höchste Priorität hat der für einen Kunden hinterlegt Preis.
    Zweithöchste Priorität hat der für die Preisliste (Kundengruppe) hinterlegte Preis
    Niedrigste Priorität hat der Listenpreis aus den Artikelstammdaten.

    Rückgabe ist tuple mit Preis und Herkunft des Preises.

    >>> abgabepreis_kunde('04711', 99954)
    (1500, 'Preisliste 95')

    >>> abgabepreis_kunde('04711', 98000)
    (1400, 'Listenpreis')

    >>> abgabepreis_kunde('04711', 94763)
    (1300, 'Kundenpreis')

    """

    if not auftragsdatum:
        auftragsdatum = datetime.date.today()

    # Kundennr als Zeichenkette
    kundennr = remove_prefix(kundennr, 'SC')
    date_str = sql_quote(date2softm(auftragsdatum))

    # 1. Preis für Kunde hinterlegt?
    conditions = ["PNSANR=PRSANR",
                  "PRANW='A'",
                  "PRSTAT=' '",
                  "PNSTAT=' '",
                  "PRARTN=%s" % sql_quote(artnr),
                  "PRDTBI>=%s" % date_str,
                  "PRDTVO<=%s" % date_str,
                  ]
    condition_kunde = conditions + ["PRKDNR=%s" % pad('PRKDNR', kundennr)]
    rows = query(['XPN00', 'XPR00'], fields=['PNPRB'], condition=' AND '.join(condition_kunde),
                 ordering='PRDTVO', limit=1)
    if rows:
        return (int(rows[0][0] * 100), 'Kundenpreis')

    # 2. Preis aus Preislistennr. des Kunden ermitteln
    condition_gruppe = conditions + [
                            # "PRPRLK = %s" % sql_quote(kunde['kunden_gruppe']),
                            "KDKDNR=%s" % pad('KDKDNR', kundennr),
                            "PRPRLK=KDKGRP"
                       ]
    rows = query(['XPN00', 'XPR00', 'XKD00'], fields=['PNPRB', 'PRPRLK'],
                 ordering='PRDTVO', condition=' AND '.join(condition_gruppe), limit=1)
    if rows:
        return (int(rows[0]['preis'] * 100), 'Preisliste %s' % rows[0]['preisliste_kunde'])

    # 3. Listenpreis aus Artikelstammdaten
    return (listenpreis(artnr), 'Listenpreis')
Ejemplo n.º 4
0
def get_bestellung(bestellnr):
    """Liefert alle Positionen zu einer bestellnr.

    >>> bestellungen(43123)
    [{kopfdaten},
     [{'artnr': u'64114',
      'bestellmenge': 300,
      'bestellnr': 43042,
      'created_by': 62,
      'dateifuehrungsschluessel': u'',
      'geliefert_kz': 0,
      'gelieferte_menge': 0,
      'lager': 16,
      'liefer_date': datetime.date(2009, 12, 24),
      'lieferant': u'90088',
      'menge_offen': 300,
      'position': 11,
      'status': u'',
      'streckengeschaeft': 0,
      'termin1_date': datetime.date(2009, 12, 24),
      'termin2_date': datetime.date(2009, 12, 24),
      'updated_by': 62,
      'wunsch2_date': datetime.date(2009, 12, 24),
      'wunsch_date': None,
      'zugang_date': None},
      ...]
    ]

    """

    kopf = query('EBL00', ordering=['BLBSTN DESC'],
        condition="BLSTAT<>'X' AND BLBSTN=%s" % sql_escape(bestellnr))
    if len(kopf) != 1:
        raise RuntimeError('inkonsistente Kopfdaten in EBL00')
    kopf = kursfaktorkorrektur(kopf)[0]

    # leer? WTF?
    # print query('ESL00', condition="SLBSTN=%s" % sql_escape(ponr))

    # BZT00 - zusatztexte
    # positionen = query(['EBP00', 'EWZ00'], ordering=['BPBSTN DESC', 'BPDTLT'],
    #     condition="WZBSTN=BPBSTN AND WZBSTP=BPBSTP AND BPSTAT<>'X' AND BPBSTN=%s" % sql_escape(ponr))
    positionen = query(['EBP00'], ordering=['BPBSTN DESC', 'BPDTLT'],
        condition="BPSTAT<>'X' AND BPBSTN=%s" % sql_escape(bestellnr))
    # detailierte Informationen über den Zugang gibts in EWZ00

    # AND BPKZAK=0 to get only the open ones
    # Buchungsdaten: SELECT * FROM SMKDIFP/BBU00 WHERE BUBELN = 900003977
    # Lagerveraenderung: SELECT * FROM SMKDIFP/XLB00 WHERE LBBSTN = '43072'
    # ?: SELECT * FROM EWZ00 WHERE WZBSTN = 43072
    return kopf, positionen
Ejemplo n.º 5
0
def auftragsmengen(artnr, lager=0):
    """Liefert eine Liste offener Aufträge (Warenausgänge) für einen Artikel OHNE UMLAGERUNGEN.

    >>> auftragsmengen(14865)
    {datetime.date(2009, 3, 2): 340,
     datetime.date(2009, 4, 1): 300,
     datetime.date(2009, 5, 4): 260,
     datetime.date(2009, 6, 2): 300}
    """
    conditions = [
        "APARTN=%s" % (sql_quote(artnr)),  # Artikelnummer
        "AKAUFN=APAUFN",
        "AKAUFA<>'U'",                     # kein Umlagerungsauftrag
        "APSTAT<>'X'",                     # Position nicht logisch gelöscht
        "APKZVA=0",                        # Position nicht als 'voll ausgeliefert' markiert
        "(APMNG-APMNGF) > 0",              # (noch) zu liefernde menge ist positiv
        "AKSTAT<>'X'",                     # Auftrag nicht logisch gelöscht
        "AKKZVA=0"]                        # Auftrag nicht als 'voll ausgeliefert' markiert

    if lager:
        # Achtung, hier gibt es KEIN Lager 0 in der Tabelle. D.h. APLGNR=0 gibt nix
        conditions = conditions + ["APLGNR=%d" % lager]
    rows = query(['AAP00', 'AAK00'], fields=['APDTLT', 'SUM(APMNG-APMNGF)'],
                   condition=' AND '.join(conditions),
                   ordering='APDTLT', grouping='APDTLT',
                   querymappings={'SUM(APMNG-APMNGF)': 'menge_offen', 'APDTLT': 'liefer_date'})
    return dict([(x['liefer_date'], as400_2_int(x['menge_offen'])) for x in rows if x['menge_offen'] > 0])
Ejemplo n.º 6
0
def _get_umsatz(kundennr, jahr, kundenfeld):
    """Ermittle den Umsatz im gegebenen Jahr"""

    if isinstance(jahr, datetime.date):
        jahr = jahr.year
    elif isinstance(jahr, basestring):
        jahr = int(jahr)

    # Das ist deutlich schneller als ein IN-Operator in der eigentlichen Abfrage
    kunde = husoftm2.kunden.get_kunde(kundennr)
    if kunde['land'] == 'DE':
        ktonr = 85100
    elif huTools.world.in_european_union(kunde['land']):
        ktonr = 82100
    else:
        ktonr = 81100

    conditions = ['BUJJBU=%d' % (jahr - 2000),  # Keinen Kommentar zu SoftM!
                  'BUGKTO=%s' % pad('BUGKTO', ktonr),
                  'BUPKTO=%s' % pad('BUPKTO', remove_prefix(kundennr, 'SC')),
                 ]

    rows = query(tables=['BBU00'], fields=['BUSOHA', 'SUM(BUNEBT)'], grouping=['BUSOHA'],
                 querymappings={'BUSOHA': 'art', 'SUM(BUNEBT)': 'umsatz'},
                 condition=' AND '.join(conditions), ua='husoftm2.umsatz.get_umsatz', cachingtime=86400)

    umsatz = decimal.Decimal()
    for row in rows:
        if row['art'] == 'H':
            umsatz -= decimal.Decimal(row['umsatz'])
        elif row['art'] == 'S':
            umsatz += decimal.Decimal(row['umsatz'])
    return umsatz
Ejemplo n.º 7
0
def get_kommibeleg(komminr, header_only=False):
    """Gibt einen Kommissionierbeleg zurück"""

    prefix = 'KA'
    if komminr.startswith('KB'):
        prefix = 'KB'
    komminr = remove_prefix(komminr, prefix)

    # In der Tabelle ALK00 stehen Kommissionierbelege und Lieferscheine.
    # Die Kommissionierbelege haben '0' als Lieferscheinnr.
    # Zusätzlich werden die (logisch) gelöschten Lieferscheine rausgefiltert.
    conditions = ["LKLFSN = 0", "LKKBNR = %s" % sql_quote(komminr), "LKSTAT<>'X'"]
    try:
        belege = get_ls_kb_data(conditions, header_only=header_only,
                                is_lieferschein=False)
    except RuntimeError:
        return {}

    if belege:
        beleg = belege[0]
        # Falls es bereits einen Lieferschein gibt, die Lieferscheinnr in das dict schreiben.
        # Ansonsten die Eintrag 'lieferscheinnr' entfernen (wäre sonst SL0)
        rows = query(['ALK00'], condition="LKLFSN <> 0 AND LKKBNR = %s" % sql_quote(komminr))
        if rows:
            beleg['lieferscheinnr'] = rows[0]['lieferscheinnr']
        else:
            beleg.pop('lieferscheinnr', None)
        return beleg
    return {}
Ejemplo n.º 8
0
def resolve(sachbearbeiternr):
    """Returns the name for a sachbearbeiternr"""

    if not _sachbearbeiter:
        for row in query('XSB00', fields=['SBSBNR', 'SBNAME'], cachingtime=60 * 60 * 24 * 10):
            _sachbearbeiter[str(row['id'])] = row['name']
    return _sachbearbeiter.get(str(sachbearbeiternr), '?')
Ejemplo n.º 9
0
def preislisten(gueltig_bis=None):
    """Gib die 'Namen' aller Preislisten für Kundengruppen und Kunden zurück"""

    conditions = ["PNSANR=PRSANR",
                  "PRANW='A'",
                  "PRSTAT=' '",
                  "PNSTAT=' '",
                  ]

    if gueltig_bis:
        conditions.append("PRDTBI>=%s" % date2softm(gueltig_bis))

    preislisten = husoftm2.texte.get_map('PRL')

    rows = query(tables=['XPR00', 'XPN00'],
                 fields=['PRKDNR', 'PRPRLK', 'PRARTN', 'PNPRB', 'PRDTVO', 'PRDTBI'],
                 condition=' AND '.join(conditions))
    for row in rows:
        if row['kunde']:
            row['kunde'] = add_prefix(row['kunde'], 'SC')
        if row['preisliste_kunde']:
            row['preislistenname'] = preislisten.get(row['preisliste_kunde'],
                                                     "?=%s" % row['preisliste_kunde'])

    return rows
Ejemplo n.º 10
0
def kundenpreise(kundennr, gueltig_von=None, gueltig_bis=None):
    """Alle kundenspezifischen Preis für einen Kunden"""

    kundennr = remove_prefix(kundennr, 'SC')

    conditions = ["PNSANR=PRSANR",
                  "PRANW='A'",
                  "PRSTAT=' '",
                  "PNSTAT=' '",
                  "PRKDNR=%s" % pad('PRKDNR', kundennr)
                  ]

    if gueltig_von:
        conditions.append("PRDTVO>=%s" % sql_quote(date2softm(gueltig_von)))
    if gueltig_bis:
        conditions.append("PRDTBI>=%s" % sql_quote(date2softm(gueltig_bis)))

    rows = query(tables=['XPN00', 'XPR00'],
                 fields=['PRARTN', 'PNPRB', 'PRDTVO', 'PRDTBI', 'PRSANR'],
                 condition=' AND '.join(conditions),
                 ordering='PRDTVO'
                 )

    preise = {}
    for row in rows:
        preise[row['artnr']] = dict(preis=int(row['preis'] * 100),
                                    gueltig_von=row.get('gueltig_ab_date'),
                                    gueltig_bis=row.get('gueltig_bis_date'),
                                    satznr=str(row['satznr_xpr00']))
    return preise
Ejemplo n.º 11
0
def get_konditionen(kundennr):
    """Liefere die Zahlungsbedingungen für einen Kunden

    Der Rückgabewert ist ein Drei-Tupel bestehend aus Skonto-Tage, Skonto und Netto-Tage.
    >>> get_konditionen('SC66669')
    (8, Decimal('2'), 30)
    """

    # Die Kundenkonditionen sind im Format der Datei XPX00E03 gespeichert,
    # diese stehen kodiert als Base16 in der Tabelle XPX00.
    # Die Anwendung ist 'X' ("sonstige"), Dateiart 'S' (Skonto)
    # und der Schlüssel ist der Skontoschlüssel aus der Tabelle XKS00.
    # Die Datentypen der Schlüssel unterscheiden sich allerdings:
    # PXPKEY ist CHAR(3), PXPKEY ist NUMERIC(3), mit DIGITS() wird die benötigte Konvertierung
    # durchgeführt.
    #
    # Die Zahlen in PXPARM sind in einem obskuren Format gespeichert,
    # das 0xf an die Zahlen hängt. Der Einfachheit halber wird die letzte Stelle einfach abgeschnitten.
    kundennr = husoftm2.tools.remove_prefix(kundennr, 'SC')
    conditions = ["PXANW = 'X'",
                  "PXSART = 'S'",
                  "KSKDNR = %s" % husoftm2.tools.pad('KSKDNR', kundennr),
                  'PXPKEY = DIGITS(KSSKSL)']
    rows = query(tables=['XKS00', 'XPX00'], fields=['HEX(PXPARM)'], condition=' AND '.join(conditions),
                 ua='husoftm2.kunden.get_konditionen')
    if rows:
        data = rows[0][0]
        skontotage, faelligkeit, skonto = [int(part) for part in (data[0:3], data[12:15], data[16:19])]
        return skontotage, Decimal(skonto) / 100, faelligkeit
Ejemplo n.º 12
0
def get_lieferadresse(kundennr_lieferadresse):
    """Lieferadresse für eine Kundennr der Form SCxxxxx.yyy ermitteln.

    Wenn eine normale Kundennr (SCxxxxx) als kundennr_lieferadresse übergeben wird, dann wird auf die
    Funktion get_kunde() zurückgegriffen und die Kundenadresse zurückgegeben.
    Ansonsten wird die abweichende Lieferadresse mit der Versandadressnr (yyy) zurückgegeben.
    """

    kundennr_lieferadresse = str(kundennr_lieferadresse)

    if '.' not in kundennr_lieferadresse:
        return get_kunde(kundennr_lieferadresse)

    kundennr, versandadressnr = kundennr_lieferadresse.split('.')
    kundennr = husoftm2.tools.remove_prefix(kundennr, 'SC')
    versandadressnr = int(versandadressnr)
    rows = query(['AVA00'], joins=[('XXA00', 'VASANR', 'XASANR')],
                 condition="VAKDNR='%8s' AND VAVANR=%03d AND VASTAT <>'X'" % (kundennr, versandadressnr))
    if len(rows) == 1:
        row = rows[0]
        address = _softm_to_dict(row)
        # Erfassungs- und Änderungsdatum aus XXA00 eintragen
        if row.get('erfassung_date'):
            address['erfassung'] = row['erfassung_date']
            address['aenderung'] = address['erfassung']
        if row.get('XXA_aenderung_date'):
            address['aenderung'] = row['XXA_aenderung_date']
        # Die Kundennr inkl. Erweiterung für abweichende Lieferadressen eintragen
        address['kundennr'] = husoftm2.tools.add_prefix(kundennr_lieferadresse, 'SC')
        return address
    elif len(rows) > 1:
        raise RuntimeError(u"Kunden-Lieferadresse inkonsistent: %s" % kundennr_lieferadresse)
Ejemplo n.º 13
0
def umlagermenge(artnr, anlager=100):
    """Ermittelt wieviel Umlagerungen für einen Artikel der nach anlager unterwegs sind.

    Rueckgabe:
     - Wenn eine Artikelnummer angegeben wird, dann eine Menge als int
    """

    # Das Auslieferungslager steht in AKLGN1, Das Ziellager steht in AKLGN2
    # In APLGNR steht AUCH das Auslieferungslager
    tables = ['AAP00', 'AAK00']
    conditions = [
        "APARTN=%s" % sql_quote(artnr),
        "AKLGN2=%d" % int(anlager),   # Zugangslager
        "AKAUFN=APAUFN",
        "AKAUFA='U'",                 # Umlagerungsauftrag
        "APSTAT<>'X'",                # Position nicht logisch gelöscht
        "APKZVA=0",                   # Position nicht als 'voll ausgeliefert' markiert
        #"(APMNG-APMNGF-APMNGG) > 0"  # (noch) zu liefernde menge ist positiv
        "AKSTAT<>'X'",                # Auftrag nicht logisch gelöscht
        "AKKZVA=0"]                   # Auftrag nicht als 'voll ausgeliefert' markiert

    rows = query(tables=tables, fields=['SUM(APMNG)'], querymappings={}, condition=' AND '.join(conditions))
    if rows and rows[0] and rows[0][0]:
        return as400_2_int(rows[0][0])
    return 0
Ejemplo n.º 14
0
def get_lieferbedingungen(kundennr):
    """Liefert einen String für die in SoftM hinterlegten Lieferbedingungen oder ''."""
    kundennr = husoftm2.tools.remove_prefix(kundennr, 'SC')
    rows = query(['AKZ00'], fields=['KZX3LB'], condition="KZKDNR = %s" % husoftm2.tools.pad('KZKDNR', kundennr),
                 limit=1, ua='husoftm2.kunden.get_lieferbedingungen')
    if rows:
        return lieferbedingungendict.get(rows[0][0], '')
    return ''
Ejemplo n.º 15
0
def get_zugaenge_warenvereinnahmungsnr_simple(bestellnr, warenvereinnahmungsnr):
    """Liefert alle Warenzugaenge zu einer Bestellnummer und zug. Warenvereinnahmungsnummer.

    Sammelt *nicht* alle Daten zu einer Bestellung, sondern nur die jeweils gelieferten Positionen.
    """
    rows = query('EWZ00', condition="WZBSTN=%s and WZWVNR=%s" %
                                  (sql_quote(bestellnr), sql_quote(warenvereinnahmungsnr)))
    return rows
Ejemplo n.º 16
0
def get_map(schluesseltyp):
    """Liefert ein dict aller Schlüssel und Werte zu dem Schlüsseltyp"""
    result = {}
    rows = query('XKP00', fields=['KPINHA', 'KPTX30'],
                                      condition="KPTYP='%s'" % schluesseltyp, ua='husoftm2.texte')
    for row in rows:
        result[row['inhalt1']] = row['KPTX30']
    return result
Ejemplo n.º 17
0
def get_lieferadressen(kundennr):
    """Sucht zusätzliche Lieferadressen für eine Kundennr raus.

    Gibt eine Liste aller möglichen Lieferadressen in Form von Kunden-Dicts zurück.
    """

    kundennr = husoftm2.tools.remove_prefix(kundennr, 'SC')
    avrows = query(['AVA00'], condition="VAKDNR='%8s' AND VASTAT <>'X'" % int(kundennr))
    kunden = []
    for row in avrows:
        xarows = query(['XXA00'], condition="XASANR='%s'" % int(row['satznr']))
        if xarows:
            if len(xarows) != 1:
                raise RuntimeError("Kunden-Lieferadresse inkonsistent: %s/%s" % (kundennr, row['satznr']))
            kunde = _softm_to_dict(xarows[0])
            kunde['kundennr'] = '%s.%03d' % (kunde['kundennr'], int(row['versandadresssnr']))
            kunden.append(kunde)
    return kunden
Ejemplo n.º 18
0
def get_guid(auftragsnr):
    """Gibt den GUID zu einer Auftragsnr zurück, sofern vorhanden."""
    auftragsnr = remove_prefix(auftragsnr, 'SO')
    condition = "ATTX60 LIKE %s AND ATAUFN = %s AND ATAUPO = 0 AND ATTART = 8" % (sql_quote("#:guid:%%"),
                                                                                  sql_quote(auftragsnr))
    rows = query('AAT00', fields=['ATTX60'], condition=condition)
    if rows:
        return rows[0][0].replace('#:guid:', '')
    return ''
Ejemplo n.º 19
0
def get_auftragsarten_by_auftragsnrs(auftragsnrs):
    """Ermittelt die Auftragsart (Freitext) der Aufträge der gegebenen Auftragsnummern.

    auftragsnrs: liste von Auftragsnummern
    return: Dictionary Auftragnr -> Auftragsart
    """
    condition = "AKAUFN in (%s)" % ','.join(sql_quote(remove_prefix(nr, 'SO')) for nr in auftragsnrs)
    rows = query(['AAK00'], fields=['AKAUFN', 'AKAUFA'], condition=condition)
    return dict(("SO%s" % row['auftragsnr'], AUFTRAGSARTEN[row['art']]) for row in rows)
Ejemplo n.º 20
0
def durchschnittlicher_abgabepreis(artnr, kundennr=None, startdatum=None):
    """Gibt eine Liste mit den durchschnittlichen Rechnungspreisen pro Monat zurück.

    Liefert eine Liste von 4-Tuples (datum, AVG(preis), menge, umsatz)

    Wenn eine Kundennummer mitgeliefert wird, werden nur Rechungen für diesen Kunden betrachtet.
    Wenn ein startdatum angegebenw wird, werden nur vorgänge nach diesem Datum betrachtet.

    [ ...
    (datetime.date(2009, 2, 1), 3295, 2, 6590),
    (datetime.date(2009, 10, 1), 1744, 2, 3488)]

    Die Funktion ist ausgesprochen langsam - bis zu 8 Sekunden.
    """

    conditions = [
        "FUARTN=%s" % (sql_quote(artnr)),  # nur bestimmten Artikel beachten
        "FKRGNR=FURGNR",   # JOIN
        "FKAUFA<>'U'",     # Keine Umlagerung
        "FKSTAT<>'X'",     # nicht gelöscht
        "FKDTFA>0",        # Druckdatum nicht leer
        "FUKZRV=2",        # ?
        "FURGNI<>0",       # ?
        "FKFORM=' '",      # ?
        "FURGNR<>0",       # es gibt eine Rechnungsnummer
        "FUPNET>0",        # keine Gutschriften
        ]

    if kundennr:
        kundennr = remove_prefix(kundennr, 'SC')
        conditions = ["(FKKDNR=%s OR FKKDRG=%s)" % (sql_quote('%8s' % kundennr),
                                                    sql_quote('%8s' % kundennr))] + conditions
    if not startdatum:
        conditions = ["FKDTFA>'10501'"] + conditions  # keine legacy Daten
    else:
        conditions = ["FKDTFA>%s" % sql_quote(date2softm(startdatum))[:5]] + conditions

    rows = query(['AFU00', 'AFK00'], fields=["FKDTFA", 'SUM(FUMNG)', 'SUM(FUPNET)', 'COUNT(FKRGNR)'],
                 condition=' AND '.join(conditions),
                 grouping='FKDTFA', cachingtime=60 * 60 * 24 * 3,
                 querymappings={'SUM(FUMNG)': 'menge', 'SUM(FUPNET)': 'nettopreis',
                                'COUNT(FKRGNR)': 'rechnungen', 'FKDTFA': 'rechnung_date'})
    mengen = {}
    umsatz = {}
    for row in rows:
        menge = int(float(row['menge']))
        nettopreis = float(row['nettopreis']) * 100
        if menge:
            datum = datetime.date(row['rechnung_date'].year, row['rechnung_date'].month, 1)
            if datum not in mengen:
                mengen[datum] = umsatz[datum] = 0
            mengen[datum] += int(menge)
            umsatz[datum] += int(nettopreis)
    ret = []
    for datum in sorted(mengen.keys()):
        ret.append((datum, int(umsatz[datum] / mengen[datum]), mengen[datum], umsatz[datum]))
    return ret
Ejemplo n.º 21
0
def get_lieferschein_statistics():
    """ gibt ein tuple (anzahl_nicht_uebernommene_lieferscheine, uebernommene_lieferscheine) zurueck
    """
    rows = query(fields=['LKKZ02', 'COUNT(*)'],
                 tables=['ALK00'],
                 condition="LKLFSN<>0 AND LKSTAT<>'X'",
                 grouping=['LKKZ02'])

    amounts = dict((row['LKKZ02'], row['COUNT(*)']) for row in rows)
    return amounts[0], amounts[1]
Ejemplo n.º 22
0
def kredit_limit(kundennr):
    """Gib Kreditlimit für einen Kunden zurück.

    >>> kredit_limit('SC66660')
    Decimal('60000.0')
    """
    kundennr = husoftm2.tools.remove_prefix(kundennr, 'SC')
    rows = query('XKS00', fields=['KSLIMI'], condition="KSKDNR=%s" % husoftm2.tools.pad('KSKDNR', kundennr),
                 limit=1, ua='husoftm2.kunden.kredit_limit')
    if rows:
        return rows[0][0]
Ejemplo n.º 23
0
def get_bestellungen_artnr(artnr):
    """Liefert alle Warenzugaenge einer Artikelnummer."""

    # BZT00 - zusatztexte
    positionen = query(['EBP00', 'EBL00'], ordering=['BPDTLT'],
        condition="BLBSTN=BPBSTN AND BLSTAT<>'X' AND BPSTAT<>'X' AND BPARTN=%s" % sql_quote(artnr))
    ret = []
    for position in positionen:
        position['_zugaenge'] = [x for x in get_zugaenge_bestellnr(position['bestellnr'])
                                     if x['artnr'] == artnr]
        for zugang in position['_zugaenge']:  # Buchungsdaten
            buchungen = query('BBU00',
                condition='BUBELN=%s' % sql_escape(zugang['rechnungsnr']))
            zugang['_fibubuchungen'] = kursfaktorkorrektur(buchungen, umdrehen=False)
        position['_lager_stapelschnittstelle'] = query(
            'ESL00', condition="SLBSTN=%s AND SLBSTP=%s AND SLARTN=%s"
            % (sql_escape(position['bestellnr']), sql_escape(position['bestellpos']), sql_escape(artnr)))
        ret.append(position)
    # ?: SELECT * FROM EWZ00 WHERE WZBSTN = 43072
    return kursfaktorkorrektur(ret)
Ejemplo n.º 24
0
def offener_auftragswert(kundennr):
    """Ermittle die Summe der offenen Aufträge für einen Kunden
    >>> offener_auftragswert('SC66660')
    Decimal('57.11')
    """

    kundennr = husoftm2.tools.remove_prefix(kundennr, 'SC')
    rows = query('XKS00', fields=['KSAWRT'],
                 condition='KSKDNR=%s' % husoftm2.tools.pad('KSKDNR', kundennr),
                 ua='husoftm2.kunden.offener_auftragswert')
    if rows:
        return rows[0][0]
Ejemplo n.º 25
0
def get_rahmenauftraege(kundennr, artnr):
    """Gib die Auftragsnummern aller offenen Rahmenaufträge für den Kunden und den Artikel als Liste zurück.

    >>> get_rahmenauftraege('SC66663', '14600')
    ['SO1205711']
    """
    kundennr = remove_prefix(kundennr, 'SC')
    conditions = ["AKAUFN=APAUFN", "AKKZVA=0", "APKZVA=0", "AKSTAT<>'X'", "APSTAT<>'X'", "AKAUFN>0",
                  "AKAUFA='R'", "AKKDNR=%s" % pad('AKKDNR', kundennr), "APARTN=%s" % sql_quote(artnr)]
    rows = query(['AAK00', 'AAP00'], condition=' AND '.join(conditions), fields=['AKAUFN'],
                 ua='husoftm2.auftraege.get_rahmenauftraege')
    return [add_prefix(row[0], 'SO') for row in rows]
Ejemplo n.º 26
0
def get_kunde_by_iln(iln):
    """Get Kunden Address based on ILN.

    See http://cybernetics.hudora.biz/projects/wiki/AddressProtocol for the structure of returned data.
    <iln> must be an valit GLN/ILN encoded as an String.
    If no data exists for that GLN/ILN ValueError is raised.
    """
    rows = query(['XKS00'], condition="KCE2IL='%s'" % (int(iln), ))
    if rows:
        # stammadresse
        return get_kunde(rows[0]['kundennr'])
    else:
        # abweichende Lieferadresse
        rows = query(['AVA00'], condition="VAILN='%s'" % (int(iln), ))
        if rows:
            rows2 = query(['XXA00'], condition="XASANR='%s'" % (int(rows[0]['satznr']), ))
            if rows2:
                kunde = _softm_to_dict(rows2[0])
                kunde['kundennr'] = kunde['kundennr'] + ('/%03d' % int(rows[0]['versandadresssnr']))
                return kunde
    raise ValueError("Keine Daten für GLN/ILN %r gefunden" % iln)
Ejemplo n.º 27
0
def get_betreuer(kundennr):
    """Liefert einen String, der den Betreuer im Hause für einen bestimmten Kunden identifizert oder ''.

    >>> get_betreuer('SC66669')
    "Nadine Gerloff"
    """
    kundennr = husoftm2.tools.remove_prefix(kundennr, 'SC')
    rows = query(['AKZ00'], fields=['KZINFO'],
                 condition="KZKDNR = %s" % husoftm2.tools.pad('KZKDNR', kundennr),
                 limit=1, ua='husoftm2.kunden.get_betreuer')
    if rows:
        return betreuerdict.get(rows[0][0], '')
    return ''
Ejemplo n.º 28
0
def get_changed_after(date, limit=None):
    """Liefert die Lieferscheinnummern zurück, die nach <date> geändert wurden."""
    date = int(date.strftime('1%y%m%d'))
    conditions = ["LKLFSN<>0",
                  "LKSTAT<>'X'",
                  "(LKDTER>%d OR LKDTAE>=%d)" % (date, date),
                  ]
    condition = " AND ".join(conditions)
    ret = []
    for kopf in query(['ALK00'], ordering=['LKSANK DESC'], fields=['LKLFSN'],
                      condition=condition, limit=limit, ua='husoftm2.lieferscheine'):
        ret.append("SL%s" % kopf[0])
    return ret
Ejemplo n.º 29
0
def buchbestaende(artnrs=None, lager=0):
    """Gibt die Buchbestand einiger oder aller Artikels für ein Lager zurück oder (lager=0) für alle Lager

    >>> buchbestand(['14600/03'])
    {u'14600/03': 338}
    """
    conditions = ["LFLGNR=%d" % int(lager),
                  "LFMGLP<>0",
                  "LFSTAT<>'X'"]
    if artnrs:
        conditions += ["LFARTN IN (%s)" % ','.join([sql_quote(artnr) for artnr in artnrs])]
    rows = query(['XLF00'], fields=['LFARTN', 'LFMGLP'], condition=' AND '.join(conditions))
    return dict([(artnr, int(menge)) for (artnr, menge) in rows])
Ejemplo n.º 30
0
def listenpreise(artnrs=None):
    """Gibt den (aktuellen) Listenpreis in Cent für eine Liste von Artikeln zurück.
    Wenn keine Artikelnummern angegeben werden, gibt es alle Listenpreise zurück.

    >>> preise(['04711'])
    {'04711': 1365}
    """

    conditions = ["ARSTAT<>'X'"]
    if artnrs:
        conditions += ['ARARTN IN (%s)' % ','.join([sql_quote(x) for x in artnrs])]
    rows = query('XAR00', fields=['ARARTN', 'ARPREV'], condition=' AND '.join(conditions))
    return dict([(x['artnr'], int(100 * float(x['listenpreis']))) for x in rows])