Пример #1
0
def _get_locations_by_height():
    """
    Erzeuge ein Tupel mit den bebuchten und unbebuchten Plätzen.
    
    Die Elemente des Tupels sind Dictionaries, deren Schlüssel die Platzhöhe
    und deren Keys Listen mit Informationen über die Plätze sind.
    
    Beispiel:
    ({1000: [{'name': '182503', 'preference': 6}],
      2000: [{'name': '032003', 'preference': 6},
             {'name': '042503', 'preference': 6},
             {'name': '043603', 'preference': 6}]
      },
      {1050: [{'name': '011503', 'preference': 1},
              {'name': '053603', 'preference': 6}]
    })
    
    Plätze mit einer Präferenz < 1 werden nicht berücksichtigt.
    """
    
    kerneladapter = Kerneladapter()
    booked, unbooked = {}, {}
    for location in kerneladapter.get_location_list():
        info = kerneladapter.get_location(location)
        if int(info['preference']) < 1:
            continue
        if info['reserved_for'] or info['allocated_by']:
            tmp = booked
        else:
            tmp = unbooked
        tmp.setdefault(info['height'], []).append({'name': info['name'], 'preference': info['preference']})
    return booked, unbooked
Пример #2
0
def kommiauftrag_set_priority(request, kommiauftragnr):
    priority = int(request.POST.get('priority', '').strip('p'))
    kerneladapter = Kerneladapter()
    content = kerneladapter.set_kommiauftrag_priority(kommiauftragnr,
            explanation='Prioritaet auf %d durch %s geaendert' % (priority, request.user.username),
            priority=priority)
    return HttpResponse(content, mimetype='application/json')
Пример #3
0
def lager_info(request):
    """View für die Lager-Informations-Ansicht"""
    
    kerneladapter = Kerneladapter()
    anzahl_artikel = len(kerneladapter.get_article_list())
    booked, unbooked = _get_locations_by_height()
    booked = sorted((height, len(loc)) for height, loc in booked.items())
    unbooked = sorted((height, len(loc)) for height, loc in unbooked.items())
    
    num_booked = sum(platz[1] for platz in booked)
    num_unbooked = sum(platz[1] for x in unbooked)
    
    ctx = {'anzahl_bebucht': num_booked,
           'anzahl_unbebucht': num_unbooked,
           'anzahl_plaetze': num_booked + num_unbooked,
           'anzahl_artikel': anzahl_artikel,
           'plaetze_bebucht': booked,
           'plaetze_unbebucht': unbooked
          }
    
    extra_info = kerneladapter.get_statistics()
    extra_info['oldest_movement'] = fix_timestamp(extra_info['oldest_movement'])
    extra_info['oldest_pick'] = fix_timestamp(extra_info['oldest_pick'])
    ctx.update(extra_info)
    return render_to_response('myplfrontend/lager_info.html', ctx, context_instance=RequestContext(request))
Пример #4
0
def info_panel(request):
    """Renders a page, that shows an info panel for the employees in the store."""
    
    kerneladapter = Kerneladapter()
    pipeline = (kerneladapter.get_kommiauftrag(kommi) for kommi in kerneladapter.get_kommiauftrag_list())
    for kommi in pipeline:
        kommi['orderlines_count'] = len(kommi.get('orderlines', []))
    
    db = myplfrontend.tools.get_pickinfo_from_pipeline_data(pipeline)
    
    # FIXME: Der Code hier beruht noch teilweise auf den Daten, die aus der zugeh. Django DB kamen, zB. postions['done'] wurde vorher
    # aus dieser DB berechnet. Wie können wir die erledigten Positionen aus dem Kernel / couchdb / ... erhalten?
    
    positions = {}
    positions['done'] = 0
    positions['inwork'] = 0
    if 'yes' in db: # FIXME aus dem get_pickinfo_from_pipeline_data() code verstehe ich nicht, wo hier ein key 'yes' herkommen soll?
        positions['todo'] = int(db['yes']['orderlines_count'])
    else:
        positions['todo'] = 0
    positions['total'] = positions['done'] + positions['inwork'] + positions['todo']
    if positions['total']:
        positions['percent_done'] = (100.0/positions['total']) * positions['done']
    else:
        positions['percent_done'] = 0
    return render_to_response('myplfrontend/info_panel.html',
                              {'pipeline': pipeline, 'db': db, 'positions': positions},
                              context_instance=RequestContext(request))
