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.
|
|
|
|
|
"""
|
2024-03-06 15:00:46 +05:30
|
|
|
|
2023-09-05 12:41:56 +05:30
|
|
|
from datetime import date
|
2023-05-10 15:06:57 +05:30
|
|
|
import uuid
|
2023-08-21 17:25:49 +05:30
|
|
|
from django import forms
|
2023-12-01 15:36:51 +05:30
|
|
|
from base.forms import ModelForm
|
2023-08-21 17:25:49 +05:30
|
|
|
from django.core.exceptions import ValidationError
|
2023-05-10 15:06:57 +05:30
|
|
|
from django.utils.translation import gettext_lazy as _
|
2024-02-07 13:00:09 +05:30
|
|
|
from employee.forms import MultipleFileField
|
2023-08-21 17:25:49 +05:30
|
|
|
from employee.models import Employee
|
2024-03-06 15:00:46 +05:30
|
|
|
from asset.models import (
|
|
|
|
|
Asset,
|
|
|
|
|
AssetDocuments,
|
|
|
|
|
AssetReport,
|
|
|
|
|
AssetRequest,
|
|
|
|
|
AssetAssignment,
|
|
|
|
|
AssetCategory,
|
|
|
|
|
AssetLot,
|
|
|
|
|
)
|
2023-12-01 15:36:51 +05:30
|
|
|
from base.methods import reload_queryset
|
2024-01-09 10:29:09 +05:30
|
|
|
from django.template.loader import render_to_string
|
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__"
|
2024-03-25 10:08:53 +00:00
|
|
|
exclude = ["is_active"]
|
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"}
|
|
|
|
|
),
|
2024-02-05 11:45:01 +05:30
|
|
|
"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",
|
|
|
|
|
}
|
|
|
|
|
),
|
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):
|
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)
|
2023-05-10 15:06:57 +05:30
|
|
|
super(AssetForm, self).__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())})
|
|
|
|
|
|
2023-05-10 15:06:57 +05:30
|
|
|
def clean(self):
|
|
|
|
|
instance = self.instance
|
2024-03-06 15:00:46 +05:30
|
|
|
prev_instance = Asset.objects.filter(id=instance.pk).first()
|
2023-05-10 15:06:57 +05:30
|
|
|
if instance.pk:
|
2024-03-10 19:37:46 +05:30
|
|
|
if (
|
|
|
|
|
self.cleaned_data.get("asset_status", None)
|
|
|
|
|
and self.cleaned_data.get("asset_status", None)
|
|
|
|
|
!= prev_instance.asset_status
|
|
|
|
|
):
|
|
|
|
|
if asset_in_use := instance.assetassignment_set.filter(
|
|
|
|
|
return_status__isnull=True
|
|
|
|
|
):
|
2024-03-06 15:00:46 +05:30
|
|
|
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."}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2024-01-09 10:29:09 +05:30
|
|
|
class DocumentForm(forms.ModelForm):
|
2024-03-06 15:00:46 +05:30
|
|
|
file = forms.FileField(
|
|
|
|
|
widget=forms.TextInput(
|
|
|
|
|
attrs={
|
|
|
|
|
"name": "file",
|
|
|
|
|
"type": "File",
|
|
|
|
|
"class": "form-control",
|
|
|
|
|
"multiple": "True",
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
|
2024-01-09 10:29:09 +05:30
|
|
|
class Meta:
|
|
|
|
|
model = AssetDocuments
|
2024-03-06 15:00:46 +05:30
|
|
|
fields = [
|
|
|
|
|
"file",
|
|
|
|
|
]
|
2024-01-09 10:29:09 +05:30
|
|
|
|
|
|
|
|
|
|
|
|
|
class AssetReportForm(ModelForm):
|
|
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
|
model = AssetReport
|
2024-03-06 15:00:46 +05:30
|
|
|
fields = [
|
|
|
|
|
"title",
|
|
|
|
|
"asset_id",
|
|
|
|
|
]
|
2024-03-25 10:08:53 +00:00
|
|
|
exclude = ["is_active"]
|
2024-01-09 10:29:09 +05:30
|
|
|
|
|
|
|
|
# def __init__(self, *args, **kwargs):
|
|
|
|
|
# super(AssetReportForm, self).__init__(*args, **kwargs)
|
|
|
|
|
# self.fields['documents'].queryset = AssetDocuments.objects.all()
|
|
|
|
|
|
|
|
|
|
# def as_p(self, *args, **kwargs):
|
|
|
|
|
# """
|
|
|
|
|
# Render the form fields as HTML table rows with Bootstrap styling.
|
|
|
|
|
# """
|
|
|
|
|
# context = {"form": self}
|
|
|
|
|
# table_html = render_to_string("attendance_form.html", context)
|
|
|
|
|
# return table_html
|
|
|
|
|
|
|
|
|
|
|
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__"
|
2024-03-25 10:08:53 +00:00
|
|
|
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__"
|
2024-03-25 10:08:53 +00:00
|
|
|
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(AssetRequestForm, self).__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
|
|
|
|
2023-09-05 15:18:10 +05:30
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
super(AssetAllocationForm, self).__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-03-06 15:00:46 +05:30
|
|
|
|
2024-02-07 13:00:09 +05:30
|
|
|
self.fields["assign_images"] = MultipleFileField()
|
|
|
|
|
self.fields["assign_images"].required = True
|
2023-09-05 15:18:10 +05:30
|
|
|
|
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__"
|
2024-03-25 10:08:53 +00:00
|
|
|
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
|
|
|
}
|
2024-03-25 10:08:53 +00:00
|
|
|
|
2024-03-11 11:23:44 +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
|
|
|
}
|
2024-03-06 15:00:46 +05:30
|
|
|
|
2024-01-31 11:37:09 +05:30
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
super(AssetReturnForm, self).__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):
|
|
|
|
|
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,
|
|
|
|
|
}
|
|
|
|
|
),
|
|
|
|
|
}
|