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
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')
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))
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))
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))
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))
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))
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))
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)
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))
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]
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))
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))
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))
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))
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))
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))
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))
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))
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))
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
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)
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))