def add_notification(data): """Function for adding a user to the customer""" api = CreateApiResource('robotRock/Notification') api.create(customer=request.customer.kundennr, recipient=data.get('email'), status=data.get('event')) return render_to_json({'result': 'ok'})
def _create_order(api, customer, useremail, form_data, documents=None, orderlines=None): """ speichert einen neuen Auftrag via RobotRock """ order = {'customer': customer.kundennr, 'erfasst_von': useremail, 'source': 'FF'} # drei moegliche Quellen: "FF": Fullfillment, # "SV": Serviceauftrag, # "WS": Webshop # Service-Aufträge als solche markieren if customer.kundennr == '66663': order['source'] = 'SV' # zuerst bauen wir uns die Basis-Felder zusammen fields = ['kundenauftragsnr', 'name1', 'name2', 'strasse', 'plz', 'ort', 'land', 'phone', 'mobil', 'mail'] for field in fields: order[field] = form_data[field] # haben wir eine einzelne Bestellposition bekommen? ic = CreateApiResource('inventory/Price') eap = CreateApiResource('inventory/EAP') order['orderlines'] = [] if 'orderline_artnr' in form_data: artnr = form_data['orderline_artnr'] preis = ic.preis(artnr) name = eap.fetch(artnr).get('name', '???') order['orderlines'].append({'artnr': artnr, 'name': name, 'menge': form_data['orderline_menge'], 'preis': preis}) # oder haben wir eine ganze Liste von Bestellpositionen? if orderlines: for form in orderlines: artnr = form.cleaned_data['artnr'] preis = ic.preis(artnr) order['orderlines'].append({'artnr': artnr, 'name': form.cleaned_data['name'], 'menge': form.cleaned_data['menge'], 'preis': preis}) # sollen wir noch Zusatzdokumente anhaengen? if documents is None: documents = [] order['dokumente'] = [] for filename, data in documents: #try: order['dokumente'].append({'name': filename, 'content': data.encode('base64')}) #except Exception as ex: # pass # Handling-Gebühren als eigenständige Position order['additional_expenses'] = customer.additional_expenses # XXX: CB: Warum wird die api Variable bis hierher durchgeschleift? # Reicht es nicht, api hier erst zu initialisieren return api.create(order)
def credit(self): """Gibt den 'Rest-Kredit' des Kunden zurück. Das entspricht dem Kreditlimit abzgl. Offener Posten. Erwartet, dass die interne Kundennr der SoftM Kundennr entspricht. """ api = CreateApiResource('bookkeeping/CreditConsumption') credit = api.read(self.kundennr) return credit
def delete_notifications(designators): """Function for removing a list of user_ids""" api = CreateApiResource('robotRock/Notification') for designator in designators: try: api.remove(customer=request.customer.kundennr, designator=designator) except Exception, ex: logger.error("unable to delete notification '%s': %s" % (designator, ex))
def show(request, order_id, document_name): """ liefert das angefrage Zusatzdokument als PDF zurueck """ api = CreateApiResource('robotRock/Documents') pdf = api.read(request.customer, order_id, document_name) if not pdf: raise Http404 resp = HttpResponse(mimetype='application/pdf') resp['Content-Disposition'] = 'inline; filename=%s' % document_name resp.write(pdf) return resp
def test_called_method_indication(self): """ werden die aufgerufenen Methoden richtig angezeigt? """ mock = MockWithUtils() SetApiResourceMock('robotRock/Customer', mock) settings.SHOULD_MOCK_API = True rsrc = CreateApiResource('robotRock/Customer', '*****@*****.**', 'foobar') rsrc.read() self.assertTrue(mock.ctor_was_called('*****@*****.**', 'foobar')) self.assertFalse(mock.ctor_was_called('*****@*****.**', 'carcdr')) self.assertTrue(mock.method_was_called('read'))
def cancel(request, order_id): """ storniert einen Auftrag """ try: api = CreateApiResource('robotRock/Order') order = api.read(request.customer, order_id) if api.storno(request.customer, order): return render_to_json({'result': 'ok'}) else: return render_to_json({'result': 'error', 'msg': 'Der Auftrag konnte nicht storniert werden.'}) except: return render_to_json({'result': 'error', 'msg': 'Allgemeiner Fehler beim Stornieren.'})
def show(request, order_designator): """ liefert die Details fuer einen Auftrag zur Anzeige """ api = CreateApiResource('robotRock/Order') order = api.read(request.customer, order_designator) texts = OrderFreitext.objects.filter(order_designator=order.designator) freitext = texts[0].text if len(texts)>0 else None for line in order.orderlines: artnr = line['artnr'] return render_to_response_with_request(request, 'beliza/orders/show.html', {'order': order, 'freitext': freitext, 'trackingdata': trackingnummern(order.designator)})
def test_mock_calling(self): """ koennen wir Funktionen im Mock aufrufen? """ mock = MockWithUtils() mock.read.return_value = Customer() mock.read.return_value['name1'] = 'Heinz Mueller' mock.read.return_value['name2'] = 'Entenhausen Corp.' SetApiResourceMock('robotRock/Customer', mock) settings.SHOULD_MOCK_API = True rsrc = CreateApiResource('robotRock/Customer', '*****@*****.**', 'foobar') customer = rsrc.read() self.assertTrue(dict(customer)) self.assertEquals('Heinz Mueller, Entenhausen Corp.', customer.name())
def authenticate(self, username=None, password=None): # pylint: disable=R0201 """ versucht den Benutzer ueber RobotRock zu authentifizieren """ # koennen wir ueberhaupt Daten zum Benutzer abrufen? Wenn ja suchen wir uns # den richtigen Benutzer aus allen Benutzern, die der Kunde hat. try: resource = CreateApiResource('robotRock/Customer', username, password) customer = resource.read() if not customer: return None realname = '' for user in customer.users: if user['username'] == username: realname = ' '.join([user['first_name'], user['last_name']]) break except Exception as exc: return None # jetzt gucken wir, ob wir solchen Benutzer schon in der Datenbank haben, # wenn nicht muessen wir einen neuen Datensatz fuer den Benutzer anlegen. users = User.objects.filter(username=username) if len(users) > 1: raise RuntimeError("Duplicate user %s" % username) elif len(users) < 1: user = User.objects.create(username=username, email=username) user.set_unusable_password() else: user = users[0] # jetzt aktualisieren wir die Attribute des Benutzers mit den neuesten # Werten von RobotRock, falls sich da was geaendert haben sollte user.first_name = realname user.last_name = customer.name1 user.password = password user.is_staff = True user.save() # und jetzt noch die OAuth-Credentials speichern try: user_data = UserProfile.objects.get(user__id__exact=user.id) except: user_data = UserProfile() user_data.user = user user_data.email = username user_data.password = password user_data.save() # das war's, Benutzer zurueckliefern, damit ist Login geglueckt return user
def check_availability(request): """ Verfügbarkeit einer Bestellposition überprüfen. Wenn der entsprechende Artikel fuer den jeweiligen Kunden lieferbar ist wird ein HTML-Snippet mit der Orderline gerendert und zurueckgeliefert, damit es dann in der Tabelle der Bestellpositionen angezeigt werden kann. """ # ueberprueft die Parameter artnr = request.GET.get('artnr') try: menge = int(request.GET.get('menge')) except ValueError: return render_to_json({'result': 'does_not_exist', 'reason': 'invalid article or quantity'}) if not (menge and artnr): return render_to_json({'result': 'does_not_exist', 'reason': 'invalid article or quantity'}) # eap Infos holen api = CreateApiResource('inventory/EAP') eap = api.fetch(artnr) if not eap: return render_to_json({'result': 'does_not_exist', 'reason': 'invalid article or quantity'}) try: # zuerst die Verfuegbarkeit if not filter(lambda entry: entry['articles'] and entry['automatisch_moeglich'], CreateApiResource('inventory/Alternatives').read(menge, artnr)): NonAvailable.objects.create(menge=menge, artnr=artnr, customer=request.customer.designator) return render_to_json({'result': 'not_available'}) # jetzt den Preis und den Namen api = CreateApiResource('inventory/Price') preis = api.preis(artnr, request.customer.kundennr) * menge, form = OrderlineForm(prefix='form-%d' % int(time()), initial={'menge': menge, 'artnr': artnr, 'preis': '%.2f EUR' % preis, 'name': eap.get('name', '???')}); t = loader.get_template('beliza/orders/orderline.html') html = t.render(Context({'form': form})) return render_to_json({'result': 'ok', 'html': html}) except Exception, exc: print "------------> debug 100, %s" % exc if str(exc).find('unbekannt') != -1: return render_to_json({'result': 'does_not_exist'})
def clean(self): data = self.cleaned_data # pylint: disable=E1101 # zuerst ueberpruefen wir, ob das XML gueltig ist schemafile = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'xml-schemas', 'rossmann.xsd') schema_doc = etree.parse(open(schemafile)) xmlschema = etree.XMLSchema(schema_doc) xml_is_valid = False if 'xml' in data: xml_filename = data['xml'].name doc = etree.parse(data['xml']) #xmlschema.assertValid(doc) if not xmlschema.validate(doc): msg = 'XML-Datei entspricht nicht der Formatvorgabe!' self._errors['xml'] = self.error_class([msg]) else: data['xml'] = doc xml_is_valid = True # wenn das XML gueltig war muessen wir noch ueberpruefen, ob # wir das entsprechende Produkt ueberhaupt liefern koennen if xml_is_valid: ean = doc.xpath('/order/ean')[0].text menge = doc.xpath('/order/menge')[0].text api = CreateApiResource('inventory/Alternatives') alternatives = api.search(ean, menge) if len(alternatives) == 0: msg = 'Die EAN %s ist zur Zeit nicht lieferbar!' % ean self._errors['xml'] = self.error_class([msg]) else: artnr = etree.Element('artnr') artnr.text = alternatives[0]['articles'][0]['artnr'] doc.xpath('/order')[0].append(artnr) # heisst das PDF genauso wie die XML-Datei? if 'pdf' in data and xml_filename: id = xml_filename.split('.')[0] if not data['pdf'].name.startswith(id): msg = 'PDF-Datei heisst nicht genauso wie die XML-Datei!' self._errors['pdf'] = self.error_class([msg]) return data
def nnnotifications(request): """View für Seite zur Änderung der (E-Mail-)Benachrichtigungen""" def add_notification(**kwargs): result = api.create(customer=kwargs['customer'], recipient=kwargs['recipient'], status=kwargs['status'], means='email') # kwargs['means'] return result def remove_notification(customer, designator): result = api.remove(customer=customer, designator=designator) return result api = CreateApiResource('robotRock/Notification') notifications = api.read(request.customer.kundennr) if request.method == "POST": form = NotificationCreationForm(request.POST) # Hinzufügen oder Löschen von Notifications? if 'delete' in request.POST: for designator in request.POST.getlist('notification_designator'): remove_notification(request.customer.kundennr, designator) return redirect('account.notifications') elif 'add' in request.POST: if form.is_valid(): add_notification(customer=request.customer.kundennr, **form.cleaned_data) return redirect('account.notifications') else: form = NotificationCreationForm() return render_to_response('beliza/customers/notifications.html', {'form': form, 'notifications': notifications}, context_instance=RequestContext(request))
class LieferscheinGenerator(JasperGenerator): """ Der Generator fuer die Lieferschein-PDFs bei Serviceauftraegen """ def __init__(self): super(LieferscheinGenerator, self).__init__() self.reportname = os.path.abspath(os.path.join(os.path.dirname(__file__), 'reports', 'Lieferschein.jrxml')) self.xpath = 'lieferscheine/lieferschein/position' self.root = ET.Element('lieferscheine') self.eap = CreateApiResource('inventory/EAP') def generate_xml(self, data): """ erzeugt das XML-File mit den Lieferscheindaten als Eingabe fuer Jasper """ os.environ['PYJASPER_SERVLET_URL'] = getattr(settings, 'PYJASPER_SERVLET_URL', None) ET.SubElement(self.root, 'generator').text = '__revision__' return self.lieferschein2xml(*data) def lieferschein2xml(self, order_form, orderlines_formset): """ Generic functionality to turn a Lieferschein object into XML.""" sendung = ET.SubElement(self.root, 'lieferschein') data = order_form.cleaned_data ET.SubElement(sendung, 'designator').text = data['kundenauftragsnr'] ET.SubElement(sendung, 'lieferscheinnr').text = '' ET.SubElement(sendung, 'liefer_date').text = '' ET.SubElement(sendung, 'kommissionierbelegnr').text = '' ET.SubElement(sendung, 'auftragsnr').text = '' ET.SubElement(sendung, 'auftragsnr_kunde').text = data['kundenauftragsnr'] ET.SubElement(sendung, 'warenempfaenger').text = data.get('name1', '') ET.SubElement(sendung, 'name1').text = data.get('name1', '') ET.SubElement(sendung, 'name2').text = data.get('name2', '') ET.SubElement(sendung, 'strasse').text = data.get('strasse') ET.SubElement(sendung, 'plz').text = data.get('plz') ET.SubElement(sendung, 'ort').text = data.get('ort') ET.SubElement(sendung, 'land').text = data.get('land') ET.SubElement(sendung, 'anfangstext').text = data.get('freitext', '') for form in orderlines_formset.forms: artnr = form.cleaned_data.get('artnr') product = self.eap.fetch(artnr) pos = ET.SubElement(sendung, 'position') ET.SubElement(pos, 'menge').text = str(form.cleaned_data['menge']) ET.SubElement(pos, 'artnr').text = artnr ET.SubElement(pos, 'name').text = form.cleaned_data['name'] ET.SubElement(pos, 'ean').text = product.get('ean', '') return self.root
def index(request): """Zeige Startseite mit Auftragübersicht des aktuellen Kunden an""" customer = request.customer api = CreateApiResource('robotRock/Order') # welche Seite sollen wir in der Pagination anzeigen und wieviele Zeilen # pro Seite haben wir? orders_per_page = 20 try: page = max(0, int(request.GET.get('page', 0))) except ValueError: page = 0 # soll die Liste der Auftraege gefiltert werden? filter = request.REQUEST.get('filter', '') # es sollen nicht alle moeglichen RobotRock-Status auch in der Uebersicht # einzelnen angezeigt werden. Deshalb mappen wir jetzt die Beliza-Status auf # die jeweiligen Kombinationen von RobotRock-Status. status_mappings = {'new': ['new'], 'packaged': ['bundled', 'packed'], 'shipped': ['shipped', 'canceled', 'charged', 'payed'], 'problematic': ['problematic', 'locked']} # Wenn es problematische Aufträge gibt, soll der Kunde auf der Startseite # den entsprechenden Reiter sehen. Wenn diese problematischen Auftraege daher # kommen, das das Kreditlimit erschoepft ist (Status 'locked') muss zusaetzlich # noch ein entsprechender Hinweis anzeigt werden. problematic_orders = api.list(customer, filter, status_mappings['problematic'], orders_per_page, page * orders_per_page) or [] is_locked = reduce(lambda x, y: x or y, map(lambda order: order.status == 'locked', problematic_orders), False) if is_locked: messages.warning(request, u'Ihr Kreditlimit ist überschritten, neue Aufträge werden bis auf Weiteres nicht bearbeitet!') status = request.REQUEST.get('status', None) if status is None: status = 'problematic' if len(problematic_orders)>0 else None mapping = status_mappings.get(status) if mapping is None: status = 'new' mapping = status_mappings[status] # jetzt muessen wir noch die anzuzeigenden Auftraege laden, wenn wir sie nicht # bereits als problematische Auftraege geladen haben if status == 'problematic': orders = problematic_orders else: orders = api.list(customer, filter, mapping, orders_per_page, page * orders_per_page) # jetzt die Pagination-Infos zusammenbauen, dazu holen wir uns die erste Zeile order = orders[0] if orders else {} paginator = Paginator(page, orders_per_page, order.get('total_rows', 0)) # und schliesslich die Liste anzeigen ctxt = {'orders': orders, 'status': status, 'paginator': paginator, 'filter': filter, } return render_to_response_with_request(request, 'beliza/orders/index.html', ctxt)
def __init__(self): super(LieferscheinGenerator, self).__init__() self.reportname = os.path.abspath(os.path.join(os.path.dirname(__file__), 'reports', 'Lieferschein.jrxml')) self.xpath = 'lieferscheine/lieferschein/position' self.root = ET.Element('lieferscheine') self.eap = CreateApiResource('inventory/EAP')
except Exception, ex: logger.error("unable to delete notification '%s': %s" % (designator, ex)) return render_to_json({'result': 'ok'}) # sollen wir eine Aktion durchfuehren? if request.method == "POST": what = request.POST.get('what') if what == 'create': return add_notification(request.POST) elif what == 'delete': return delete_notifications(request.POST.getlist('ids[]')) else: return render_to_json({'result': 'error', 'msg': 'Ungueltige Aktion!'}) # oder nur die Seite anzeigen? api = CreateApiResource('robotRock/Notification') notifications = [] for notification in api.read(request.customer.kundennr): notifications.append({'designator': notification.designator, 'email': notification.recipient, 'event': NOTIFICATION_EVENTS.get(notification.status, '(Unbekanntes Ereignis)')}) paginator = Paginator(request, 10, len(notifications)) return render_to_response('beliza/customers/notifications.html', {'notifications': notifications[paginator.start():paginator.stop()], 'paginator': paginator}, context_instance=RequestContext(request)) @breadcrumb(u'Benutzerverwaltung') def users(request):