Как я могу получить поле суммы пожертвования для каждого сотрудника в Django из фронтенда?

Я работаю над приложением для пожертвований. В этом приложении я меняю функцию, чтобы каждый сотрудник организации получал равную сумму пожертвования на индивидуальную сумму пожертвования. Я буду получать разные суммы пожертвований для каждого сотрудника из фронтенда. Я не совсем понимаю, как это сделать. Вот мой код:

class BusinessDonation():
    def create(self, request, response, business):
        employees= Employment.objects.filter(business=business, active=True)
        try:
            amounts = int(request.payload.get("amounts"))
            total = int(request.payload.get("total"))
        except ValueError:
            return response.bad_request("Invalid donation amounts, %s, should be in whole dollars" % amounts)

        error = run_employee_donation(business.id, to_cents(amounts))
        if error != '' and error is not None:
            return response.bad_request(error)

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


Один из подходов, о котором я могу подумать, заключается в том, что вы можете настроить сумму пожертвования некоторых/всех сотрудников и распределить остальную сумму между остальными поровну. Например:

Я хочу пожертвовать $10,000 сотрудникам 10. Первоначально каждый из них получит $1000. Но я хочу, чтобы работник-А и работник-Б получили $1200 и $1300 соответственно. Теперь у меня осталось $8500 и 8 сотрудников. Таким образом, каждый 8 из них получит $1062,5.

Реализация: (AJAX + DRF)

Вам необходимо добавить несколько полей ввода во фронт-энде. Это нужно для того, чтобы настроить, кто из сотрудников сколько должен получить пожертвований. Вы должны отслеживать employeeId, так как они понадобятся вам позже при отправке полезной нагрузки на ваш сервер.

Создайте JSON-список (из вашей формы) следующим образом и передайте его в вызов API.

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

Для отправки данных вы можете использовать любой метод. Например: в AJAX вы бы сделали что-то вроде этого:

$.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.
    },
});

В бэкенде создайте сериализатор:

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

и конечная точка API:

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)

создайте модель для хранения данных о сотрудниках и пожертвованиях. Выведите список всех сотрудников. Пользователь может щелкнуть на имени сотрудника, чтобы отобразить форму для редактирования суммы.

Это сработало для меня!!!

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})

Вернуться на верх