Пример #5
0
def article_audit(request, artnr):
    """View für die Ansicht eines Artikelkontos eines Artikels (Audit-Log)"""
    kerneladapter = Kerneladapter()
    audit = kerneladapter.get_article_audit(artnr)
    return render_to_response('myplfrontend/article_audit.html',
                              {'title': 'Artikelkonto %s' % artnr, 'artnr': artnr, 'audit': audit},
                              context_instance=RequestContext(request))
Пример #6
0
def artikel_heute(request):
    """View für Übersichtsseite mit den heute zu verschickenden Artikeln"""
    
    kerneladapter = Kerneladapter()
    
    # summarize product quantities
    products = {}
    for komminr in kerneladapter.get_kommiauftrag_list():
        kommi = kerneladapter.get_kommiauftrag(komminr)
        if kommi['shouldprocess'] == 'yes':
            for orderline in kommi['orderlines']:
                artnr = orderline['artnr']
                products[artnr] = products.get(artnr, 0) + orderline['menge']
    
    artikel_heutel = []
    for artnr, quantity in products.items():
        product = cs.masterdata.article.eap(artnr)
        if product:
            total_weight = quantity * float_or_0(product.get("package_weight")) / 1000.0
            total_volume = quantity * float_or_0(product.get("package_volume_liter"))
            total_palettes = quantity / float_or_0(product.get("palettenfaktor"), default=1.0)
            artikel_heutel.append({'quantity': quantity,
                                   'artnr': artnr,
                                   'name': product['name'],
                                   'palettenfaktor': product.get('palettenfaktor'),
                                   'total_weight': total_weight,
                                   'total_volume': total_volume,
                                   'paletten': total_palettes})
        else:
            cs.zwitscher.zwitscher('%s: eAP nicht in CouchDB. OMG! #error' % artnr, username='******')
    return render_to_response('myplfrontend/artikel_heute.html', {'artikel_heute': artikel_heutel},
                              context_instance=RequestContext(request))
Пример #7
0
def unit_list(request):
    """Render a list of all MUIs/NVEs/SSCCs"""
    
    kerneladapter = Kerneladapter()
    muis = kerneladapter.get_units_list()
    return render_to_response('myplfrontend/unit_list.html',
                              {'title': 'Units im Lager', 'muis': sorted(muis)},
                              context_instance=RequestContext(request))
Пример #8
0
def bewegungen(request):
    """Liste aller offenen Picks und Movements"""
    
    kerneladapter = Kerneladapter()
    movements = [kerneladapter.get_movement(movement_id) for movement_id in sorted(kerneladapter.get_movements_list())]
    picks = [kerneladapter.get_pick(pick_id) for pick_id in sorted(kerneladapter.get_picks_list())]
    return render_to_response('myplfrontend/movement_list.html', {'movements': movements, 'picks': picks},
                              context_instance=RequestContext(request))
Пример #9
0
def kommiauftrag_nullen(request, kommiauftragnr):
    begruendung = request.POST.get('begruendung', '').strip()
    kerneladapter = Kerneladapter()
    content = kerneladapter.kommiauftrag_nullen(kommiauftragnr, request.user.username, begruendung)
    if content:
        request.user.message_set.objects.create('%s erfolgreich genullt' % kommiauftragnr)
        return HttpResponseRedirect('../')
    else:
        return HttpResponse("Fehler beim Nullen von %r" % kommiauftragnr, mimetype='text/plain', status=500)
Пример #10
0
def article_detail(request, artnr):
    """View für Detailansicht eines Artikels"""
    
    kerneladapter = Kerneladapter()
    article_info = kerneladapter.get_article(artnr)
    return render_to_response('myplfrontend/article_details.html',
                              {'title': 'Artikelinformationen: %s (%s)' % (cs.masterdata.article.name(artnr), artnr),
                               'article_info': article_info,
                               'bestand100': husoftm.bestaende.bestand(artnr=artnr, lager=100),
                               'units': [kerneladapter.get_unit_info(nve) for nve in article_info['muis']]},
                              context_instance=RequestContext(request))
