521 lines
29 KiB
HTML
521 lines
29 KiB
HTML
{% extends 'base.html' %}
|
|
{% load static %}
|
|
|
|
{% block title %}
|
|
{% if object %}Edit Location{% else %}Add New Location{% endif %} - Inventory Management
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="content">
|
|
<div class="container-fluid">
|
|
<!-- Page Header -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="page-header">
|
|
<div class="page-title">
|
|
<h4>{% if object %}Edit Location{% else %}Add New Location{% endif %}</h4>
|
|
<h6>{% if object %}Update location information{% else %}Create a new storage location{% endif %}</h6>
|
|
</div>
|
|
<div class="page-btn">
|
|
<a href="{% url 'inventory:location_list' %}" class="btn btn-secondary">
|
|
<i class="fas fa-arrow-left me-1"></i>Back to Locations
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<form method="post" id="locationForm">
|
|
{% csrf_token %}
|
|
|
|
<!-- Basic Information -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Basic Information</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-lg-4 col-sm-6 col-12">
|
|
<div class="form-group">
|
|
<label>Location Code <span class="text-danger">*</span></label>
|
|
<input type="text" name="location_code" class="form-control"
|
|
value="{{ form.location_code.value|default:'' }}"
|
|
placeholder="Enter location code" required>
|
|
{% if form.location_code.errors %}
|
|
<div class="text-danger">{{ form.location_code.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-4 col-sm-6 col-12">
|
|
<div class="form-group">
|
|
<label>Location Name <span class="text-danger">*</span></label>
|
|
<input type="text" name="name" class="form-control"
|
|
value="{{ form.name.value|default:'' }}"
|
|
placeholder="Enter location name" required>
|
|
{% if form.name.errors %}
|
|
<div class="text-danger">{{ form.name.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-4 col-sm-6 col-12">
|
|
<div class="form-group">
|
|
<label>Location Type <span class="text-danger">*</span></label>
|
|
<select name="location_type" class="select" required>
|
|
<option value="">Choose Location Type</option>
|
|
<option value="WAREHOUSE" {% if form.location_type.value == 'WAREHOUSE' %}selected{% endif %}>Warehouse</option>
|
|
<option value="STOREROOM" {% if form.location_type.value == 'STOREROOM' %}selected{% endif %}>Storeroom</option>
|
|
<option value="PHARMACY" {% if form.location_type.value == 'PHARMACY' %}selected{% endif %}>Pharmacy</option>
|
|
<option value="NURSING_UNIT" {% if form.location_type.value == 'NURSING_UNIT' %}selected{% endif %}>Nursing Unit</option>
|
|
<option value="OR_STORAGE" {% if form.location_type.value == 'OR_STORAGE' %}selected{% endif %}>OR Storage</option>
|
|
<option value="LAB_STORAGE" {% if form.location_type.value == 'LAB_STORAGE' %}selected{% endif %}>Lab Storage</option>
|
|
<option value="RADIOLOGY" {% if form.location_type.value == 'RADIOLOGY' %}selected{% endif %}>Radiology Storage</option>
|
|
<option value="CENTRAL_SUPPLY" {% if form.location_type.value == 'CENTRAL_SUPPLY' %}selected{% endif %}>Central Supply</option>
|
|
<option value="REFRIGERATOR" {% if form.location_type.value == 'REFRIGERATOR' %}selected{% endif %}>Refrigerator</option>
|
|
<option value="FREEZER" {% if form.location_type.value == 'FREEZER' %}selected{% endif %}>Freezer</option>
|
|
<option value="CONTROLLED" {% if form.location_type.value == 'CONTROLLED' %}selected{% endif %}>Controlled Substance</option>
|
|
<option value="QUARANTINE" {% if form.location_type.value == 'QUARANTINE' %}selected{% endif %}>Quarantine</option>
|
|
<option value="RECEIVING" {% if form.location_type.value == 'RECEIVING' %}selected{% endif %}>Receiving</option>
|
|
<option value="SHIPPING" {% if form.location_type.value == 'SHIPPING' %}selected{% endif %}>Shipping</option>
|
|
<option value="OTHER" {% if form.location_type.value == 'OTHER' %}selected{% endif %}>Other</option>
|
|
</select>
|
|
{% if form.location_type.errors %}
|
|
<div class="text-danger">{{ form.location_type.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-lg-6 col-12">
|
|
<div class="form-group">
|
|
<label>Parent Location</label>
|
|
<select name="parent_location" class="select">
|
|
<option value="">No Parent Location</option>
|
|
{% for location in parent_locations %}
|
|
<option value="{{ location.id }}"
|
|
{% if form.parent_location.value == location.id %}selected{% endif %}>
|
|
{{ location.location_code }} - {{ location.name }}
|
|
</option>
|
|
{% endfor %}
|
|
</select>
|
|
{% if form.parent_location.errors %}
|
|
<div class="text-danger">{{ form.parent_location.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-6 col-12">
|
|
<div class="form-group">
|
|
<label>Location Manager</label>
|
|
<select name="location_manager" class="select">
|
|
<option value="">Select Manager</option>
|
|
{% for user in managers %}
|
|
<option value="{{ user.id }}"
|
|
{% if form.location_manager.value == user.id %}selected{% endif %}>
|
|
{{ user.get_full_name }}
|
|
</option>
|
|
{% endfor %}
|
|
</select>
|
|
{% if form.location_manager.errors %}
|
|
<div class="text-danger">{{ form.location_manager.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="form-group">
|
|
<label>Description</label>
|
|
<textarea name="description" class="form-control" rows="3"
|
|
placeholder="Enter location description">{{ form.description.value|default:'' }}</textarea>
|
|
{% if form.description.errors %}
|
|
<div class="text-danger">{{ form.description.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Physical Location -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Physical Location</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-lg-3 col-sm-6 col-12">
|
|
<div class="form-group">
|
|
<label>Building</label>
|
|
<input type="text" name="building" class="form-control"
|
|
value="{{ form.building.value|default:'' }}"
|
|
placeholder="Building name/number">
|
|
{% if form.building.errors %}
|
|
<div class="text-danger">{{ form.building.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-3 col-sm-6 col-12">
|
|
<div class="form-group">
|
|
<label>Floor</label>
|
|
<input type="text" name="floor" class="form-control"
|
|
value="{{ form.floor.value|default:'' }}"
|
|
placeholder="Floor">
|
|
{% if form.floor.errors %}
|
|
<div class="text-danger">{{ form.floor.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-3 col-sm-6 col-12">
|
|
<div class="form-group">
|
|
<label>Room</label>
|
|
<input type="text" name="room" class="form-control"
|
|
value="{{ form.room.value|default:'' }}"
|
|
placeholder="Room number">
|
|
{% if form.room.errors %}
|
|
<div class="text-danger">{{ form.room.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-3 col-sm-6 col-12">
|
|
<div class="form-group">
|
|
<label>Zone</label>
|
|
<input type="text" name="zone" class="form-control"
|
|
value="{{ form.zone.value|default:'' }}"
|
|
placeholder="Zone or area">
|
|
{% if form.zone.errors %}
|
|
<div class="text-danger">{{ form.zone.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-lg-4 col-sm-6 col-12">
|
|
<div class="form-group">
|
|
<label>Aisle</label>
|
|
<input type="text" name="aisle" class="form-control"
|
|
value="{{ form.aisle.value|default:'' }}"
|
|
placeholder="Aisle">
|
|
{% if form.aisle.errors %}
|
|
<div class="text-danger">{{ form.aisle.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-4 col-sm-6 col-12">
|
|
<div class="form-group">
|
|
<label>Shelf</label>
|
|
<input type="text" name="shelf" class="form-control"
|
|
value="{{ form.shelf.value|default:'' }}"
|
|
placeholder="Shelf">
|
|
{% if form.shelf.errors %}
|
|
<div class="text-danger">{{ form.shelf.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-4 col-sm-6 col-12">
|
|
<div class="form-group">
|
|
<label>Bin</label>
|
|
<input type="text" name="bin" class="form-control"
|
|
value="{{ form.bin.value|default:'' }}"
|
|
placeholder="Bin location">
|
|
{% if form.bin.errors %}
|
|
<div class="text-danger">{{ form.bin.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Capacity and Environmental Controls -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Capacity & Environmental Controls</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-lg-6 col-sm-6 col-12">
|
|
<div class="form-group">
|
|
<label>Capacity (Cubic Feet)</label>
|
|
<input type="number" name="capacity_cubic_feet" class="form-control"
|
|
value="{{ form.capacity_cubic_feet.value|default:'' }}"
|
|
placeholder="0.00" step="0.01">
|
|
{% if form.capacity_cubic_feet.errors %}
|
|
<div class="text-danger">{{ form.capacity_cubic_feet.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-6 col-sm-6 col-12">
|
|
<div class="form-group">
|
|
<label>Maximum Weight (Pounds)</label>
|
|
<input type="number" name="max_weight_pounds" class="form-control"
|
|
value="{{ form.max_weight_pounds.value|default:'' }}"
|
|
placeholder="0.00" step="0.01">
|
|
{% if form.max_weight_pounds.errors %}
|
|
<div class="text-danger">{{ form.max_weight_pounds.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Temperature Control -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="form-group">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" name="temperature_controlled"
|
|
id="temperatureControlled"
|
|
{% if form.temperature_controlled.value %}checked{% endif %}>
|
|
<label class="form-check-label" for="temperatureControlled">
|
|
Temperature Controlled
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row" id="temperatureControls" style="{% if not form.temperature_controlled.value %}display: none;{% endif %}">
|
|
<div class="col-lg-6 col-sm-6 col-12">
|
|
<div class="form-group">
|
|
<label>Minimum Temperature (°C)</label>
|
|
<input type="number" name="temperature_min" class="form-control"
|
|
value="{{ form.temperature_min.value|default:'' }}"
|
|
placeholder="0.0" step="0.1">
|
|
{% if form.temperature_min.errors %}
|
|
<div class="text-danger">{{ form.temperature_min.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-6 col-sm-6 col-12">
|
|
<div class="form-group">
|
|
<label>Maximum Temperature (°C)</label>
|
|
<input type="number" name="temperature_max" class="form-control"
|
|
value="{{ form.temperature_max.value|default:'' }}"
|
|
placeholder="0.0" step="0.1">
|
|
{% if form.temperature_max.errors %}
|
|
<div class="text-danger">{{ form.temperature_max.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Humidity Control -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="form-group">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" name="humidity_controlled"
|
|
id="humidityControlled"
|
|
{% if form.humidity_controlled.value %}checked{% endif %}>
|
|
<label class="form-check-label" for="humidityControlled">
|
|
Humidity Controlled
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row" id="humidityControls" style="{% if not form.humidity_controlled.value %}display: none;{% endif %}">
|
|
<div class="col-lg-6 col-sm-6 col-12">
|
|
<div class="form-group">
|
|
<label>Minimum Humidity (%)</label>
|
|
<input type="number" name="humidity_min" class="form-control"
|
|
value="{{ form.humidity_min.value|default:'' }}"
|
|
placeholder="0" min="0" max="100">
|
|
{% if form.humidity_min.errors %}
|
|
<div class="text-danger">{{ form.humidity_min.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-6 col-sm-6 col-12">
|
|
<div class="form-group">
|
|
<label>Maximum Humidity (%)</label>
|
|
<input type="number" name="humidity_max" class="form-control"
|
|
value="{{ form.humidity_max.value|default:'' }}"
|
|
placeholder="0" min="0" max="100">
|
|
{% if form.humidity_max.errors %}
|
|
<div class="text-danger">{{ form.humidity_max.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Security and Access -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Security & Access Control</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-lg-6 col-sm-6 col-12">
|
|
<div class="form-group">
|
|
<label>Access Control Method</label>
|
|
<select name="access_control" class="select">
|
|
<option value="OPEN" {% if form.access_control.value == 'OPEN' %}selected{% endif %}>Open Access</option>
|
|
<option value="BADGE" {% if form.access_control.value == 'BADGE' %}selected{% endif %}>Badge Access</option>
|
|
<option value="KEY" {% if form.access_control.value == 'KEY' %}selected{% endif %}>Key Access</option>
|
|
<option value="BIOMETRIC" {% if form.access_control.value == 'BIOMETRIC' %}selected{% endif %}>Biometric Access</option>
|
|
<option value="DUAL_CONTROL" {% if form.access_control.value == 'DUAL_CONTROL' %}selected{% endif %}>Dual Control</option>
|
|
</select>
|
|
{% if form.access_control.errors %}
|
|
<div class="text-danger">{{ form.access_control.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-6 col-sm-6 col-12">
|
|
<div class="form-group">
|
|
<div class="form-check mt-4">
|
|
<input class="form-check-input" type="checkbox" name="secure_location"
|
|
id="secureLocation"
|
|
{% if form.secure_location.value %}checked{% endif %}>
|
|
<label class="form-check-label" for="secureLocation">
|
|
Secure/Restricted Access Location
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Status and Notes -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Status & Notes</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-lg-6 col-sm-6 col-12">
|
|
<div class="form-group">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" name="is_active"
|
|
id="isActive"
|
|
{% if form.is_active.value %}checked{% endif %}>
|
|
<label class="form-check-label" for="isActive">
|
|
Location is Active
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="form-group">
|
|
<label>Notes</label>
|
|
<textarea name="notes" class="form-control" rows="4"
|
|
placeholder="Additional notes about this location">{{ form.notes.value|default:'' }}</textarea>
|
|
{% if form.notes.errors %}
|
|
<div class="text-danger">{{ form.notes.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Form Actions -->
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="form-group text-end">
|
|
<a href="{% url 'inventory:location_list' %}" class="btn btn-cancel me-2">Cancel</a>
|
|
<button type="submit" class="btn btn-submit">
|
|
{% if object %}Update Location{% else %}Create Location{% endif %}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Temperature control toggle
|
|
const temperatureControlled = document.getElementById('temperatureControlled');
|
|
const temperatureControls = document.getElementById('temperatureControls');
|
|
|
|
temperatureControlled.addEventListener('change', function() {
|
|
if (this.checked) {
|
|
temperatureControls.style.display = 'block';
|
|
} else {
|
|
temperatureControls.style.display = 'none';
|
|
// Clear temperature values when disabled
|
|
document.querySelector('input[name="temperature_min"]').value = '';
|
|
document.querySelector('input[name="temperature_max"]').value = '';
|
|
}
|
|
});
|
|
|
|
// Humidity control toggle
|
|
const humidityControlled = document.getElementById('humidityControlled');
|
|
const humidityControls = document.getElementById('humidityControls');
|
|
|
|
humidityControlled.addEventListener('change', function() {
|
|
if (this.checked) {
|
|
humidityControls.style.display = 'block';
|
|
} else {
|
|
humidityControls.style.display = 'none';
|
|
// Clear humidity values when disabled
|
|
document.querySelector('input[name="humidity_min"]').value = '';
|
|
document.querySelector('input[name="humidity_max"]').value = '';
|
|
}
|
|
});
|
|
|
|
// Form validation
|
|
const form = document.getElementById('locationForm');
|
|
form.addEventListener('submit', function(e) {
|
|
let isValid = true;
|
|
const requiredFields = ['location_code', 'name', 'location_type'];
|
|
|
|
requiredFields.forEach(fieldName => {
|
|
const field = document.querySelector(`[name="${fieldName}"]`);
|
|
if (!field.value.trim()) {
|
|
isValid = false;
|
|
field.classList.add('is-invalid');
|
|
} else {
|
|
field.classList.remove('is-invalid');
|
|
}
|
|
});
|
|
|
|
// Validate temperature range
|
|
const tempMin = document.querySelector('input[name="temperature_min"]');
|
|
const tempMax = document.querySelector('input[name="temperature_max"]');
|
|
if (temperatureControlled.checked && tempMin.value && tempMax.value) {
|
|
if (parseFloat(tempMin.value) >= parseFloat(tempMax.value)) {
|
|
isValid = false;
|
|
alert('Minimum temperature must be less than maximum temperature.');
|
|
}
|
|
}
|
|
|
|
// Validate humidity range
|
|
const humidityMin = document.querySelector('input[name="humidity_min"]');
|
|
const humidityMax = document.querySelector('input[name="humidity_max"]');
|
|
if (humidityControlled.checked && humidityMin.value && humidityMax.value) {
|
|
if (parseInt(humidityMin.value) >= parseInt(humidityMax.value)) {
|
|
isValid = false;
|
|
alert('Minimum humidity must be less than maximum humidity.');
|
|
}
|
|
}
|
|
|
|
if (!isValid) {
|
|
e.preventDefault();
|
|
}
|
|
});
|
|
|
|
// Auto-generate location code if needed
|
|
const locationName = document.querySelector('input[name="name"]');
|
|
const locationCode = document.querySelector('input[name="location_code"]');
|
|
|
|
locationName.addEventListener('blur', function() {
|
|
if (!locationCode.value && this.value) {
|
|
// Generate code from name (first 3 letters + random number)
|
|
const code = this.value.substring(0, 3).toUpperCase() + Math.floor(Math.random() * 1000);
|
|
locationCode.value = code;
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
{% endblock %}
|
|
|