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

694 lines
33 KiB
HTML

{% extends "base.html" %}
{% load static %}
{% block title %}{{ object.item_name }} - Inventory Item Details{% endblock %}
{% block css %}
<link href="{% static 'plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" />
<link href="{% static 'plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" />
<link href="{% static 'plugins/chart.js/dist/Chart.min.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">{{ object.item_code }}</li>
</ol>
<!-- END breadcrumb -->
<!-- BEGIN page-header -->
<h1 class="page-header">
{{ object.item_name }}
<small>{{ object.item_code }} - Inventory Item Details</small>
</h1>
<!-- END page-header -->
<div class="row">
<div class="col-xl-8">
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Item Information</h4>
<div class="panel-heading-btn">
<a href="{% url 'inventory:item_update' object.pk %}" class="btn btn-xs btn-primary me-2">
<i class="fa fa-edit"></i> Edit
</a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
</div>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-6">
<table class="table table-borderless">
<tr>
<td class="fw-bold" width="150">Item Code:</td>
<td>{{ object.item_code }}</td>
</tr>
<tr>
<td class="fw-bold">Item Name:</td>
<td>{{ object.item_name }}</td>
</tr>
<tr>
<td class="fw-bold">Category:</td>
<td>
<span class="badge bg-secondary">{{ object.get_category_display }}</span>
{% if object.subcategory %}
<br><small class="text-muted">{{ object.subcategory }}</small>
{% endif %}
</td>
</tr>
<tr>
<td class="fw-bold">Item Type:</td>
<td>
<span class="badge bg-{{ object.get_item_type_color }}">{{ object.get_item_type_display }}</span>
</td>
</tr>
<tr>
<td class="fw-bold">Unit of Measure:</td>
<td>{{ object.get_unit_of_measure_display }}</td>
</tr>
<tr>
<td class="fw-bold">Package Size:</td>
<td>{{ object.package_size }} {{ object.get_unit_of_measure_display }}{{ object.package_size|pluralize }}</td>
</tr>
</table>
</div>
<div class="col-md-6">
<table class="table table-borderless">
<tr>
<td class="fw-bold" width="150">Manufacturer:</td>
<td>{{ object.manufacturer|default:"Not specified" }}</td>
</tr>
<tr>
<td class="fw-bold">Model Number:</td>
<td>{{ object.model_number|default:"Not specified" }}</td>
</tr>
<tr>
<td class="fw-bold">Part Number:</td>
<td>{{ object.part_number|default:"Not specified" }}</td>
</tr>
<tr>
<td class="fw-bold">UPC Code:</td>
<td>{{ object.upc_code|default:"Not specified" }}</td>
</tr>
<tr>
<td class="fw-bold">Unit Cost:</td>
<td class="fw-bold text-success"><span class="symbol">&#xea;</span>{{ object.unit_cost|floatformat:'2g' }}</td>
</tr>
<tr>
<td class="fw-bold">List Price:</td>
<td><span class="symbol">&#xea;</span>{{ object.list_price|floatformat:'2g' }}</td>
</tr>
</table>
</div>
</div>
{% if object.description %}
<div class="mt-4">
<h6>Description</h6>
<div class="bg-light p-3 rounded">{{ object.description }}</div>
</div>
{% endif %}
<!-- Item Features -->
<div class="mt-4">
<h6>Item Features</h6>
<div class="row">
<div class="col-md-6">
<div class="mb-2">
<i class="fa fa-{{ object.is_active|yesno:'check text-success,times text-danger' }} me-2"></i>
Active Item
</div>
<div class="mb-2">
<i class="fa fa-{{ object.is_tracked|yesno:'check text-success,times text-muted' }} me-2"></i>
Inventory Tracked
</div>
<div class="mb-2">
<i class="fa fa-{{ object.is_serialized|yesno:'check text-success,times text-muted' }} me-2"></i>
Serial Number Tracking
</div>
</div>
<div class="col-md-6">
<div class="mb-2">
<i class="fa fa-{{ object.is_lot_tracked|yesno:'check text-success,times text-muted' }} me-2"></i>
Lot Number Tracking
</div>
<div class="mb-2">
<i class="fa fa-{{ object.has_expiration|yesno:'check text-success,times text-muted' }} me-2"></i>
Has Expiration Date
</div>
<div class="mb-2">
<i class="fa fa-{{ object.controlled_substance|yesno:'check text-warning,times text-muted' }} me-2"></i>
Controlled Substance
</div>
</div>
</div>
</div>
<!-- Regulatory Information -->
{% if object.fda_approved or object.controlled_substance or object.dea_schedule %}
<div class="mt-4">
<h6>Regulatory Information</h6>
<div class="row">
{% if object.fda_approved %}
<div class="col-md-4">
<div class="text-center p-3 bg-success text-white rounded">
<i class="fa fa-check-circle fa-2x mb-2"></i>
<div>FDA Approved</div>
</div>
</div>
{% endif %}
{% if object.controlled_substance %}
<div class="col-md-4">
<div class="text-center p-3 bg-warning text-white rounded">
<i class="fa fa-exclamation-triangle fa-2x mb-2"></i>
<div>Controlled Substance</div>
{% if object.dea_schedule %}
<small>{{ object.get_dea_schedule_display }}</small>
{% endif %}
</div>
</div>
{% endif %}
</div>
</div>
{% endif %}
<!-- Clinical Information -->
{% if object.clinical_use or object.contraindications %}
<div class="mt-4">
<h6>Clinical Information</h6>
{% if object.clinical_use %}
<div class="mb-3">
<strong>Clinical Use:</strong><br>
<div class="bg-light p-3 rounded">{{ object.clinical_use }}</div>
</div>
{% endif %}
{% if object.contraindications %}
<div class="mb-3">
<strong>Contraindications:</strong><br>
<div class="bg-warning-subtle p-3 rounded border border-warning">
<i class="fa fa-exclamation-triangle text-warning me-2"></i>
{{ object.contraindications }}
</div>
</div>
{% endif %}
</div>
{% endif %}
</div>
</div>
<!-- END panel -->
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Stock Information</h4>
<div class="panel-heading-btn">
<a href="{% url 'inventory:stock_create' %}?item={{ object.pk }}" class="btn btn-xs btn-success me-2">
<i class="fa fa-plus"></i> Add Stock
</a>
<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">
<!-- Stock Summary -->
<div class="row mb-4">
<div class="col-md-3">
<div class="text-center p-3 bg-primary text-white rounded">
<div class="fs-24px fw-bold">{{ object.current_stock }}</div>
<div class="small">Current Stock</div>
</div>
</div>
<div class="col-md-3">
<div class="text-center p-3 bg-warning text-white rounded">
<div class="fs-24px fw-bold">{{ object.reorder_point }}</div>
<div class="small">Reorder Point</div>
</div>
</div>
<div class="col-md-3">
<div class="text-center p-3 bg-info text-white rounded">
<div class="fs-24px fw-bold">{{ object.reorder_quantity }}</div>
<div class="small">Reorder Quantity</div>
</div>
</div>
<div class="col-md-3">
<div class="text-center p-3 bg-success text-white rounded">
<div class="fs-24px fw-bold"><span class="symbol">&#xea;</span>{{ object.total_value|floatformat:'2g' }}</div>
<div class="small">Total Value</div>
</div>
</div>
</div>
<!-- Stock Status Alert -->
{% if object.needs_reorder %}
<div class="alert alert-warning d-flex align-items-center mb-4">
<i class="fa fa-exclamation-triangle fa-2x me-3"></i>
<div>
<h6 class="alert-heading mb-1">Reorder Required</h6>
<p class="mb-0">Current stock ({{ object.current_stock }}) is at or below the reorder point ({{ object.reorder_point }}). Consider placing a new order.</p>
</div>
<div class="ms-auto">
<a href="{% url 'inventory:purchase_order_create' %}?item={{ object.pk }}" class="btn btn-warning">
<i class="fa fa-shopping-cart me-2"></i>Create Order
</a>
</div>
</div>
{% endif %}
<!-- Stock by Location -->
{% if object.inventory_stocks.exists %}
<div class="table-responsive">
<table class="table table-sm">
<thead>
<tr>
<th>Location</th>
<th>Lot Number</th>
<th>Quantity</th>
<th>Expiration</th>
<th>Quality Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for stock in object.inventory_stocks.all %}
<tr>
<td>
<a href="{% url 'inventory:location_detail' stock.location.pk %}" class="text-decoration-none">
{{ stock.location.name }}
</a>
</td>
<td>{{ stock.lot_number|default:"-" }}</td>
<td>
<span class="fw-bold">{{ stock.quantity_on_hand }}</span>
{% if stock.quantity_reserved > 0 %}
<br><small class="text-muted">({{ stock.quantity_reserved }} reserved)</small>
{% endif %}
</td>
<td>
{% if stock.expiration_date %}
{% if stock.is_expired %}
<span class="text-danger fw-bold">{{ stock.expiration_date|date:"M d, Y" }}</span>
<br><small class="text-danger">Expired</small>
{% elif stock.days_to_expiry <= 30 %}
<span class="text-warning fw-bold">{{ stock.expiration_date|date:"M d, Y" }}</span>
<br><small class="text-warning">{{ stock.days_to_expiry }} days</small>
{% else %}
{{ stock.expiration_date|date:"M d, Y" }}
{% endif %}
{% else %}
<span class="text-muted">No expiration</span>
{% endif %}
</td>
<td>
{% if stock.quality_status == 'GOOD' %}
<span class="badge bg-success">{{ stock.get_quality_status_display }}</span>
{% elif stock.quality_status == 'QUARANTINE' %}
<span class="badge bg-warning">{{ stock.get_quality_status_display }}</span>
{% else %}
<span class="badge bg-danger">{{ stock.get_quality_status_display }}</span>
{% endif %}
</td>
<td>
<a href="{% url 'inventory:stock_detail' stock.pk %}" class="btn btn-xs btn-outline-primary">
<i class="fa fa-eye"></i>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-center py-4 text-muted">
<i class="fa fa-boxes fa-3x mb-3"></i>
<p>No stock records found for this item.</p>
<a href="{% url 'inventory:stock_create' %}?item={{ object.pk }}" class="btn btn-primary">
<i class="fa fa-plus me-2"></i>Add Initial Stock
</a>
</div>
{% endif %}
</div>
</div>
<!-- END panel -->
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Recent Transactions</h4>
<div class="panel-heading-btn">
<a href="#" class="btn btn-xs btn-outline-secondary me-2">
<i class="fa fa-list"></i> View All
</a>
<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">
{% if recent_transactions %}
<div class="timeline">
{% for transaction in recent_transactions %}
<div class="timeline-item">
<div class="timeline-time">{{ transaction.transaction_date|date:"M d" }}</div>
<div class="timeline-icon bg-{{ transaction.get_transaction_type_color }}">
<i class="fa fa-{{ transaction.get_transaction_icon }}"></i>
</div>
<div class="timeline-body">
<div class="timeline-header">
<span class="fw-bold">{{ transaction.get_transaction_type_display }}</span>
<span class="badge bg-{{ transaction.get_transaction_type_color }} ms-2">
{{ transaction.quantity_change|floatformat:0 }}
</span>
</div>
<div class="timeline-content">
<div class="small text-muted">
{{ transaction.location.name }}
{% if transaction.reference_number %}
• Ref: {{ transaction.reference_number }}
{% endif %}
</div>
{% if transaction.notes %}
<div class="small">{{ transaction.notes|truncatechars:100 }}</div>
{% endif %}
</div>
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="text-center py-4 text-muted">
<i class="fa fa-exchange-alt fa-3x mb-3"></i>
<p>No recent transactions for this item.</p>
</div>
{% endif %}
</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">Quick Actions</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="d-grid gap-2">
<a href="{% url 'inventory:item_update' object.pk %}" class="btn btn-primary">
<i class="fa fa-edit me-2"></i>Edit Item
</a>
<a href="{% url 'inventory:stock_create' %}?item={{ object.pk }}" class="btn btn-success">
<i class="fa fa-plus me-2"></i>Add Stock
</a>
<a href="#" class="btn btn-warning">
<i class="fa fa-adjust me-2"></i>Adjust Stock
</a>
{% if object.needs_reorder %}
<a href="{% url 'inventory:purchase_order_create' %}?item={{ object.pk }}" class="btn btn-info">
<i class="fa fa-shopping-cart me-2"></i>Create Purchase Order
</a>
{% endif %}
<button class="btn btn-outline-secondary" onclick="printItemLabel()">
<i class="fa fa-print me-2"></i>Print Label
</button>
<button class="btn btn-outline-info" onclick="showStockChart()">
<i class="fa fa-chart-line me-2"></i>Stock History
</button>
</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">
{% if object.storage_temperature_min or object.storage_temperature_max or object.storage_requirements %}
<table class="table table-sm table-borderless">
{% if object.storage_temperature_min or object.storage_temperature_max %}
<tr>
<td class="text-muted">Temperature:</td>
<td>
{% if object.storage_temperature_min and object.storage_temperature_max %}
{{ object.storage_temperature_min }}°C to {{ object.storage_temperature_max }}°C
{% elif object.storage_temperature_min %}
Above {{ object.storage_temperature_min }}°C
{% elif object.storage_temperature_max %}
Below {{ object.storage_temperature_max }}°C
{% endif %}
</td>
</tr>
{% endif %}
{% if object.storage_humidity_min or object.storage_humidity_max %}
<tr>
<td class="text-muted">Humidity:</td>
<td>
{% if object.storage_humidity_min and object.storage_humidity_max %}
{{ object.storage_humidity_min }}% to {{ object.storage_humidity_max }}%
{% elif object.storage_humidity_min %}
Above {{ object.storage_humidity_min }}%
{% elif object.storage_humidity_max %}
Below {{ object.storage_humidity_max }}%
{% endif %}
</td>
</tr>
{% endif %}
{% if object.shelf_life_days %}
<tr>
<td class="text-muted">Shelf Life:</td>
<td>{{ object.shelf_life_days }} days</td>
</tr>
{% endif %}
</table>
{% if object.storage_requirements %}
<div class="mt-3">
<strong>Special Requirements:</strong><br>
<div class="bg-light p-3 rounded small">{{ object.storage_requirements }}</div>
</div>
{% endif %}
{% else %}
<div class="text-center py-3 text-muted">
<i class="fa fa-thermometer-half fa-2x mb-2"></i>
<p class="mb-0">No special storage requirements specified.</p>
</div>
{% endif %}
</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">
{% if object.primary_supplier %}
<div class="d-flex align-items-center mb-3">
<div class="flex-fill">
<div class="fw-bold">{{ object.primary_supplier.name }}</div>
<div class="text-muted small">Primary Supplier</div>
</div>
<a href="{% url 'inventory:supplier_detail' object.primary_supplier.pk %}" class="btn btn-sm btn-outline-primary">
View Details
</a>
</div>
{% if object.primary_supplier.contact_email %}
<div class="small mb-2">
<i class="fa fa-envelope me-2"></i>{{ object.primary_supplier.contact_email }}
</div>
{% endif %}
{% if object.primary_supplier.contact_phone %}
<div class="small mb-2">
<i class="fa fa-phone me-2"></i>{{ object.primary_supplier.contact_phone }}
</div>
{% endif %}
{% else %}
<div class="text-center py-3 text-muted">
<i class="fa fa-truck fa-2x mb-2"></i>
<p class="mb-0">No primary supplier assigned.</p>
<a href="{% url 'inventory:item_update' object.pk %}" class="btn btn-sm btn-outline-primary mt-2">
Assign Supplier
</a>
</div>
{% endif %}
</div>
</div>
<!-- END panel -->
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Item History</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="small text-muted">
<div class="mb-2">
<strong>Created:</strong> {{ object.created_at|date:"M d, Y H:i" }}
{% if object.created_by %}
<br>by {{ object.created_by.get_full_name }}
{% endif %}
</div>
<div class="mb-2">
<strong>Last Updated:</strong> {{ object.updated_at|date:"M d, Y H:i" }}
</div>
{% if object.notes %}
<div class="mt-3">
<strong>Notes:</strong><br>
<div class="bg-light p-2 rounded">{{ object.notes }}</div>
</div>
{% endif %}
</div>
</div>
</div>
<!-- END panel -->
</div>
</div>
<!-- Stock Chart Modal -->
<div class="modal fade" id="stockChartModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Stock Level History</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div style="height: 400px;">
<canvas id="stock-chart"></canvas>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" onclick="exportStockChart()">Export Chart</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block js %}
<script src="{% static 'plugins/datatables.net/js/dataTables.min.js' %}"></script>
<script src="{% static 'plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script>
<script src="{% static 'plugins/chart.js/dist/chart.js' %}"></script>
<script>
var stockChart;
{#function printItemLabel() {#}
{# window.open('{% url "inventory:item_label_print" object.pk %}', '_blank');#}
{# }#}
function showStockChart() {
$('#stockChartModal').modal('show');
loadStockChart();
}
{#function loadStockChart() {#}
{# $.ajax({#}
{# url: '{% url "inventory:item_stock_history" object.pk %}',#}
{# success: function(data) {#}
{# renderStockChart(data);#}
{# },#}
{# error: function() {#}
{# toastr.error('Failed to load stock history data');#}
{# }#}
{# });#}
{# }#}
function renderStockChart(data) {
var ctx = document.getElementById('stock-chart').getContext('2d');
if (stockChart) {
stockChart.destroy();
}
stockChart = new Chart(ctx, {
type: 'line',
data: {
labels: data.labels,
datasets: [{
label: 'Stock Level',
data: data.stock_levels,
borderColor: 'rgb(75, 192, 192)',
backgroundColor: 'rgba(75, 192, 192, 0.2)',
tension: 0.1
}, {
label: 'Reorder Point',
data: data.reorder_points,
borderColor: 'rgb(255, 99, 132)',
backgroundColor: 'rgba(255, 99, 132, 0.2)',
borderDash: [5, 5],
tension: 0.1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
title: {
display: true,
text: 'Quantity'
}
},
x: {
title: {
display: true,
text: 'Date'
}
}
}
}
});
}
function exportStockChart() {
if (stockChart) {
var url = stockChart.toBase64Image();
var link = document.createElement('a');
link.download = 'stock-history-{{ object.item_code }}.png';
link.href = url;
link.click();
}
}
// Auto-refresh stock information every 5 minutes
setInterval(function() {
location.reload();
}, 300000);
</script>
{% endblock %}