Пример #11
0
def find_softm_differences():
    """Find articles which have different quantities in myPL as their SoftM counterparts."""
    kerneladapter = Kerneladapter()
    softmbestand = set(husoftm.bestaende.buchbestaende(lager=100).items())
    kernelbestand = set((artdict['artnr'], artdict['full_quantity']) for artdict in
                        (kerneladapter.get_article(article) for article in kerneladapter.get_article_list()))
    difkernel2softm = kernelbestand.difference(softmbestand)
    difsoftm2kernel = softmbestand.difference(kernelbestand)
    artnrs = set(artnr for (artnr, mng) in itertools.chain(difkernel2softm, difsoftm2kernel))
    dictkernel2softm = dict(difkernel2softm)
    dictsoftm2kernel = dict(difsoftm2kernel)
    return [dict(artnr=artnr, softm_menge=dictsoftm2kernel.get(artnr, 0), kernel_menge=dictkernel2softm.get(artnr, 0))
            for artnr in artnrs]
Пример #12
0
def lagerplatz_detail(request, location):
    """View für Detailansicht eines Lagerplatzes"""
    
    kerneladapter = Kerneladapter()
    platzinfo = kerneladapter.get_location(location)
    units = [kerneladapter.get_unit_info(mui) for mui in platzinfo['allocated_by']]
    
    # TODO: alle movements und korrekturbuchungen auf diesem Platz zeigen
    # Und zwar wie?!?
    
    return render_to_response('myplfrontend/platz_detail.html',
                              {'title': 'Lagerplatz %s' % location, 'platzinfo': platzinfo, 'units': units},
                              context_instance=RequestContext(request))
Пример #13
0
def pick_show(request, pickid):
    """Informationen zu einem Pick"""
    
    kerneladapter = Kerneladapter()
    pick = kerneladapter.get_pick(pickid)
    if not pick:
        raise Http404("Kein Pick mit ID %s gefunden" % pickid)
    title = 'Pick %s' % pickid
    if pick.get('archived'):
        title += ' (archiviert)'
    return render_to_response('myplfrontend/pick_info.html',
                              {'title': title, 'pick': pick},
                              context_instance=RequestContext(request))
Пример #14
0
def movement_show(request, mid):
    """Informationen zu einer Bewegung"""
    
    kerneladapter = Kerneladapter()
    movement = kerneladapter.get_movement(mid)
    if not movement:
        raise Http404("Kein Movement mit ID %s gefunden" % mid)
    
    title = 'Movement %s' % mid
    if movement.get('archived'):
        title += ' (archiviert)'
    return render_to_response('myplfrontend/movement_info.html',
                              {'movement': movement, 'title': title},
                              context_instance=RequestContext(request))
Пример #15
0
def abc(request):
    """View für ABC-Klassifizierung"""
    
    kerneladapter = Kerneladapter()
    klasses = {}
    for name, klass in kerneladapter.get_abc().items():
        tmp = []
        for quantity, artnr in klass:
            product_detail = kerneladapter.get_article(artnr)
            full_quantity = product_detail["full_quantity"]
            nve_count = len(product_detail["muis"])
            tmp.append((quantity, full_quantity, artnr, nve_count))
        klasses[name] = tmp
    return render_to_response('myplfrontend/abc.html', {'klasses': klasses},
                              context_instance=RequestContext(request))
Пример #16
0
def penner(request):
    """View für Penner-Übersicht (Artikel ohne Aktivität in der letzten Zeit)"""
    
    kerneladapter = Kerneladapter()
    abc_articles = set(artnr for (m, artnr) in itertools.chain(*kerneladapter.get_abc().values()))
    lagerbestand = set(kerneladapter.get_article_list())
    
    pennerliste = []
    for artnr in (lagerbestand - abc_articles):
        product_detail = kerneladapter.get_article(artnr)
        full_quantity = product_detail['full_quantity']
        nve_count = len(product_detail['muis'])
        pennerliste.append((nve_count, full_quantity, artnr))
    return render_to_response('myplfrontend/penner.html',
                              {'pennerliste': sorted(pennerliste, reverse=True)},
                              context_instance=RequestContext(request))
