Marwan Alwali 1f0a6bff5f update
2025-08-31 12:21:16 +03:00

714 lines
32 KiB
HTML

{% extends "base.html" %}
{% load static %}
{% block title %}{% if object %}Edit {{ object.item_name }}{% else %}Add New Item{% endif %} - Inventory{% endblock %}
{% block css %}
<link href="{% static 'plugins/select2/dist/css/select2.min.css' %}" rel="stylesheet" />
<link href="{% static 'plugins/bootstrap-datepicker/dist/css/bootstrap-datepicker.min.css' %}" rel="stylesheet" />
{#<link href="{% static 'plugins/jquery-file-upload/css/jquery.fileupload.css' %}" rel="stylesheet" />#}
{% endblock %}
{% block content %}
<!-- BEGIN breadcrumb -->
<ol class="breadcrumb float-xl-end">
<li class="breadcrumb-item"><a href="{% url 'core:dashboard' %}">Dashboard</a></li>
<li class="breadcrumb-item"><a href="{% url 'inventory:dashboard' %}">Inventory</a></li>
<li class="breadcrumb-item"><a href="{% url 'inventory:item_list' %}">Items</a></li>
<li class="breadcrumb-item active">{% if object %}Edit Item{% else %}Add Item{% endif %}</li>
</ol>
<!-- END breadcrumb -->
<!-- BEGIN page-header -->
<h1 class="page-header">
{% if object %}Edit Inventory Item{% else %}Add New Inventory Item{% endif %}
<small>{% if object %}{{ object.item_code }}{% else %}Medical Supplies & Equipment{% endif %}</small>
</h1>
<!-- END page-header -->
<form method="post" enctype="multipart/form-data" id="item-form">
{% csrf_token %}
<div class="row">
<div class="col-xl-8">
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Basic Information</h4>
<div class="panel-heading-btn">
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
</div>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Item Code <span class="text-danger">*</span></label>
<div class="input-group">
{{ form.item_code }}
<button class="btn btn-outline-secondary" type="button" onclick="generateItemCode()">
<i class="fa fa-magic"></i> Generate
</button>
</div>
{% if form.item_code.help_text %}
<div class="form-text">{{ form.item_code.help_text }}</div>
{% endif %}
{% if form.item_code.errors %}
<div class="text-danger">{{ form.item_code.errors.0 }}</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Item Name <span class="text-danger">*</span></label>
{{ form.item_name }}
{% if form.item_name.errors %}
<div class="text-danger">{{ form.item_name.errors.0 }}</div>
{% endif %}
</div>
</div>
</div>
<div class="mb-3">
<label class="form-label">Description</label>
{{ form.description }}
{% if form.description.help_text %}
<div class="form-text">{{ form.description.help_text }}</div>
{% endif %}
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Category <span class="text-danger">*</span></label>
{{ form.category }}
{% if form.category.errors %}
<div class="text-danger">{{ form.category.errors.0 }}</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Subcategory</label>
{{ form.subcategory }}
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Item Type <span class="text-danger">*</span></label>
{{ form.item_type }}
{% if form.item_type.errors %}
<div class="text-danger">{{ form.item_type.errors.0 }}</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Unit of Measure</label>
{{ form.unit_of_measure }}
</div>
</div>
</div>
</div>
</div>
<!-- END panel -->
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Manufacturer & Identification</h4>
<div class="panel-heading-btn">
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
</div>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Manufacturer</label>
{{ form.manufacturer }}
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Model Number</label>
{{ form.model_number }}
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Part Number</label>
{{ form.part_number }}
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">UPC Code</label>
<div class="input-group">
{{ form.upc_code }}
<button class="btn btn-outline-secondary" type="button" onclick="scanBarcode()">
<i class="fa fa-barcode"></i> Scan
</button>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">NDC Code</label>
{{ form.ndc_code }}
<div class="form-text">For medications only</div>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">GTIN Code</label>
{{ form.gtin_code }}
</div>
</div>
</div>
</div>
</div>
<!-- END panel -->
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Packaging & Pricing</h4>
<div class="panel-heading-btn">
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
</div>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Package Size</label>
<div class="input-group">
{{ form.package_size }}
<span class="input-group-text" id="package-unit">units</span>
</div>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Package Type</label>
{{ form.package_type }}
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Unit Cost</label>
<div class="input-group">
<span class="input-group-text">$</span>
{{ form.unit_cost }}
</div>
{% if form.unit_cost.errors %}
<div class="text-danger">{{ form.unit_cost.errors.0 }}</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">List Price</label>
<div class="input-group">
<span class="input-group-text">$</span>
{{ form.list_price }}
</div>
</div>
</div>
</div>
</div>
</div>
<!-- END panel -->
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Storage Requirements</h4>
<div class="panel-heading-btn">
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
</div>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Min Temperature (°C)</label>
{{ form.storage_temperature_min }}
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Max Temperature (°C)</label>
{{ form.storage_temperature_max }}
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Min Humidity (%)</label>
{{ form.storage_humidity_min }}
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Max Humidity (%)</label>
{{ form.storage_humidity_max }}
</div>
</div>
</div>
<div class="mb-3">
<label class="form-label">Special Storage Requirements</label>
{{ form.storage_requirements }}
<div class="form-text">Describe any special storage conditions (e.g., "Keep refrigerated", "Store in dark place")</div>
</div>
</div>
</div>
<!-- END panel -->
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Clinical Information</h4>
<div class="panel-heading-btn">
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
</div>
</div>
<div class="panel-body">
<div class="mb-3">
<label class="form-label">Clinical Use</label>
{{ form.clinical_use }}
<div class="form-text">Describe the clinical applications and indications for use</div>
</div>
<div class="mb-3">
<label class="form-label">Contraindications</label>
{{ form.contraindications }}
<div class="form-text">List any contraindications, warnings, or precautions</div>
</div>
</div>
</div>
<!-- END panel -->
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Additional Notes</h4>
<div class="panel-heading-btn">
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
</div>
</div>
<div class="panel-body">
<div class="mb-3">
<label class="form-label">Notes</label>
{{ form.notes }}
<div class="form-text">Any additional information about this item</div>
</div>
</div>
</div>
<!-- END panel -->
</div>
<div class="col-xl-4">
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Item Settings</h4>
<div class="panel-heading-btn">
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
</div>
</div>
<div class="panel-body">
<div class="mb-3">
<div class="form-check">
{{ form.is_active }}
<label class="form-check-label" for="{{ form.is_active.id_for_label }}">
Active Item
</label>
</div>
<div class="form-text">Inactive items are hidden from normal operations</div>
</div>
<div class="mb-3">
<div class="form-check">
{{ form.is_tracked }}
<label class="form-check-label" for="{{ form.is_tracked.id_for_label }}">
Track Inventory Levels
</label>
</div>
<div class="form-text">Enable inventory level tracking for this item</div>
</div>
<div class="mb-3">
<div class="form-check">
{{ form.is_serialized }}
<label class="form-check-label" for="{{ form.is_serialized.id_for_label }}">
Track by Serial Number
</label>
</div>
<div class="form-text">Track individual items by serial number</div>
</div>
<div class="mb-3">
<div class="form-check">
{{ form.is_lot_tracked }}
<label class="form-check-label" for="{{ form.is_lot_tracked.id_for_label }}">
Track by Lot Number
</label>
</div>
<div class="form-text">Track items by lot/batch number</div>
</div>
<div class="mb-3">
<div class="form-check">
{{ form.has_expiration }}
<label class="form-check-label" for="{{ form.has_expiration.id_for_label }}">
Has Expiration Date
</label>
</div>
<div class="form-text">Item has an expiration date</div>
</div>
<div class="mb-3" id="shelf-life-field" style="display: none;">
<label class="form-label">Shelf Life (Days)</label>
{{ form.shelf_life_days }}
<div class="form-text">Default shelf life in days</div>
</div>
</div>
</div>
<!-- END panel -->
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Regulatory Information</h4>
<div class="panel-heading-btn">
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
</div>
</div>
<div class="panel-body">
<div class="mb-3">
<div class="form-check">
{{ form.fda_approved }}
<label class="form-check-label" for="{{ form.fda_approved.id_for_label }}">
FDA Approved
</label>
</div>
</div>
<div class="mb-3">
<div class="form-check">
{{ form.controlled_substance }}
<label class="form-check-label" for="{{ form.controlled_substance.id_for_label }}">
Controlled Substance
</label>
</div>
</div>
<div class="mb-3" id="dea-schedule-field" style="display: none;">
<label class="form-label">DEA Schedule</label>
{{ form.dea_schedule }}
<div class="form-text">Required for controlled substances</div>
</div>
</div>
</div>
<!-- END panel -->
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Inventory Management</h4>
<div class="panel-heading-btn">
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
</div>
</div>
<div class="panel-body">
<div class="mb-3">
<label class="form-label">Reorder Point</label>
{{ form.reorder_point }}
<div class="form-text">Minimum stock level before reordering</div>
{% if form.reorder_point.errors %}
<div class="text-danger">{{ form.reorder_point.errors.0 }}</div>
{% endif %}
</div>
<div class="mb-3">
<label class="form-label">Reorder Quantity</label>
{{ form.reorder_quantity }}
<div class="form-text">Standard quantity to order</div>
{% if form.reorder_quantity.errors %}
<div class="text-danger">{{ form.reorder_quantity.errors.0 }}</div>
{% endif %}
</div>
<div class="mb-3">
<label class="form-label">Maximum Stock Level</label>
{{ form.max_stock_level }}
<div class="form-text">Maximum inventory level (optional)</div>
</div>
</div>
</div>
<!-- END panel -->
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Supplier Information</h4>
<div class="panel-heading-btn">
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
</div>
</div>
<div class="panel-body">
<div class="mb-3">
<label class="form-label">Primary Supplier</label>
{{ form.primary_supplier }}
<div class="form-text">
<a href="{% url 'inventory:supplier_create' %}" target="_blank">Add new supplier</a>
</div>
</div>
</div>
</div>
<!-- END panel -->
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Form Actions</h4>
</div>
<div class="panel-body">
<div class="d-grid gap-2">
<button type="submit" class="btn btn-primary btn-lg">
<i class="fa fa-save me-2"></i>
{% if object %}Update Item{% else %}Create Item{% endif %}
</button>
{% if object %}
<button type="submit" name="save_and_continue" class="btn btn-success">
<i class="fa fa-save me-2"></i>Save & Continue Editing
</button>
{% else %}
<button type="submit" name="save_and_add_another" class="btn btn-info">
<i class="fa fa-plus me-2"></i>Save & Add Another
</button>
{% endif %}
<a href="{% if object %}{% url 'inventory:item_detail' object.pk %}{% else %}{% url 'inventory:item_list' %}{% endif %}" class="btn btn-secondary">
<i class="fa fa-times me-2"></i>Cancel
</a>
{% if object %}
<hr>
<a href="{% url 'inventory:item_delete' object.pk %}" class="btn btn-danger">
<i class="fa fa-trash me-2"></i>Delete Item
</a>
{% endif %}
</div>
</div>
</div>
<!-- END panel -->
</div>
</div>
</form>
{% endblock %}
{% block js %}
<script src="{% static 'assets/plugins/select2/dist/js/select2.min.js' %}"></script>
<script src="{% static 'assets/plugins/bootstrap-datepicker/dist/js/bootstrap-datepicker.min.js' %}"></script>
<script src="{% static 'assets/plugins/jquery-file-upload/js/jquery.fileupload.js' %}"></script>
<script>
$(document).ready(function() {
// Initialize Select2
$('.select2').select2({
theme: 'bootstrap-5',
width: '100%'
});
// Show/hide conditional fields
toggleConditionalFields();
// Event handlers for conditional fields
$('#id_has_expiration').on('change', function() {
if ($(this).is(':checked')) {
$('#shelf-life-field').show();
} else {
$('#shelf-life-field').hide();
$('#id_shelf_life_days').val('');
}
});
$('#id_controlled_substance').on('change', function() {
if ($(this).is(':checked')) {
$('#dea-schedule-field').show();
} else {
$('#dea-schedule-field').hide();
$('#id_dea_schedule').val('');
}
});
// Update package unit display
$('#id_unit_of_measure').on('change', function() {
var unit = $(this).find('option:selected').text().toLowerCase();
$('#package-unit').text(unit + 's');
});
// Form validation
$('#item-form').on('submit', function(e) {
var isValid = true;
var errors = [];
// Required field validation
if (!$('#id_item_code').val().trim()) {
errors.push('Item code is required');
isValid = false;
}
if (!$('#id_item_name').val().trim()) {
errors.push('Item name is required');
isValid = false;
}
// Controlled substance validation
if ($('#id_controlled_substance').is(':checked') && !$('#id_dea_schedule').val()) {
errors.push('DEA schedule is required for controlled substances');
isValid = false;
}
// Temperature range validation
var minTemp = parseFloat($('#id_storage_temperature_min').val());
var maxTemp = parseFloat($('#id_storage_temperature_max').val());
if (!isNaN(minTemp) && !isNaN(maxTemp) && minTemp >= maxTemp) {
errors.push('Minimum temperature must be less than maximum temperature');
isValid = false;
}
// Humidity range validation
var minHumidity = parseInt($('#id_storage_humidity_min').val());
var maxHumidity = parseInt($('#id_storage_humidity_max').val());
if (!isNaN(minHumidity) && !isNaN(maxHumidity) && minHumidity >= maxHumidity) {
errors.push('Minimum humidity must be less than maximum humidity');
isValid = false;
}
if (!isValid) {
e.preventDefault();
toastr.error('Please correct the following errors:<br>' + errors.join('<br>'));
}
});
// Auto-save draft functionality
var autoSaveTimer;
$('input, textarea, select').on('change', function() {
clearTimeout(autoSaveTimer);
autoSaveTimer = setTimeout(function() {
saveDraft();
}, 30000); // Auto-save after 30 seconds of inactivity
});
});
function toggleConditionalFields() {
// Show/hide expiration field
if ($('#id_has_expiration').is(':checked')) {
$('#shelf-life-field').show();
}
// Show/hide DEA schedule field
if ($('#id_controlled_substance').is(':checked')) {
$('#dea-schedule-field').show();
}
}
{#function generateItemCode() {#}
{# var category = $('#id_category').val();#}
{# var itemType = $('#id_item_type').val();#}
{# #}
{# if (!category) {#}
{# toastr.warning('Please select a category first');#}
{# return;#}
{# }#}
{# #}
{# $.ajax({#}
{# url: '{% url "inventory:generate_item_code" %}',#}
{# data: {#}
{# 'category': category,#}
{# 'item_type': itemType#}
{# },#}
{# success: function(response) {#}
{# $('#id_item_code').val(response.item_code);#}
{# toastr.success('Item code generated: ' + response.item_code);#}
{# },#}
{# error: function() {#}
{# toastr.error('Failed to generate item code');#}
{# }#}
{# });#}
{# }#}
function scanBarcode() {
// Implementation for barcode scanning
toastr.info('Barcode scanning functionality will be implemented');
}
function saveDraft() {
var formData = new FormData($('#item-form')[0]);
formData.append('save_draft', 'true');
$.ajax({
url: window.location.href,
method: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(response) {
if (response.success) {
toastr.info('Draft saved automatically');
}
},
error: function() {
// Silently fail for auto-save
}
});
}
// Prevent accidental navigation away from unsaved form
var formChanged = false;
$('input, textarea, select').on('change', function() {
formChanged = true;
});
$('#item-form').on('submit', function() {
formChanged = false;
});
$(window).on('beforeunload', function() {
if (formChanged) {
return 'You have unsaved changes. Are you sure you want to leave?';
}
});
</script>
{% endblock %}