예제 #1
0
    def form_valid(self, form):
        # if the person was just changed from unaffiliated to an associate member, send them an email.
        if 'groups' in form.changed_data and 'groups' in form.cleaned_data:
            oldgroups = form.initial['groups']
            newgroups = form.cleaned_data['groups']
            if not oldgroups and Group.objects.get(
                    name='Associate') in newgroups:
                email = DefaultLNLEmailGenerator(
                    subject="Welcome to LNL!",
                    to_emails=[self.object.email],
                    bcc=[settings.EMAIL_TARGET_S],
                    reply_to=[settings.EMAIL_TARGET_S],
                    context={'new_member': self.object},
                    template_basename='emails/email_welcome')
                email.send()
                messages.success(self.request, "Welcome email sent")
            # Ensure that title is stripped when no longer an officer
            if Group.objects.get(name="Officer") not in newgroups:
                self.object.title = None
                self.object.save()

        messages.success(self.request,
                         "Account Info Saved!",
                         extra_tags='success')
        return super(UserUpdateView, self).form_valid(form)
예제 #2
0
def snipe_checkout(request):
    if not settings.SNIPE_URL:
        return HttpResponse('This page is unavailable because SNIPE_URL is not set.', status=501)
    if not settings.SNIPE_API_KEY:
        return HttpResponse('This page is unavailable because SNIPE_API_KEY is not set.', status=501)
    # Get the list of users in the rental group from Snipe
    error_message = 'Error communicating with Snipe. Did not check out anything.'
    checkout_to_choices = []
    response = requests.request('GET', '{}api/v1/users'.format(settings.SNIPE_URL), headers={
        'authorization': 'Bearer {}'.format(settings.SNIPE_API_KEY),
    })
    if response.status_code == 200:
        try:
            data = json.loads(response.text)
            if data.get('status') == 'error':
                return HttpResponse(error_message, status=502)
            checkout_to_choices = [(user['id'], user['name']) for user in data['rows'] if 'rental' in ((group['name'] for group in user['groups']['rows']) if user['groups'] is not None else ())]
        except ValueError:
            return HttpResponse(error_message, status=502)
    else:
        return HttpResponse(error_message, status=502)

    # Handle the form
    error_message = 'Error communicating with Snipe. Some things may have been checked out while some were not. ' \
                    'Please go check Snipe.'
    if request.method == 'POST':
        receipt_info = {}
        form = forms.SnipeCheckoutForm(checkout_to_choices, request.POST, request.FILES)
        if form.is_valid():
            success_count_assets = 0
            success_count_accessories = 0
            for tag in [tag for tag in re.split('[^a-zA-Z0-9]', form.cleaned_data['asset_tags']) if tag]:
                match = re.match('LNLACC([0-9]+)', tag)
                if match:
                    tag = match.group(1)
                    # This tag represents an accessory
                    response = requests.request('GET', '{}api/v1/accessories/{}'.format(settings.SNIPE_URL, tag),
                                                headers={'authorization': 'Bearer {}'.format(settings.SNIPE_API_KEY),
                                                         'accept': 'application/json'})
                    if response.status_code == 200:
                        try:
                            data = json.loads(response.text)
                            if data.get('status') == 'error':
                                # No accessory with that ID exists in Snipe
                                messages.add_message(request, messages.ERROR, 'No such accessory with ID {}'.format(tag))
                                continue
                            accessory_name = data['name']
                            rental_price = float(data['order_number']) if data['order_number'] is not None else None
                            # Check out the accessory
                            response = requests.request('POST', '{}api/v1/accessories/{}/checkout'.format(settings.SNIPE_URL, tag), data=json.dumps({
                                'assigned_to': form.cleaned_data['checkout_to'],
                            }), headers={
                                'authorization': 'Bearer {}'.format(settings.SNIPE_API_KEY),
                                'accept': 'application/json',
                                'content-type': 'application/json',
                            })
                            if response.status_code == 200:
                                data = json.loads(response.text)
                                if data.get('status') == 'error':
                                    # Snipe refused to check out the accessory (maybe they are all checked out)
                                    messages.add_message(request, messages.ERROR, 'Unable to check out accessory {}. Snipe says: {}'.format(tag, data['messages']))
                                    continue
                                # The accessory was successfully checked out
                                success_count_accessories += 1
                                if tag in receipt_info:
                                    if receipt_info[tag]['name'] != accessory_name \
                                            or receipt_info[tag]['rental_price'] != rental_price:
                                        return HttpResponse(error_message, status=502)
                                    receipt_info[tag]['quantity'] += 1
                                else:
                                    receipt_info[tag] = {'name': accessory_name, 'rental_price': rental_price,
                                                         'quantity': 1}
                            else:
                                return HttpResponse(error_message, status=502)
                        except ValueError:
                            return HttpResponse(error_message, status=502)
                    else:
                        return HttpResponse(error_message, status=502)
                else:
                    # This tag represents an asset
                    response = requests.request('GET', '{}api/v1/hardware/bytag/{}'.format(settings.SNIPE_URL, tag),
                                                headers={'authorization': 'Bearer {}'.format(settings.SNIPE_API_KEY),
                                                         'accept': 'application/json'})
                    if response.status_code == 200:
                        try:
                            data = json.loads(response.text)
                            if data.get('status') == 'error':
                                # The asset tag does not exist in Snipe
                                messages.add_message(request, messages.ERROR, 'No such asset tag {}'.format(tag))
                                continue
                            asset_name = data['name']
                            if 'custom_fields' in data and 'Rental Price' in data['custom_fields'] and \
                                    'value' in data['custom_fields']['Rental Price'] and data['custom_fields']['Rental Price']['value'] is not None:
                                rental_price = float(data['custom_fields']['Rental Price']['value'])
                            else:
                                rental_price = None
                            # Check out the asset
                            response = requests.request('POST', '{}api/v1/hardware/{}/checkout'.format(settings.SNIPE_URL, data['id']), data=json.dumps({
                                'checkout_to_type': 'user',
                                'assigned_user': form.cleaned_data['checkout_to'],
                            }), headers={
                                'authorization': 'Bearer {}'.format(settings.SNIPE_API_KEY),
                                'accept': 'application/json',
                                'content-type': 'application/json',
                            })
                            if response.status_code == 200:
                                data = json.loads(response.text)
                                if data.get('status') == 'error':
                                    # Snipe refused to check out the asset (maybe it is already checked out)
                                    messages.add_message(request, messages.ERROR, 'Unable to check out asset {} - {}. Snipe says: {}'.format(tag, asset_name, data['messages']))
                                    continue
                                # The asset was successfully checked out
                                success_count_assets += 1
                                if tag in receipt_info:
                                    return HttpResponse(error_message, status=502)
                                receipt_info[tag] = {'name': asset_name, 'rental_price': rental_price, 'quantity': 1}
                            else:
                                return HttpResponse(error_message, status=502)
                        except ValueError:
                            return HttpResponse(error_message, status=502)
                    else:
                        return HttpResponse(error_message, status=502)
            if success_count_assets > 0 or success_count_accessories > 0:
                messages.add_message(request, messages.SUCCESS, 'Successfully checked out {} assets and {} accessories'.format(success_count_assets, success_count_accessories))
            rental_prices = [(None if asset_info['rental_price'] is None else asset_info['rental_price'] * asset_info['quantity']) for asset_info in receipt_info.values()]
            total_rental_price = None if None in rental_prices else sum(rental_prices)
            checkout_to_name = next((item[1] for item in checkout_to_choices if item[0] == form.cleaned_data['checkout_to']))
            # Before returning the response, email a PDF receipt
            html = render_to_string('pdf_templates/inventory-receipt.html', request=request, context={
                'title': 'Checkout Receipt',
                'receipt_info': receipt_info,
                'num_assets': success_count_assets,
                'num_accessories': success_count_accessories,
                'total_rental_price': total_rental_price,
                'checkout_to': checkout_to_name,
            })
            pdf_file = BytesIO()
            pisa.CreatePDF(html, dest=pdf_file, link_callback=link_callback)
            pdf_handle = pdf_file.getvalue()
            filename = 'LNL-checkout-receipt-{}.pdf'.format(timezone.now().isoformat())
            attachments = [{'file_handle': pdf_handle, 'name': filename}]
            email = DefaultLNLEmailGenerator(subject='LNL Inventory Checkout Receipt', attachments=attachments,
                                             to_emails=(request.user.email, settings.DEFAULT_TO_ADDR),
                                             body='A receipt for the rental checkout by {} to {} is '
                                                  'attached.'.format(request.user, checkout_to_name))
            email.send()
            # Return the response
            return render(request, 'inventory/checkout_receipt.html', {
                'receipt_info': receipt_info,
                'num_assets': success_count_assets,
                'num_accessories': success_count_accessories,
                'total_rental_price': total_rental_price,
                'checkout_to': form.cleaned_data['checkout_to'],
                'checkout_to_name': checkout_to_name,
            })
        else:
            form = forms.SnipeCheckoutForm(checkout_to_choices, initial={'checkout_to': form.cleaned_data['checkout_to']})
    else:
        if 'checkout_to' in request.GET:
            form = forms.SnipeCheckoutForm(checkout_to_choices, initial={'checkout_to': request.GET['checkout_to']})
        else:
            form = forms.SnipeCheckoutForm(checkout_to_choices)
    return render(request, "form_crispy.html", {
        'msg': 'Inventory checkout',
        'form': form,
    })