Пример #17
0
def kommiauftrag_show(request, kommiauftragnr):
    """Render a page with further information for a single Kommiauftrag."""
    
    kerneladapter = Kerneladapter()
    kommiauftrag = kerneladapter.get_kommiauftrag(kommiauftragnr)
    # Prüfen, ob genug Ware für den Artikel verfügbar ist.
    
    orderlines = []
    if not kommiauftrag.get('archived') and 'orderlines' in kommiauftrag:
        for orderline in kommiauftrag['orderlines']:
            orderline['picksuggestion'] = kerneladapter.find_provisioning_candidates(orderline['menge'], orderline['artnr'])
            available = bool(orderline['picksuggestion'])
            orderline['available'] = available
            if not available:
                orderline['fehler'] = u'Kann zur Zeit nicht efüllt werden'
            orderlines.append(orderline)
    
    kommischeine = []
    for kommischein_id in kommiauftrag.get('provisioninglists', []):
        kommischein = kommiauftrag.get_kommischein(kommischein_id)
        
        provisionings = []
        for provisioning_id in kommischein.get('provisioning_ids', []):
            if kommischein.get('type') == 'picklist':
                provisioning = kommiauftrag.get_pick(provisioning_id)
                if not provisioning:
                    provisioning = {}
                provisioning.update({'id': provisioning_id})
                provisionings.append(provisioning)
        kommischein['provisionings'] = provisionings
        kommischeine.append(kommischein)
    
    # TODO: change to unitaudit
    audit = kerneladapter.get_audit('fields/by_komminr', kommiauftragnr)
    title = 'Kommissionierauftrag %s' % kommiauftragnr
    if kommiauftrag.get('archived'):
        title += ' (archiviert)'

    return render_to_response('myplfrontend/kommiauftrag.html',
                              {'title': title,
                               'kommiauftrag': kommiauftrag,
                               'orderlines': orderlines,
                               'kommischeine': kommischeine,
                               'auditlines': audit},
                              context_instance=RequestContext(request))
Пример #18
0
def kommiauftrag_list(request):
    """View für Liste der Aufträge in der Provpipeline"""
    
    kerneladapter = Kerneladapter()
    kommiauftraege_new, kommiauftraege_processing = [], []
    
    for kommiauftragnr in kerneladapter.get_kommiauftrag_list():
        kommiauftrag = kerneladapter.get_kommiauftrag(kommiauftragnr)
        
        if kommiauftrag['status'] == 'processing':
            kommiauftraege_processing.append(kerneladapter.get_kommiauftrag(kommiauftragnr))
        else:
            kommiauftraege_new.append(kerneladapter.get_kommiauftrag(kommiauftragnr))
        
    kommiauftraege = kommiauftraege_processing + kommiauftraege_new
    
    return render_to_response('myplfrontend/kommiauftraege.html',
                              {'title': 'Komissionierungen, die nicht erledigt sind.',
                               'kommiauftraege': kommiauftraege},
                              context_instance=RequestContext(request))
Пример #19
0
def show_articles(request, want_softm):
    """Render a list of all articles."""
    if request.method == 'POST':
        url = './' + request.POST.get('article', '')
        return HttpResponseRedirect(url)
    
    kerneladapter = Kerneladapter()
    articles = []
    for artnr in kerneladapter.get_article_list():
        article = kerneladapter.get_article(artnr)
        article['name'] = cs.masterdata.article.name(article['artnr'])
        if want_softm:
            article['buchbestand'] = husoftm.bestaende.buchbestand(lager=100, artnr=article['artnr'])
        articles.append(article)
    
    # TODO: Artikel finden, von denen SoftM denkt, sie wären im myPL, von denen das myPL aber nichts weiss
    # Wie?
    
    title = 'Artikel am Lager'
    if want_softm:
        title += ' mit SoftM Buchbeständen'
    return render_to_response('myplfrontend/articles.html',
                              {'title': title, 'articles': articles, 'want_softm': want_softm},
                              context_instance=RequestContext(request))
Пример #20
0
def unit_show(request, mui):
    """View für Detailansicht einer MUI"""
    
    kerneladapter = Kerneladapter()
    unit = kerneladapter.get_unit_info(mui)
    
    if request.method == "POST":
        form = PalletHeightForm(request.POST)
        if unit.get('archived'):
            pass
        elif form.is_valid():
            kerneladapter.set_unit_height(mui, form.cleaned_data['height'])
    else:
        form = PalletHeightForm({'height': unit.get('height', 1950)})
    
    title = 'Unit %s' % mui
    if unit.get('archived'):
        title += ' (archiviert)'
    audit = kerneladapter.get_unit_audit(mui)
    return render_to_response('myplfrontend/unit_detail.html',
                              {'title': title,
                               'unit': unit, 'audit': audit,
                               'form': form},
                              context_instance=RequestContext(request))
