67a0e674ca
Marine maintenance management: work orders with photos, ISM/SWP procedures, MSDS, inventory, RFQ/purchases, vessel history, bilingual PDF reports. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
134 lines
5.9 KiB
HTML
134 lines
5.9 KiB
HTML
{% extends 'base.html' %}
|
|
{% block title %}Nueva Orden de Trabajo{% endblock %}
|
|
{% block page_title %}Nueva Orden de Trabajo{% endblock %}
|
|
{% block topbar_actions %}
|
|
<a href="{{ url_for('work_orders') }}" class="btn btn-secondary">← Volver</a>
|
|
{% endblock %}
|
|
{% block content %}
|
|
<div class="card" style="max-width:820px">
|
|
<form method="POST">
|
|
<div class="form-grid">
|
|
<div class="form-group">
|
|
<label>Sistema Principal *</label>
|
|
<select name="system_id" id="systemSelect" required>
|
|
<option value="">-- Seleccionar Sistema --</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label style="color:var(--cyan)">🚢 Embarcación *</label>
|
|
<select name="vessel_id" id="vesselSelect" required onchange="loadEquipment(this.value)"
|
|
style="border-color:rgba(0,180,216,0.4);font-weight:600">
|
|
<option value="">— Seleccionar Embarcación —</option>
|
|
{% for v in vessels %}
|
|
<option value="{{ v.id }}" {% if preselect_vessel and preselect_vessel==v.id|string %}selected{% endif %}>{{ v.name }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Equipo Específico (opcional)</label>
|
|
<select name="equipment_id" id="equipmentSelect">
|
|
<option value="">— General / Sin equipo específico —</option>
|
|
{% for e in equipment_list %}
|
|
<option value="{{ e.id }}">{{ e.name }} {% if e.serial_number %}· S/N: {{ e.serial_number }}{% endif %}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
<div class="form-group full">
|
|
<label>Scope — Resumen del Trabajo *</label>
|
|
<input type="text" name="scope" required
|
|
placeholder="Ej: Diagnóstico y cambio de cargador de baterías estribor">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Tipo de Facturación *</label>
|
|
<select name="billing_type" required>
|
|
<option value="labor_materials" {% if not order or order.billing_type=='labor_materials' %}selected{% endif %}>
|
|
Mano de obra + Materiales (discriminado)
|
|
</option>
|
|
<option value="lump_sum" {% if order and order.billing_type=='lump_sum' %}selected{% endif %}>
|
|
A todo costo (precio fijo todo incluido)
|
|
</option>
|
|
<option value="labor_only" {% if order and order.billing_type=='labor_only' %}selected{% endif %}>
|
|
Solo mano de obra
|
|
</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Tipo de Trabajo</label>
|
|
<select name="work_type">
|
|
<option value="">-- Seleccionar --</option>
|
|
<option value="Preventive">Preventivo</option>
|
|
<option value="Corrective">Correctivo</option>
|
|
<option value="Inspection">Inspección</option>
|
|
<option value="Installation">Instalación</option>
|
|
<option value="Other">Otro</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Técnico</label>
|
|
<input type="text" name="technician">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Fecha Inicio</label>
|
|
<input type="date" name="start_date" id="startDate">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Horas Motor (inicio)</label>
|
|
<input type="number" step="0.1" name="engine_hours_start">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Tarifa Mano de Obra ($/h)</label>
|
|
<input type="number" step="0.01" name="labor_rate" value="0">
|
|
</div>
|
|
<div class="form-group full">
|
|
<label>Descripción Detallada</label>
|
|
<textarea name="description" rows="4"
|
|
placeholder="Describe en detalle el trabajo a realizar..."></textarea>
|
|
</div>
|
|
<div class="form-group full">
|
|
<label>Notas Internas</label>
|
|
<textarea name="notes" rows="2"></textarea>
|
|
</div>
|
|
</div>
|
|
<div class="flex gap-3 mt-6">
|
|
<button type="submit" class="btn btn-primary">💾 Crear Orden</button>
|
|
<a href="{{ url_for('work_orders') }}" class="btn btn-secondary">Cancelar</a>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
{% endblock %}
|
|
{% block scripts %}
|
|
<script>
|
|
document.getElementById('startDate').value = new Date().toISOString().split('T')[0];
|
|
|
|
// Load systems
|
|
fetch('/api/systems').then(r=>r.json()).then(data => {
|
|
const sel = document.getElementById('systemSelect');
|
|
data.forEach(s => {
|
|
const opt = document.createElement('option');
|
|
opt.value = s.id;
|
|
opt.textContent = s.name;
|
|
sel.appendChild(opt);
|
|
});
|
|
});
|
|
|
|
function loadEquipment(vesselId) {
|
|
const sel = document.getElementById('equipmentSelect');
|
|
sel.innerHTML = '<option value="">— General / Sin equipo específico —</option>';
|
|
if (!vesselId) return;
|
|
fetch(`/api/vessel-equipment/${vesselId}`)
|
|
.then(r => r.json())
|
|
.then(data => {
|
|
data.forEach(e => {
|
|
const opt = document.createElement('option');
|
|
opt.value = e.id;
|
|
opt.textContent = e.name + (e.serial_number ? ` · S/N: ${e.serial_number}` : '');
|
|
sel.appendChild(opt);
|
|
});
|
|
});
|
|
}
|
|
{% if preselect_vessel %}
|
|
loadEquipment('{{ preselect_vessel }}');
|
|
{% endif %}
|
|
</script>
|
|
{% endblock %}
|