147 lines
8.8 KiB
XML
147 lines
8.8 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<odoo>
|
|
|
|
<record id="portal_rental_inspection" model="ir.ui.view">
|
|
<field name="name">Rental Pickup Inspection</field>
|
|
<field name="type">qweb</field>
|
|
<field name="key">fusion_rental.portal_rental_inspection</field>
|
|
<field name="arch" type="xml">
|
|
<t t-call="web.frontend_layout">
|
|
<div class="container py-4">
|
|
<div class="row justify-content-center">
|
|
<div class="col-lg-8">
|
|
<div class="card shadow-sm">
|
|
<div class="card-header bg-primary text-white">
|
|
<h3 class="mb-0">Rental Pickup Inspection</h3>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="mb-3">
|
|
<strong>Order:</strong> <t t-out="order.name or ''">SO001</t><br/>
|
|
<strong>Customer:</strong> <t t-out="order.partner_id.name or ''">Customer</t><br/>
|
|
<strong>Task:</strong> <t t-out="task.name or ''">Task</t>
|
|
</div>
|
|
|
|
<h5>Equipment Condition</h5>
|
|
<div class="mb-3">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="radio" name="condition" id="cond_excellent" value="excellent"/>
|
|
<label class="form-check-label" for="cond_excellent">Excellent - No issues</label>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="radio" name="condition" id="cond_good" value="good"/>
|
|
<label class="form-check-label" for="cond_good">Good - Minor wear</label>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="radio" name="condition" id="cond_fair" value="fair"/>
|
|
<label class="form-check-label" for="cond_fair">Fair - Some issues noted</label>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="radio" name="condition" id="cond_damaged" value="damaged"/>
|
|
<label class="form-check-label" for="cond_damaged">Damaged - Requires review</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="inspection_notes" class="form-label">Notes / Damage Description</label>
|
|
<textarea id="inspection_notes" class="form-control" rows="4"
|
|
placeholder="Describe the condition, any damage, missing parts..."/>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label">Photos</label>
|
|
<input type="file" id="inspection_photos" class="form-control"
|
|
accept="image/*" multiple="multiple"/>
|
|
<div class="text-muted small mt-1">Upload photos of the equipment condition.</div>
|
|
</div>
|
|
|
|
<div id="inspection_error" class="alert alert-danger d-none"></div>
|
|
<div id="inspection_success" class="alert alert-success d-none"></div>
|
|
|
|
<button type="button" id="btn_submit_inspection" class="btn btn-primary btn-lg w-100"
|
|
t-att-data-task-id="task.id">
|
|
Submit Inspection
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
document.getElementById('btn_submit_inspection').addEventListener('click', async function() {
|
|
var btn = this;
|
|
btn.disabled = true;
|
|
btn.textContent = 'Submitting...';
|
|
var errDiv = document.getElementById('inspection_error');
|
|
var successDiv = document.getElementById('inspection_success');
|
|
errDiv.classList.add('d-none');
|
|
successDiv.classList.add('d-none');
|
|
|
|
var condition = document.querySelector('input[name="condition"]:checked');
|
|
if (!condition) {
|
|
errDiv.textContent = 'Please select an equipment condition.';
|
|
errDiv.classList.remove('d-none');
|
|
btn.disabled = false;
|
|
btn.textContent = 'Submit Inspection';
|
|
return;
|
|
}
|
|
|
|
var photoIds = [];
|
|
var files = document.getElementById('inspection_photos').files;
|
|
for (var i = 0; i < files.length; i++) {
|
|
var reader = new FileReader();
|
|
var data = await new Promise(function(resolve) {
|
|
reader.onload = function(e) { resolve(e.target.result.split(',')[1]); };
|
|
reader.readAsDataURL(files[i]);
|
|
});
|
|
var resp = await fetch('/web/dataset/call_kw', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json'},
|
|
body: JSON.stringify({
|
|
jsonrpc: '2.0', method: 'call', id: i + 1,
|
|
params: {
|
|
model: 'ir.attachment', method: 'create',
|
|
args: [{'name': files[i].name, 'type': 'binary', 'datas': data}],
|
|
kwargs: {},
|
|
}
|
|
})
|
|
});
|
|
var result = await resp.json();
|
|
if (result.result) photoIds.push(result.result);
|
|
}
|
|
|
|
var taskId = btn.dataset.taskId;
|
|
fetch('/my/technician/rental-inspection/' + taskId + '/submit', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json'},
|
|
body: JSON.stringify({
|
|
jsonrpc: '2.0', method: 'call', id: 99,
|
|
params: {
|
|
task_id: parseInt(taskId),
|
|
condition: condition.value,
|
|
notes: document.getElementById('inspection_notes').value,
|
|
photo_ids: photoIds,
|
|
}
|
|
})
|
|
}).then(function(r) { return r.json(); }).then(function(data) {
|
|
var res = data.result || data;
|
|
if (res.success) {
|
|
successDiv.textContent = res.message || 'Inspection saved!';
|
|
successDiv.classList.remove('d-none');
|
|
btn.textContent = 'Submitted!';
|
|
} else {
|
|
errDiv.textContent = res.error || 'An error occurred.';
|
|
errDiv.classList.remove('d-none');
|
|
btn.disabled = false;
|
|
btn.textContent = 'Submit Inspection';
|
|
}
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
</t>
|
|
</field>
|
|
</record>
|
|
|
|
</odoo>
|