Пример #21
0
    def provisioning2xml(self, provisioning_id):
        """Generic functionality to create a XML file from kernelE's kommischein information."""

        provisioning_dict = Kerneladapter().get_kommischein(provisioning_id)

        xmlroot = self.root
        xml_provisioning = ET.SubElement(xmlroot, 'provisioning')

        # neccessary data from kommischein
        for fieldname in ['provpipeline_id', 'id']:
            _add_subelemententry(xml_provisioning, fieldname, provisioning_dict)

        # FIXME This is special treatment for archived provisionings. Is there a need to process the archived?
        for fieldname in ['parts']:
            attr_dict = provisioning_dict.get('attributes', provisioning_dict)
            _add_subelemententry(xml_provisioning, fieldname, attr_dict)

        # data from kommiauftrag
        fields = ['liefertermin', 'kundennr', 'auftragsnummer']
        kommiauftrag = Kerneladapter().get_kommiauftrag(provisioning_dict["provpipeline_id"])
        attr_dict = kommiauftrag.get('attributes', kommiauftrag)
        for fieldname in fields:
            _add_subelemententry(xml_provisioning, fieldname, attr_dict)

        # data from the kommischeins provisionings_ids
        weight_sum = 0
        volume_sum = 0

        # collect provisionings in a list of dictionaries -> for sorting
        provisionings = []
        # XXX: provisionings called provisioning_ids in kernel and provisionings in archive
        # FIXME: do we need archived provisionings?
        for provisioningid in provisioning_dict.get("provisioning_ids",
                                                    provisioning_dict.get("provisionings", [])):
            if provisioningid.startswith('P'):
                provisioning = Kerneladapter().get_pick(provisioningid)
            else:
                provisioning = Kerneladapter().get_movement(provisioningid)
            provisionings.append(provisioning)


        # process provisionings sorted by from_location
        for provisioning in sort_plaetze(provisionings, key='from_location'):

            xml_pos = ET.SubElement(xml_provisioning, 'provisioningposition')

            # FIXME was ist provisioning_type? -> pick/retrieval? wo wird das angedruckt?
            # FIXME: sowas wie from_location gibts bei archivierten daten nicht
            for fieldname in ['from_location', 'provisioning_type', 'menge']:
                _add_subelemententry(xml_pos, fieldname, provisioning)
            
            # article data
            artnr = provisioning['artnr']
            pickmenge = provisioning['menge']
            product = dict(cs.masterdata.article.eap(artnr)) # dict aus couchdb document machen
            product['artnr'] = artnr # ist sonst nur _id
            xml_product = ET.SubElement(xml_pos, 'product')

            volume = product.get('package_volume_liter')
            if volume:
                volume_sum += pickmenge * volume
            else:
                cs.zwitscher.zwitscher('%s: Volumen unbekannt' % artnr, username='******')

            weight = product.get('package_weight', 0)/1000.
            if weight:
                weight_sum += pickmenge * weight
            else:
                cs.zwitscher.zwitscher('%s: Gewicht unbekannt' % artnr, username='******')

            for fieldname in ['artnr', 'name', 'package_weight']:
                _add_subelemententry(xml_product, fieldname, product)

            if self.produktionsauftrag:
                ET.SubElement(xml_product, 'produktionshinweis').text = cs.masterdata.vorprodukte.produktionshinweis(artnr)

            products_per_export_package = product.get('products_per_export_package')
            if products_per_export_package:
                ET.SubElement(xml_pos, 'export_packages_per_position').text = unicode(
                        pickmenge / float(products_per_export_package))
            else:
                ET.SubElement(xml_pos, 'export_packages_per_position').text = ''

        ET.SubElement(xml_provisioning, 'volume_sum').text = str(volume_sum)
        ET.SubElement(xml_provisioning, 'weight_sum').text = str(weight_sum)
        return xmlroot
Пример #22
0
def get_provisioning_pdf(provisioning_id):
    """Public interface to get a kommischein pdf."""
    ka = Kerneladapter()
    auftragsart = ka.get_kommiauftrag(ka.get_kommischein(provisioning_id)["provpipeline_id"])['art']
    generator = _ProvisioningGenerator(produktionsauftrag=(auftragsart == 'KO'))
    return generator.generate(provisioning_id)
Пример #23
0
def requesttracker(request):
    """Display a table containing requesttracker data from kernelE."""
    kerneladapter = Kerneladapter()
    tracking_infos = kerneladapter.requesttracker()
    return render_to_response('myplfrontend/requesttracker.html', dict(tracking_infos=tracking_infos),
                              context_instance=RequestContext(request))