Django_Basic_Manufacturing_3/templates/purchasing/gr_form.html
2025-08-22 17:05:22 +07:00

190 lines
8.7 KiB
HTML

{% extends 'base.html' %}
{% load indonesian_filters %}
{% block title %}{{ module_title }} - Manufacturing App{% endblock %}
{% block content %}
<div class="container-fluid mt-4">
<div class="row">
<div class="col-md-10 offset-md-1">
<div class="card">
<div class="card-header">
<h4 class="mb-0">
<i class="fas fa-truck-loading"></i> Create Goods Receipt
</h4>
</div>
<div class="card-body">
<!-- Purchase Order Info -->
<div class="alert alert-info">
<h6>Creating Goods Receipt for Purchase Order: {{ po.po_number }}</h6>
<p class="mb-1"><strong>Supplier:</strong> {{ po.supplier.name }}</p>
<p class="mb-0"><strong>Order Total:</strong> {{ po.total_amount|format_rupiah }}</p>
</div>
<form method="post" id="gr-form">
{% csrf_token %}
<!-- Goods Receipt Header -->
<div class="row mb-4">
<div class="col-md-6">
<div class="mb-3">
<label for="id_receipt_date" class="form-label">Receipt Date *</label>
<input type="date" name="receipt_date" id="id_receipt_date"
class="form-control" value="{{ today }}" required>
</div>
</div>
</div>
<!-- Order Items for Receipt -->
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">Items to Receive</h5>
</div>
<div class="card-body">
{% if po.items.all %}
{% for po_item in po.items.all %}
<div class="row mb-3 p-3 border rounded">
<div class="col-md-4">
<h6>{{ po_item.product.name }}</h6>
<small class="text-muted">{{ po_item.product.code }}</small>
</div>
<div class="col-md-2">
<label class="form-label">Ordered</label>
<div class="form-control-plaintext">
{{ po_item.quantity|indonesian_number:2 }} {{ po_item.product.unit_of_measure.abbreviation }}
</div>
</div>
<div class="col-md-2">
<label class="form-label">Previously Received</label>
<div class="form-control-plaintext">
{{ po_item.received_quantity|indonesian_number:2 }} {{ po_item.product.unit_of_measure.abbreviation }}
</div>
</div>
<div class="col-md-2">
<label class="form-label">Receiving Now *</label>
<input type="text" name="quantity_{{ po_item.id }}"
class="form-control indonesian-number"
placeholder="0,00" required
data-min="0"
data-max="{{ po_item.quantity|add:po_item.received_quantity|floatformat:2 }}">
</div>
<div class="col-md-2">
<label class="form-label">Notes</label>
<input type="text" name="notes_{{ po_item.id }}"
class="form-control" placeholder="Optional notes">
</div>
</div>
{% endfor %}
{% else %}
<p class="text-muted">No items found in this purchase order.</p>
{% endif %}
</div>
</div>
<!-- Notes -->
<div class="mb-3">
<label for="id_notes" class="form-label">General Notes</label>
<textarea name="notes" id="id_notes" class="form-control" rows="3"
placeholder="Optional general notes for this receipt"></textarea>
</div>
<div class="d-flex justify-content-between">
<a href="{% url 'purchasing:po_detail' po.po_number %}" class="btn btn-secondary">
<i class="fas fa-times"></i> Cancel
</a>
<button type="submit" class="btn btn-success">
<i class="fas fa-save"></i> Create Goods Receipt
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% block extra_js %}
<script>
document.addEventListener('DOMContentLoaded', function() {
// Indonesian number formatting for quantity fields
document.querySelectorAll('.indonesian-number').forEach(function(field) {
field.addEventListener('input', function(e) {
// Allow only numbers and comma
let value = this.value.replace(/[^0-9,]/g, '');
// Ensure only one comma
const parts = value.split(',');
if (parts.length > 2) {
value = parts[0] + ',' + parts.slice(1).join('');
}
this.value = value;
});
field.addEventListener('blur', function(e) {
// Format the number properly on blur
let value = this.value.replace(/[^0-9,]/g, '');
if (value) {
const parts = value.split(',');
if (parts.length === 2) {
// Ensure decimal part has 2 digits
parts[1] = parts[1].substring(0, 2).padEnd(2, '0');
this.value = parts[0] + ',' + parts[1];
} else {
this.value = parts[0] + ',00';
}
}
});
});
// Add validation for quantity fields
document.querySelectorAll('input[name^="quantity_"]').forEach(function(field) {
field.addEventListener('blur', function() {
const value = parseFloat(this.value.replace(',', '.')) || 0;
const max = parseFloat(this.getAttribute('data-max')) || 0;
const min = parseFloat(this.getAttribute('data-min')) || 0;
if (value < min) {
this.value = formatIndonesianNumber(min);
} else if (value > max) {
this.value = formatIndonesianNumber(max);
alert('Cannot receive more than ordered quantity!');
}
});
});
// Auto-focus on first quantity field
const firstQuantityField = document.querySelector('input[name^="quantity_"]');
if (firstQuantityField) {
firstQuantityField.focus();
}
// Form validation before submission
document.getElementById('gr-form').addEventListener('submit', function(e) {
let hasValidQuantity = false;
document.querySelectorAll('input[name^="quantity_"]').forEach(function(field) {
const value = parseFloat(field.value.replace(',', '.')) || 0;
if (value > 0) {
hasValidQuantity = true;
}
});
if (!hasValidQuantity) {
alert('Please enter at least one quantity to receive.');
e.preventDefault();
return false;
}
// Show loading state
const submitBtn = this.querySelector('button[type="submit"]');
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Creating...';
submitBtn.disabled = true;
});
});
function formatIndonesianNumber(num) {
return num.toFixed(2).toString().replace('.', ',');
}
</script>
{% endblock %}
{% endblock %}