Files
ihrm/asset/forms.py

485 lines
16 KiB
Python
Raw Normal View History

2023-08-21 17:25:49 +05:30
"""
2023-12-01 15:36:51 +05:30
forms.py
2023-08-21 17:25:49 +05:30
Asset Management Forms
This module contains Django ModelForms for handling various aspects of asset management,
including asset creation, allocation, return, category assignment, and batch handling.
"""
2023-05-10 15:06:57 +05:30
import uuid
from datetime import date
2023-08-21 17:25:49 +05:30
from django import forms
from django.core.exceptions import ValidationError
2023-05-10 15:06:57 +05:30
from django.utils.translation import gettext_lazy as _
from asset.models import (
Asset,
AssetAssignment,
AssetCategory,
AssetDocuments,
AssetLot,
AssetReport,
AssetRequest,
)
from base.forms import ModelForm
2023-12-01 15:36:51 +05:30
from base.methods import reload_queryset
from employee.forms import MultipleFileField
from employee.models import Employee
from horilla.horilla_middlewares import _thread_locals
2023-05-10 15:06:57 +05:30
def set_date_field_initial(instance):
2023-08-21 17:25:49 +05:30
"""this is used to update change the date value format"""
2023-05-10 15:06:57 +05:30
initial = {}
if instance.asset_purchase_date is not None:
2023-08-21 17:25:49 +05:30
initial["asset_purchase_date"] = instance.asset_purchase_date.strftime(
"%Y-%m-%d"
)
2023-05-10 15:06:57 +05:30
return initial
class AssetForm(ModelForm):
2023-08-21 17:25:49 +05:30
"""
A ModelForm for creating and updating asset information.
"""
2023-05-10 15:06:57 +05:30
class Meta:
2023-08-21 17:25:49 +05:30
"""
Specifies the model and fields to be used for the AssetForm.
Attributes:
model (class): The model class Asset to be used for the form.
fields (str): A special value "__all__" to include all fields
of the model in the form.
"""
2023-05-10 15:06:57 +05:30
model = Asset
2023-08-21 17:25:49 +05:30
fields = "__all__"
exclude = ["is_active", "owner"]
2023-05-10 15:06:57 +05:30
widgets = {
2023-08-21 17:25:49 +05:30
"asset_name": forms.TextInput(
attrs={"placeholder": "Macbook Pro.", "class": "oh-input w-100"}
),
"asset_description": forms.Textarea(
attrs={
"type": "text",
"placeholder": _("A powerful laptop for business use."),
"class": "oh-input oh-input--textarea oh-input--block",
"rows": 3,
"cols": 40,
}
),
"asset_tracking_id": forms.TextInput(
attrs={"placeholder": "LPT001", "class": "oh-input w-100"}
),
"asset_purchase_date": forms.DateInput(
attrs={"type": "date", "class": "oh-input w-100"}
),
"expiry_date": forms.DateInput(
attrs={"type": "date", "class": "oh-input w-100"}
),
2023-08-21 17:25:49 +05:30
"asset_purchase_cost": forms.NumberInput(
attrs={"class": "oh-input w-100", "placeholder": "1200.00."}
),
"asset_category_id": forms.Select(
attrs={
"class": "oh-select oh-select-2 select2-hidden-accessible",
},
),
"asset_status": forms.Select(
attrs={"class": "oh-select oh-select--lg oh-select-no-search "}
),
"asset_lot_number_id": forms.Select(
attrs={
"class": "oh-select oh-select-2 select2-hidden-accessible ",
"placeholder": "LOT001",
"onchange": "batchNoChange($(this))",
2023-08-21 17:25:49 +05:30
}
),
2023-05-10 15:06:57 +05:30
}
2023-08-21 17:25:49 +05:30
2023-05-10 15:06:57 +05:30
def __init__(self, *args, **kwargs):
request = getattr(_thread_locals, "request")
2023-08-21 17:25:49 +05:30
instance = kwargs.get("instance")
2023-05-10 15:06:57 +05:30
if instance:
2023-08-21 17:25:49 +05:30
kwargs["initial"] = set_date_field_initial(instance)
super().__init__(*args, **kwargs)
2023-12-01 15:36:51 +05:30
reload_queryset(self.fields)
2023-08-21 17:25:49 +05:30
self.fields["asset_category_id"].widget.attrs.update({"id": str(uuid.uuid4())})
self.fields["asset_lot_number_id"].widget.attrs.update(
{"id": str(uuid.uuid4())}
)
self.fields["asset_status"].widget.attrs.update({"id": str(uuid.uuid4())})
if request.user.has_perm("asset.add_assetlot"):
batch_no_choices = [("", _("---Choose Batch No.---"))] + list(
self.fields["asset_lot_number_id"].queryset.values_list(
"id", "lot_number"
)
)
self.fields["asset_lot_number_id"].choices = batch_no_choices
if self.instance.pk is None:
self.fields["asset_lot_number_id"].choices += [
("create", _("Create new batch number"))
]
2023-08-21 17:25:49 +05:30
2023-05-10 15:06:57 +05:30
def clean(self):
instance = self.instance
prev_instance = Asset.objects.filter(id=instance.pk).first()
2023-05-10 15:06:57 +05:30
if instance.pk:
if (
self.cleaned_data.get("asset_status", None)
and self.cleaned_data.get("asset_status", None)
!= prev_instance.asset_status
):
2024-06-20 11:50:05 +05:30
if instance.assetassignment_set.filter(
return_status__isnull=True
2024-06-20 11:50:05 +05:30
).exists():
raise ValidationError(
{"asset_status": 'Asset in use you can"t change the status'}
)
2023-08-21 17:25:49 +05:30
if (
2023-12-01 15:36:51 +05:30
Asset.objects.filter(asset_tracking_id=self.data["asset_tracking_id"])
.exclude(id=instance.pk)
.exists()
2023-08-21 17:25:49 +05:30
):
raise ValidationError(
{"asset_tracking_id": "Already asset with this tracking id exists."}
)
class DocumentForm(forms.ModelForm):
2024-06-20 11:50:05 +05:30
"""
Form for uploading documents related to an asset.
Attributes:
- file: A FileField with a TextInput widget for file upload, allowing multiple files.
"""
file = forms.FileField(
widget=forms.TextInput(
attrs={
"name": "file",
"type": "File",
"class": "form-control",
"multiple": "True",
"accept": ".jpeg, .jpg, .png, .pdf",
}
)
)
class Meta:
2024-06-20 11:50:05 +05:30
"""
Metadata options for the DocumentForm.
Attributes:
- model: The model associated with this form (AssetDocuments).
- fields: Fields to include in the form ('file').
- exclude: Fields to exclude from the form ('is_active').
"""
model = AssetDocuments
fields = [
"file",
]
exclude = ["is_active"]
class AssetReportForm(ModelForm):
2024-06-20 11:50:05 +05:30
"""
Form for creating and updating asset reports.
Metadata:
- model: The model associated with this form (AssetReport).
- fields: Fields to include in the form ('title', 'asset_id').
- exclude: Fields to exclude from the form ('is_active').
Methods:
- __init__: Initializes the form, disabling the 'asset_id' field.
"""
class Meta:
2024-06-20 11:50:05 +05:30
"""
Metadata options for the AssetReportForm.
Attributes:
- model: The model associated with this form (AssetReport).
- fields: Fields to include in the form ('title', 'asset_id').
- exclude: Fields to exclude from the form ('is_active').
"""
model = AssetReport
fields = [
"title",
"asset_id",
]
exclude = ["is_active"]
def __init__(self, *args, **kwargs):
2024-06-20 11:50:05 +05:30
"""
Initialize the AssetReportForm, disabling the 'asset_id' field.
Args:
- *args: Variable length argument list.
- **kwargs: Arbitrary keyword arguments.
"""
super().__init__(*args, **kwargs)
self.fields["asset_id"].widget.attrs["disabled"] = "disabled"
2023-05-10 15:06:57 +05:30
class AssetCategoryForm(ModelForm):
2023-08-21 17:25:49 +05:30
"""
A form for creating and updating AssetCategory instances.
"""
2023-05-10 15:06:57 +05:30
class Meta:
2023-08-21 17:25:49 +05:30
"""
Specifies the model and fields to be used for the AssetForm.
Attributes:
model (class): The model class AssetCategory to be used for the form.
fields (str): A special value "__all__" to include all fields
of the model in the form.
widgets (dict): A dictionary containing widget configurations for
specific form fields.
"""
2023-05-10 15:06:57 +05:30
model = AssetCategory
2023-08-21 17:25:49 +05:30
fields = "__all__"
exclude = ["is_active"]
2023-05-10 15:06:57 +05:30
widgets = {
2023-08-21 17:25:49 +05:30
"asset_category_name": forms.TextInput(
attrs={"placeholder": _("Computers."), "class": "oh-input w-100"}
),
"asset_category_description": forms.Textarea(
attrs={
"type": "text",
"placeholder": _("A category for all types of laptops."),
"class": "oh-input oh-input--textarea oh-input--block",
"rows": 3,
"cols": 40,
}
),
2023-05-10 15:06:57 +05:30
}
2023-08-21 17:25:49 +05:30
2023-05-10 15:06:57 +05:30
class AssetRequestForm(ModelForm):
2023-08-21 17:25:49 +05:30
"""
A Django ModelForm for creating and updating AssetRequest instances.
"""
2023-05-10 15:06:57 +05:30
class Meta:
2023-08-21 17:25:49 +05:30
"""
Specifies the model and fields to be used for the AssetRequestForm.
Attributes:
model (class): The model class AssetRequest to be used for the form.
fields (str): A special value "__all__" to include all fields
of the model in the form.
widgets (dict): A dictionary containing widget configurations for
specific form fields.
"""
2023-05-10 15:06:57 +05:30
model = AssetRequest
2023-08-21 17:25:49 +05:30
fields = "__all__"
exclude = ["is_active"]
2023-05-10 15:06:57 +05:30
widgets = {
2023-08-21 17:25:49 +05:30
"requested_employee_id": forms.Select(
attrs={
"class": "oh-select oh-select-2 select2-hidden-accessible",
}
),
"asset_category_id": forms.Select(
attrs={
"class": "oh-select oh-select-2 select2-hidden-accessible",
}
),
"description": forms.Textarea(
attrs={
"type": "text",
"id": "objective_description",
"placeholder": _(
"Requesting a laptop for software development purposes."
),
"class": "oh-input oh-input--textarea oh-input--block",
"rows": 3,
"cols": 40,
}
),
2023-05-10 15:06:57 +05:30
}
2023-08-21 17:25:49 +05:30
def __init__(self, *args, **kwargs):
user = kwargs.pop("user", None)
super().__init__(*args, **kwargs)
2023-12-01 15:36:51 +05:30
reload_queryset(self.fields)
2023-08-21 17:25:49 +05:30
if user is not None and user.has_perm("asset.add_assetrequest"):
self.fields["requested_employee_id"].queryset = Employee.objects.all()
self.fields["requested_employee_id"].initial = Employee.objects.filter(
id=user.employee_get.id
).first()
2023-05-10 15:06:57 +05:30
else:
2023-08-21 17:25:49 +05:30
self.fields["requested_employee_id"].queryset = Employee.objects.filter(
employee_user_id=user
)
self.fields["requested_employee_id"].initial = user.employee_get
2023-05-10 15:06:57 +05:30
2023-08-21 17:25:49 +05:30
self.fields["asset_category_id"].widget.attrs.update({"id": str(uuid.uuid4())})
2023-05-10 15:06:57 +05:30
class AssetAllocationForm(ModelForm):
2023-08-21 17:25:49 +05:30
"""
A Django ModelForm for creating and updating AssetAssignment instances.
"""
2023-05-10 15:06:57 +05:30
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
2023-12-01 15:36:51 +05:30
reload_queryset(self.fields)
self.fields["asset_id"].queryset = Asset.objects.filter(
asset_status="Available"
)
2024-02-07 13:00:09 +05:30
self.fields["assign_images"] = MultipleFileField()
self.fields["assign_images"].required = True
2023-05-10 15:06:57 +05:30
class Meta:
2023-08-21 17:25:49 +05:30
"""
Specifies the model and fields to be used for the AssetAllocationForm.
Attributes:
model (class): The model class AssetAssignment to be used for the form.
fields (str): A special value "__all__" to include all fields
of the model in the form.
widgets (dict): A dictionary containing widget configurations for
specific form fields.
"""
2023-05-10 15:06:57 +05:30
model = AssetAssignment
2023-08-21 17:25:49 +05:30
fields = "__all__"
exclude = [
"return_date",
"return_condition",
"assigned_date",
"return_images",
"is_active",
]
2023-05-10 15:06:57 +05:30
widgets = {
2023-08-21 17:25:49 +05:30
"asset_id": forms.Select(attrs={"class": "oh-select oh-select-2 "}),
"assigned_to_employee_id": forms.Select(
attrs={"class": "oh-select oh-select-2 "}
),
"assigned_by_employee_id": forms.Select(
attrs={
"class": "oh-select oh-select-2 ",
},
),
2023-05-10 15:06:57 +05:30
}
# def clean(self):
# cleaned_data = super.clean()
2023-05-10 15:06:57 +05:30
class AssetReturnForm(ModelForm):
2023-08-21 17:25:49 +05:30
"""
A Django ModelForm for updating AssetAssignment instances during asset return.
"""
2023-05-10 15:06:57 +05:30
class Meta:
2023-08-21 17:25:49 +05:30
"""
Specifies the model and fields to be used for the AssetReturnForm.
Attributes:
model (class): The model class AssetAssignment to be used for the form.
fields (list): The fields to include in the form, referring to
related AssetAssignment fields.
widgets (dict): A dictionary containing widget configurations for
specific form fields.
"""
2023-05-10 15:06:57 +05:30
model = AssetAssignment
2024-02-07 13:00:09 +05:30
fields = ["return_date", "return_condition", "return_status", "return_images"]
2023-05-10 15:06:57 +05:30
widgets = {
2023-08-21 17:25:49 +05:30
"return_date": forms.DateInput(
attrs={"type": "date", "class": "oh-input w-100", "required": "true"}
),
"return_condition": forms.Textarea(
attrs={
"class": "oh-input oh-input--textarea oh-input--block",
"rows": 3,
"cols": 40,
"placeholder": _(
2023-09-05 12:41:56 +05:30
"on returns the laptop. However, it has suffered minor damage."
2023-08-21 17:25:49 +05:30
),
}
),
"return_status": forms.Select(
attrs={"class": "oh-select oh-select-2", "required": "true"},
),
2023-05-10 15:06:57 +05:30
}
def __init__(self, *args, **kwargs):
[IMP] Remove inter module dependency (#274) This commit introduces significant changes to the architecture of the Horilla HRMS system by decoupling interdependent modules. The following modifications were made: 1. **Module Independence**: Each module has been refactored to eliminate reliance on other modules, promoting a more modular and maintainable codebase. 2. **Refactored Imports and Dependencies**: Adjusted import statements and dependency injections to support independent module operation. 3. **Compatibility and Functionality**: Ensured that all modules are compatible with existing systems and maintain their intended functionality both independently and when integrated with other modules. These changes enhance the modularity, maintainability, and scalability of the Horilla HRMS, allowing developers to work on individual modules without affecting the entire system. Future development and deployment will be more efficient and less prone to issues arising from tightly coupled code. **NOTE** For existing Horilla users, if you face any issues during the migrations, please run the following command and try again the migrations. - `python3 manage.py makemigrations` - `python3 manage.py migrate base` - `python3 manage.py migrate` * [IMP] ASSET: Asset module dependency removal from other Horilla apps * [IMP] ATTENDANCE: Attendance module dependency removal from other Horilla apps * [IMP] BASE: Base module dependency removal from other Horilla apps * [IMP] EMPLOYEE: Employee module dependency removal from other Horilla apps * [IMP] HELPDESK: Helpdesk module dependency removal from other Horilla apps * [IMP] HORILLA AUDIT: Horilla Audit module dependency removal from other Horilla apps * [IMP] HORILLA CRUMBS: Horilla Crumbs module dependency removal from other Horilla apps * [IMP] HORILLA AUTOMATIONS: Horilla Automations module dependency removal from other Horilla apps * [IMP] HORILLA VIEWS: Horilla Views module dependency removal from other Horilla apps * [IMP] LEAVE: Leave module dependency removal from other Horilla apps * [IMP] OFFBOARDING: Offboarding module dependency removal from other Horilla apps * [IMP] ONBOARDING: Onboarding module dependency removal from other Horilla apps * [IMP] PMS: PMS module dependency removal from other Horilla apps * [IMP] PAYROLL: Payroll module dependency removal from other Horilla apps * [IMP] RECRUITMENT: Recruitment module dependency removal from other Horilla apps * [IMP] HORILLA: Dependency removal updates * [IMP] TEMPLATES: Dependency removal updates * [IMP] STATIC: Dependency removal updates * [IMP] HORILLA DOCUMENTS: Horilla Documents module dependency removal from other Horilla apps * [ADD] HORILLA: methods.py * [UPDT] HORILLA: Settings.py * [FIX] EMPLOYEE: About tab issue * Update horilla_settings.py * Remove dummy db init password
2024-08-05 14:22:44 +05:30
"""
Initializes the AssetReturnForm with initial values and custom field settings.
"""
super().__init__(*args, **kwargs)
self.fields["return_date"].initial = date.today()
2024-02-07 13:00:09 +05:30
self.fields["return_images"] = MultipleFileField(label="Images")
self.fields["return_images"].required = True
2023-12-01 15:36:51 +05:30
2023-09-05 12:41:56 +05:30
def clean_return_date(self):
2024-06-20 11:50:05 +05:30
"""
Validates the 'return_date' field.
Ensures that the return date is not in the future. If the return date is in the future,
a ValidationError is raised.
Returns:
- The cleaned return date.
Raises:
- forms.ValidationError: If the return date is in the future.
"""
2023-09-05 12:41:56 +05:30
return_date = self.cleaned_data.get("return_date")
if return_date and return_date > date.today():
raise forms.ValidationError(_("Return date cannot be in the future."))
return return_date
2023-05-10 15:06:57 +05:30
class AssetBatchForm(ModelForm):
2023-08-21 17:25:49 +05:30
"""
A Django ModelForm for creating or updating AssetLot instances.
"""
2023-12-01 15:36:51 +05:30
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
reload_queryset(self.fields)
2023-05-10 15:06:57 +05:30
class Meta:
2023-08-21 17:25:49 +05:30
"""
Specifies the model and fields to be used for the AssetBatchForm.
Attributes:
model (class): The model class AssetLot to be used for the form.
fields (str): A special value "__all__" to include all fields
of the model in the form.
widgets (dict): A dictionary containing widget configurations for
specific form fields.
"""
2023-05-10 15:06:57 +05:30
model = AssetLot
2023-08-21 17:25:49 +05:30
fields = "__all__"
2023-05-10 15:06:57 +05:30
widgets = {
2023-08-21 17:25:49 +05:30
"lot_number": forms.TextInput(
attrs={"placeholder": "A12345.", "class": "oh-input w-100"}
),
"lot_description": forms.Textarea(
attrs={
"type": "text",
"placeholder": _(
2023-09-09 14:09:55 +05:30
"A batch of 50 laptops, consisting of Lenovo ThinkPad T480s\
and Dell XPS 13."
2023-08-21 17:25:49 +05:30
),
"class": "oh-input oh-input--textarea oh-input--block",
"rows": 3,
"cols": 40,
}
),
}