|
|
|
from datetime import datetime, timedelta, timezone
|
|
|
|
from decimal import Decimal
|
|
|
|
from django.contrib.auth.models import User, Group
|
|
|
|
from django.shortcuts import get_object_or_404
|
|
|
|
from rest_framework import serializers
|
|
|
|
from caremyway.api.models import UserInfo, Client, Provider, WorkType, Manage, Price, Shift
|
|
|
|
|
|
|
|
class UserInfoSerializer(serializers.ModelSerializer):
|
|
|
|
class Meta:
|
|
|
|
model = UserInfo
|
|
|
|
fields = ('dob', 'address1', 'address2', 'city', 'province', 'postal_code', 'phone_number')
|
|
|
|
|
|
|
|
def create(self, validated_data):
|
|
|
|
validated_data['user'] = self.context['request'].user
|
|
|
|
return serializers.ModelSerializer.create(self, validated_data)
|
|
|
|
|
|
|
|
class WorkTypeSerializer(serializers.ModelSerializer):
|
|
|
|
class Meta:
|
|
|
|
model = WorkType
|
|
|
|
fields = ('uuid', 'color', 'label', 'deleted')
|
|
|
|
read_only_fields = ('deleted',)
|
|
|
|
|
|
|
|
def create(self, validated_data):
|
|
|
|
validated_data['client'] = self.context['request'].user.client
|
|
|
|
return serializers.ModelSerializer.create(self, validated_data)
|
|
|
|
|
|
|
|
def update(self, instance, validated_data):
|
|
|
|
if 'label' in validated_data:
|
|
|
|
raise serializers.ValidationError("Cannot update field.")
|
|
|
|
return super().update(instance, validated_data)
|
|
|
|
|
|
|
|
class PriceSerializer(serializers.ModelSerializer):
|
|
|
|
get_employee_uuid = serializers.UUIDField(write_only=True)
|
|
|
|
get_work_type_uuid = serializers.UUIDField(write_only=True)
|
|
|
|
work_type = WorkTypeSerializer(read_only=True)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
model = Price
|
|
|
|
fields = ('uuid', 'get_employee_uuid', 'get_work_type_uuid', 'work_type', 'amount', 'deleted')
|
|
|
|
read_only_fields = ('deleted',)
|
|
|
|
depth = 1
|
|
|
|
|
|
|
|
def create(self, validated_data):
|
|
|
|
user = self.context['request'].user
|
|
|
|
|
|
|
|
if not Client.objects.filter(user=user).exists():
|
|
|
|
raise serializers.ValidationError("User is not a client.")
|
|
|
|
|
|
|
|
client = user.client
|
|
|
|
manage_objs = Manage.objects.filter(deleted=False).filter(client=client)
|
|
|
|
employee_uuid = validated_data.pop('get_employee_uuid')
|
|
|
|
employee = get_object_or_404(manage_objs, uuid=employee_uuid)
|
|
|
|
worktype_objs = WorkType.objects.filter(deleted=False).filter(client=client)
|
|
|
|
work_type_uuid = validated_data.pop('get_work_type_uuid')
|
|
|
|
work_type = get_object_or_404(worktype_objs, uuid=work_type_uuid)
|
|
|
|
|
|
|
|
if not employee.approved:
|
|
|
|
raise serializers.ValidationError("Employee hasn't approved employment yet.")
|
|
|
|
|
|
|
|
if Price.objects.filter(deleted=False) \
|
|
|
|
.filter(work_type=work_type) \
|
|
|
|
.filter(management=employee).exists():
|
|
|
|
raise serializers.ValidationError("Price for this work already defined.")
|
|
|
|
|
|
|
|
validated_data['management'] = employee
|
|
|
|
validated_data['work_type'] = work_type
|
|
|
|
return serializers.ModelSerializer.create(self, validated_data)
|
|
|
|
|
|
|
|
class EmployeeUserSerializer(serializers.ModelSerializer):
|
|
|
|
userinfo = UserInfoSerializer(read_only=True)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
model = User
|
|
|
|
fields = ('is_active', 'first_name', 'last_name', 'email', 'userinfo')
|
|
|
|
depth = 1
|
|
|
|
|
|
|
|
class EmployeeSerializer(serializers.ModelSerializer):
|
|
|
|
provider_email = serializers.EmailField(write_only=True)
|
|
|
|
provider = serializers.SerializerMethodField()
|
|
|
|
prices = PriceSerializer(many=True, read_only=True)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
model = Manage
|
|
|
|
fields = ('uuid', 'provider', 'provider_email', 'note', 'approved', 'prices', 'deleted')
|
|
|
|
read_only_fields = ('approved', 'deleted')
|
|
|
|
|
|
|
|
def get_provider(self, obj):
|
|
|
|
if obj.approved == True:
|
|
|
|
user = User.objects.get(provider=obj.provider)
|
|
|
|
return EmployeeUserSerializer(user).data
|
|
|
|
else:
|
|
|
|
return obj.provider.user.email
|
|
|
|
|
|
|
|
def create(self, validated_data):
|
|
|
|
user = self.context['request'].user
|
|
|
|
|
|
|
|
if not Client.objects.filter(user=user).exists():
|
|
|
|
raise serializers.ValidationError("User is not a client.")
|
|
|
|
|
|
|
|
client = user.client
|
|
|
|
provider_email = validated_data.pop('provider_email')
|
|
|
|
provider = get_object_or_404(Provider, user__email=provider_email)
|
|
|
|
|
|
|
|
if Manage.objects.filter(deleted=False) \
|
|
|
|
.filter(provider=provider) \
|
|
|
|
.filter(client=client).exists():
|
|
|
|
raise serializers.ValidationError("Employee already added.")
|
|
|
|
|
|
|
|
validated_data['client'] = client
|
|
|
|
validated_data['provider'] = provider
|
|
|
|
return serializers.ModelSerializer.create(self, validated_data)
|
|
|
|
|
|
|
|
class ClientSerializer(serializers.ModelSerializer):
|
|
|
|
work_types = WorkTypeSerializer(many=True, read_only=True)
|
|
|
|
employees = EmployeeSerializer(many=True, read_only=True)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
model = Client
|
|
|
|
fields = ('business_number', 'alt_name', 'alt_address1', 'alt_address2', 'alt_city', 'alt_province', 'alt_phone_number', 'work_types', 'employees')
|
|
|
|
|
|
|
|
def create(self, validated_data):
|
|
|
|
user = self.context['request'].user
|
|
|
|
|
|
|
|
if Provider.objects.filter(user=user).exists():
|
|
|
|
raise serializers.ValidationError("User is already a Provider.")
|
|
|
|
|
|
|
|
validated_data['user'] = user
|
|
|
|
return serializers.ModelSerializer.create(self, validated_data)
|
|
|
|
|
|
|
|
class EmployerUserSerializer(serializers.ModelSerializer):
|
|
|
|
userinfo = UserInfoSerializer(read_only=True)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
model = User
|
|
|
|
fields = ('is_active', 'first_name', 'last_name', 'email', 'userinfo')
|
|
|
|
depth = 1
|
|
|
|
|
|
|
|
class EmployerSerializer(serializers.ModelSerializer):
|
|
|
|
client = serializers.SerializerMethodField()
|
|
|
|
prices = PriceSerializer(many=True, read_only=True)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
model = Manage
|
|
|
|
fields = ('uuid', 'client', 'note', 'approved', 'prices', 'deleted')
|
|
|
|
read_only_fields = ('note', 'deleted')
|
|
|
|
|
|
|
|
def get_client(self, obj):
|
|
|
|
if obj.approved == True:
|
|
|
|
user = User.objects.get(client=obj.client)
|
|
|
|
return EmployerUserSerializer(user).data
|
|
|
|
else:
|
|
|
|
return obj.client.user.first_name + ' ' + obj.client.user.last_name
|
|
|
|
|
|
|
|
class ProviderSerializer(serializers.ModelSerializer):
|
|
|
|
employers = EmployerSerializer(many=True, read_only=True)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
model = Provider
|
|
|
|
fields = ('sin', 'cert_title1', 'cert_date1', 'cert_institution1', 'cert_title2', 'cert_date2', 'cert_institution2', 'cert_title3', 'cert_date3', 'cert_institution3', 'emerg_contact_name', 'emerg_contact_number', 'crim_record_check_date', 'employers')
|
|
|
|
|
|
|
|
def create(self, validated_data):
|
|
|
|
user = self.context['request'].user
|
|
|
|
|
|
|
|
if Client.objects.filter(user=user).exists():
|
|
|
|
raise serializers.ValidationError("User is already a Client.")
|
|
|
|
|
|
|
|
validated_data['user'] = user
|
|
|
|
return serializers.ModelSerializer.create(self, validated_data)
|
|
|
|
|
|
|
|
class UserSerializer(serializers.ModelSerializer):
|
|
|
|
userinfo = UserInfoSerializer(read_only=True)
|
|
|
|
client = ClientSerializer(read_only=True)
|
|
|
|
provider = ProviderSerializer(read_only=True)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
model = User
|
|
|
|
fields = ('username', 'is_active', 'first_name', 'last_name', 'email', 'userinfo', 'client', 'provider')
|
|
|
|
depth = 1
|
|
|
|
|
|
|
|
class ShiftSerializer(serializers.ModelSerializer):
|
|
|
|
price = serializers.SerializerMethodField()
|
|
|
|
amount = serializers.SerializerMethodField()
|
|
|
|
|
|
|
|
def get_price(self, obj):
|
|
|
|
return obj.price.uuid
|
|
|
|
|
|
|
|
def get_amount(self, obj):
|
|
|
|
if obj.approved_end:
|
|
|
|
shift_length = obj.approved_end - obj.approved_start
|
|
|
|
return Decimal(shift_length.total_seconds()) / 3600 * obj.set_price
|
|
|
|
else:
|
|
|
|
return None
|
|
|
|
|
|
|
|
class CShiftSerializer(ShiftSerializer):
|
|
|
|
get_price_uuid = serializers.UUIDField(write_only=True)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
model = Shift
|
|
|
|
fields = ('uuid', 'chart', 'get_price_uuid', 'price', 'set_price', 'set_start', 'set_end', 'actual_start', 'actual_end', 'approved_start', 'approved_end', 'approved_date', 'amount', 'description', 'provider_approved', 'deleted')
|
|
|
|
read_only_fields = ('chart', 'price', 'set_price', 'actual_start', 'actual_end', 'approved_date', 'provider_approved', 'deleted')
|
|
|
|
|
|
|
|
def create(self, validated_data):
|
|
|
|
user = self.context['request'].user
|
|
|
|
|
|
|
|
if not Client.objects.filter(user=user).exists():
|
|
|
|
raise serializers.ValidationError("User is not a client.")
|
|
|
|
|
|
|
|
client = user.client
|
|
|
|
price_objs = Price.objects.filter(deleted=False).filter(management__client=client)
|
|
|
|
price_uuid = validated_data.pop('get_price_uuid')
|
|
|
|
price = get_object_or_404(price_objs, uuid=price_uuid)
|
|
|
|
|
|
|
|
if price.management.deleted:
|
|
|
|
raise serializers.ValidationError("Employment relationship was deleted.")
|
|
|
|
if price.work_type.deleted:
|
|
|
|
raise serializers.ValidationError("Type of work was deleted.")
|
|
|
|
if not price.management.approved:
|
|
|
|
raise serializers.ValidationError("Employee hasn't approved employment yet.")
|
|
|
|
|
|
|
|
now = datetime.now(timezone.utc)
|
|
|
|
set_start = validated_data['set_start']
|
|
|
|
set_end = validated_data['set_end']
|
|
|
|
approved_start = validated_data['approved_start']
|
|
|
|
approved_end = validated_data['approved_end']
|
|
|
|
|
|
|
|
if approved_start or approved_end:
|
|
|
|
raise serializers.ValidationError("Can't set approved time on creation.")
|
|
|
|
if not set_start or not set_end:
|
|
|
|
raise serializers.ValidationError("Must include shift start and end times.")
|
|
|
|
if set_start > set_end:
|
|
|
|
raise serializers.ValidationError("Shift ends before it starts.")
|
|
|
|
if set_start > set_end - timedelta(hours=1):
|
|
|
|
raise serializers.ValidationError("Shift is less than one hour long.")
|
|
|
|
if set_start < now or set_end < now:
|
|
|
|
raise serializers.ValidationError("Shift is in the past.")
|
|
|
|
|
|
|
|
# TODO: Make sure provider isn't double-booked?????
|
|
|
|
|
|
|
|
validated_data['price'] = price
|
|
|
|
return serializers.ModelSerializer.create(self, validated_data)
|
|
|
|
|
|
|
|
def update(self, instance, validated_data):
|
|
|
|
set_start = validated_data['set_start']
|
|
|
|
set_end = validated_data['set_end']
|
|
|
|
approved_start = validated_data['approved_start']
|
|
|
|
approved_end = validated_data['approved_end']
|
|
|
|
|
|
|
|
if set_start and set_end:
|
|
|
|
if instance.actual_start:
|
|
|
|
raise serializers.ValidationError("Can't update after checkin.")
|
|
|
|
|
|
|
|
now = datetime.now(timezone.utc)
|
|
|
|
if set_start > set_end:
|
|
|
|
raise serializers.ValidationError("Shift ends before it starts.")
|
|
|
|
if set_start > set_end - timedelta(hours=1):
|
|
|
|
raise serializers.ValidationError("Shift is less than one hour long.")
|
|
|
|
if set_start < now or set_end < now:
|
|
|
|
raise serializers.ValidationError("Shift is in the past.")
|
|
|
|
|
|
|
|
# Reset provider approval on update
|
|
|
|
instance.provider_approved = None
|
|
|
|
|
|
|
|
instance.set_start = set_start
|
|
|
|
instance.set_end = set_end
|
|
|
|
|
|
|
|
elif approved_start and approved_end:
|
|
|
|
if not instance.actual_start:
|
|
|
|
raise serializers.ValidationError("Can't approve / edit time until after checkin.")
|
|
|
|
|
|
|
|
if approved_start > approved_end:
|
|
|
|
raise serializers.ValidationError("Shift ends before it starts.")
|
|
|
|
if approved_start > approved_end - timedelta(hours=1):
|
|
|
|
raise serializers.ValidationError("Shift is less than one hour long.")
|
|
|
|
|
|
|
|
instance.approved_start = approved_start
|
|
|
|
instance.approved_end = approved_end
|
|
|
|
instance.approved_date = approved_start.date()
|
|
|
|
else:
|
|
|
|
raise serializers.ValidationError("Missing field.")
|
|
|
|
|
|
|
|
instance.save()
|
|
|
|
return instance
|
|
|
|
|
|
|
|
class PShiftSerializer(ShiftSerializer):
|
|
|
|
action = serializers.ChoiceField(write_only=True, allow_blank=True, choices=['checkin', 'checkout'])
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
model = Shift
|
|
|
|
fields = ('uuid', 'action', 'chart', 'price', 'set_price', 'set_start', 'set_end', 'actual_start', 'actual_end', 'approved_start', 'approved_end', 'approved_date', 'amount', 'description', 'provider_approved', 'deleted')
|
|
|
|
read_only_fields = ('uuid', 'price', 'set_price', 'set_start', 'set_end', 'actual_start', 'actual_end', 'approved_start', 'approved_end', 'approved_date', 'description', 'deleted')
|
|
|
|
|
|
|
|
def update(self, instance, validated_data):
|
|
|
|
provider_approved = validated_data['provider_approved']
|
|
|
|
action = validated_data['action']
|
|
|
|
chart = validated_data['chart']
|
|
|
|
|
|
|
|
if provider_approved == True:
|
|
|
|
if instance.deleted:
|
|
|
|
raise serializers.ValidationError("Shift was deleted.")
|
|
|
|
|
|
|
|
instance.provider_approved = True
|
|
|
|
|
|
|
|
elif provider_approved == False:
|
|
|
|
if instance.actual_start:
|
|
|
|
raise serializers.ValidationError("Can't disapprove after check in.")
|
|
|
|
|
|
|
|
instance.provider_approved = False
|
|
|
|
|
|
|
|
if action == 'checkin':
|
|
|
|
if instance.deleted:
|
|
|
|
raise serializers.ValidationError("Shift was deleted.")
|
|
|
|
if not instance.provider_approved:
|
|
|
|
raise serializers.ValidationError("Shift hasn't been approved by the provider..")
|
|
|
|
if instance.actual_start:
|
|
|
|
raise serializers.ValidationError("Already checked in.")
|
|
|
|
if chart:
|
|
|
|
raise serializers.ValidationError("Can only provide chart on checkout.")
|
|
|
|
|
|
|
|
instance.actual_start = datetime.now(timezone.utc)
|
|
|
|
instance.set_price = instance.price.amount
|
|
|
|
|
|
|
|
elif action == 'checkout':
|
|
|
|
if not instance.actual_start:
|
|
|
|
raise serializers.ValidationError("Need to check in first.")
|
|
|
|
if instance.actual_end:
|
|
|
|
raise serializers.ValidationError("Already checked out.")
|
|
|
|
if not chart:
|
|
|
|
raise serializers.ValidationError("No chart info provided.")
|
|
|
|
|
|
|
|
instance.actual_end = datetime.now(timezone.utc)
|
|
|
|
instance.chart = chart
|
|
|
|
|
|
|
|
instance.save()
|
|
|
|
return instance
|
|
|
|
|
|
|
|
class TimeSheetSerializer(serializers.Serializer):
|
|
|
|
class ShiftSerializer(serializers.Serializer):
|
|
|
|
date = serializers.DateField()
|
|
|
|
start = serializers.DateTimeField()
|
|
|
|
end = serializers.DateTimeField()
|
|
|
|
hours = serializers.DecimalField(max_digits=8, decimal_places=2)
|
|
|
|
rate = serializers.DecimalField(max_digits=8, decimal_places=2)
|
|
|
|
amount = serializers.DecimalField(max_digits=8, decimal_places=2)
|
|
|
|
work = serializers.CharField()
|
|
|
|
|
|
|
|
management = serializers.CharField()
|
|
|
|
client = serializers.CharField()
|
|
|
|
provider = serializers.CharField()
|
|
|
|
payday = serializers.DateField()
|
|
|
|
paystart = serializers.DateField()
|
|
|
|
payend = serializers.DateField()
|
|
|
|
shifts = ShiftSerializer(many=True)
|
|
|
|
|
|
|
|
class RecordSheetSerializer(serializers.Serializer):
|
|
|
|
class RecordSerializer(serializers.Serializer):
|
|
|
|
payday = serializers.DateField()
|
|
|
|
reg_pay = serializers.DecimalField(max_digits=10, decimal_places=2)
|
|
|
|
vac_pay = serializers.DecimalField(max_digits=10, decimal_places=2)
|
|
|
|
earnings = serializers.DecimalField(max_digits=10, decimal_places=2)
|
|
|
|
cpp_ytd = serializers.DecimalField(max_digits=10, decimal_places=2)
|
|
|
|
cpp = serializers.DecimalField(max_digits=10, decimal_places=2)
|
|
|
|
ei_ytd = serializers.DecimalField(max_digits=10, decimal_places=2)
|
|
|
|
ei = serializers.DecimalField(max_digits=10, decimal_places=2)
|
|
|
|
taxable_income = serializers.DecimalField(max_digits=10, decimal_places=2)
|
|
|
|
fed_tax = serializers.DecimalField(max_digits=10, decimal_places=2)
|
|
|
|
fed_tax_payable = serializers.DecimalField(max_digits=10, decimal_places=2)
|
|
|
|
prov_tax = serializers.DecimalField(max_digits=10, decimal_places=2)
|
|
|
|
prov_tax_deduction = serializers.DecimalField(max_digits=10, decimal_places=2)
|
|
|
|
income_tax = serializers.DecimalField(max_digits=10, decimal_places=2)
|
|
|
|
total_deductions = serializers.DecimalField(max_digits=10, decimal_places=2)
|
|
|
|
net_pay = serializers.DecimalField(max_digits=10, decimal_places=2)
|
|
|
|
|
|
|
|
management = serializers.CharField()
|
|
|
|
client = serializers.CharField()
|
|
|
|
provider = serializers.CharField()
|
|
|
|
phone_number = serializers.CharField()
|
|
|
|
sin = serializers.CharField()
|
|
|
|
record = RecordSerializer(many=True)
|
|
|
|
|
|
|
|
class PayStubSerializer(serializers.Serializer):
|
|
|
|
management = serializers.CharField()
|
|
|
|
client = serializers.CharField()
|
|
|
|
provider = serializers.CharField()
|
|
|
|
payday = serializers.DateField()
|
|
|
|
reg_pay = serializers.DecimalField(max_digits=10, decimal_places=2)
|
|
|
|
vac_pay = serializers.DecimalField(max_digits=10, decimal_places=2)
|
|
|
|
earnings = serializers.DecimalField(max_digits=10, decimal_places=2)
|
|
|
|
cpp = serializers.DecimalField(max_digits=10, decimal_places=2)
|
|
|
|
ei = serializers.DecimalField(max_digits=10, decimal_places=2)
|
|
|
|
income_tax = serializers.DecimalField(max_digits=10, decimal_places=2)
|
|
|
|
total_deductions = serializers.DecimalField(max_digits=10, decimal_places=2)
|
|
|
|
net_pay = serializers.DecimalField(max_digits=10, decimal_places=2)
|