Ejemplo n.º 1
0
 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'})
Ejemplo n.º 2
0
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)
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
 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))
Ejemplo n.º 5
0
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
Ejemplo n.º 6
0
    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'))
Ejemplo n.º 7
0
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.'})
Ejemplo n.º 8
0
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)})
Ejemplo n.º 9
0
    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())
Ejemplo n.º 10
0
    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
Ejemplo n.º 11
0
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'})
Ejemplo n.º 12
0
    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
Ejemplo n.º 13
0
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))
Ejemplo n.º 14
0
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
Ejemplo n.º 15
0
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)
Ejemplo n.º 16
0
 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')
Ejemplo n.º 17
0
            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):