I have updated my code-- I want to pass an object in "for loop" with employee_id and his specific donation amount, How can I do this?

Viewed 236

I am working on a donation app. In this app, There was a feature that sends an equal amount of donation money to every employee of the organization now they want to change this feature by sending a customized amount of donation to all or some of the employees. I have worked on it: Now I am using a for loop which iterates over the list of employees id and gives the amount to each id. But What I want is to pass an object in a for loop, where the object has an id from list of ids and the amount received from payload. I want to keep that id with his specific amount locked in an object Here is my code now:

class BusinessDonationController(BaseController):
    def create(self, request, response, business):
        employees =Employment.objects.filter(business=business, active=True)
        ids = employees.values_list('id', flat=True)
        donation_amount = []
        for id in ids:
            try:
                amount = int(request.payload.get("amount"))
                donation_amount.append({
                    "id" : id,
                    "amount" : amount
                })
            except ValueError:
                return response.bad_request("Invalid donation amounts, %s, should be in whole dollars" % amount)
        return donation_amount

3 Answers

One approach I can think of is, you can customize the amount of donation of some/all employees and distribute the rest to others equally. For example:

I want to donate $10,000 to 10 employees. Originally, each of them would receive $1000. But I want Employee-A and Employee-B to receive $1200 and $1300 respectively. Now I am left with $8500 and 8 employees. So, each 8 of them will receive $1062.5.

Implementation: (AJAX + DRF)

You have to add some input fields in your front-end. This is to customize which employee should receive how much donation. You should keep track of the employeeId as you will need it later while sending the payload to your server.

Create a JSON list (from your form) like this and pass it to the API call.

let payload = [
    {"employee_id": 1, "amount": 1300.0},
    {"employee_id": 2, "amount": 1200.0},
]

You can use any method to send the data. For example: in AJAX you would something like that:

$.ajax({
    type: "POST",
    url: "/your/api/endpoint/",
    data: {
        // Send `donation_amount` too.
        // This will help to validate data in backend.
        donation_amount: 10000.0,

        customized_amounts: payload
    },
    traditional: true,

    beforeSend: function () {
        // show some loading animation.
    },

    success: function (data) {
        // show a success toast or redirect.
    },

    error: function (error) {
        // show some error toast.
    },
});

In the backend create a serializer:

from rest_framework import serializers
from django.utils.text import gettext_lazy as _

# TODO: from .models import Business


class DonationSerializer(serializers.Serializer):
    business = serializers.PrimaryKeyRelatedField(label=_('Business'), queryset=Business.objects.all(), required=True)
    donation_amount = serializers.FloatField(label=_('Donation Amount'), required=True, min_value=0.0)
    customized_amounts = serializers.JSONField(label=_('Customized Amounts'), default=list, required=False)

    def validate(self, attrs):
        donation_amount = attrs.get('donation_amount', 0.0)
        customized_amounts = attrs.get('customized_amounts', [])

        if donation_amount == 0.0:
            raise serializers.ValidationError(_('Donation cannot be empty!'))

        partial_sum = 0.0
        for data in customized_amounts:
            # Checking if employee_id is valid or not
            employee_id = data.get('employee_id')
            if not Employment.objects.filte(id=employee_id).exitst():
                raise serializers.ValidationError(_(f'Employee with id: ${employee_id} does not exists!'))

            # summing up amount to check if it exceeds total amount
            partial_sum += data.get('amount')

        if partial_sum > donation_amount:
            raise serializers.ValidationError(_('Individual donation amount exceeds total amount!'))

        # add any other validation you want.

        return attrs

    def update(self, instance, validated_data):
        pass

    def create(self, validated_data):
        pass

and an API endpoint:

from rest_framework import status
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response

# TODO: from .models import Employment
# TODO: from .tasks import run_employee_donation


class DonationCreateAPIView(GenericAPIView):
    def post(self, request, *args, **kwargs):
        serializer = DonationSerializer(data=request.data, context={'request': request})
        serializer.is_valid(raise_exception=True)

        business = serializer.validated_data.get('business')
        donation_amount = serializer.validated_data.get('donation_amount')
        customized_amounts = serializer.validated_data.get('customized_amounts')

        employee_qs = Employment.objects.filter(business=business, active=True)
        total_employees = employee_qs.count()

        donation_per_employee = donation_amount / (total_employees - len(customized_amounts))

        for employee in employee_qs:
            customized_amount = [data for data in customized_amounts if data['employee_id'] == employee.id]

            if len(customized_amount) > 0:
                # Customized donation for this employee found.
                run_employee_donation(employee_id=employee.id, amount=customized_amount[0].get('amount'))
            else:
                run_employee_donation(employee_id=employee.id, amount=donation_per_employee)

        return Response({'success': True}, status=status.HTTP_201_CREATED)

create a model to store employee and donation. List all employees. user can click on an employee name to display a form to edit the amount.

This Worked for me!!

class BusinessDonationController(BaseController):
    def create(self, request, response, business):
        business = Business.objects.get(id=business)
        employees =Employment.objects.filter(business=business, active=True)
        ids = employees.values_list('id', flat=True)
        donation_amount = []
        try:
            employee_id = int(request.payload.get("employee_id"))
            amount = int(request.payload.get("amount"))
            donation_amount.append({
                "employee_id" : employee_id,
                "amount" : amount
            })
        except ValueError:
            return response.bad_request("Invalid donation amounts, %s, should be in whole dollars" % amount)

        for employee in employees:
            if employee.id == employee_id:
                credit_account = CreditAccount.objects.create(deposit=deposit, total_amount=amount, current_amount=amount, employment=employee)
        if error != '' and error is not None:
            return response.bad_request(error)

        response.set(**{'success': True})

Related