feat(c4): complete quota projection and copier views
This commit is contained in:
parent
a2374d8157
commit
e560d824cc
3 changed files with 27 additions and 3 deletions
|
|
@ -11,7 +11,7 @@ from ..core.models import (
|
|||
)
|
||||
from ..core.services.c4_service import (
|
||||
C4DomainError, assign_equipment_to_contract, calculate_contract_usage,
|
||||
create_consumable_order, create_contract, evaluate_quota_alert,
|
||||
create_consumable_order, create_contract, evaluate_quota_alert, project_contract_usage,
|
||||
estimate_consumable_lifetime, receive_consumable_order, record_consumable_issue,
|
||||
)
|
||||
from ..extensions import db
|
||||
|
|
@ -31,6 +31,16 @@ def contracts():
|
|||
return render_template("c4/contracts.html", contracts=rows)
|
||||
|
||||
|
||||
@c4_bp.get("/equipment/<int:equipment_id>")
|
||||
@login_required
|
||||
@permission_required("patrimoine.view")
|
||||
def equipment_detail(equipment_id):
|
||||
equipment = Equipment.query.get_or_404(equipment_id)
|
||||
assignments = ContractEquipmentAssignment.query.filter_by(equipment_id=equipment.id).order_by(ContractEquipmentAssignment.entry_date.desc()).all()
|
||||
links = EquipmentConsumable.query.filter_by(equipment_id=equipment.id).all()
|
||||
return render_template("c4/equipment_detail.html", equipment=equipment, assignments=assignments, links=links)
|
||||
|
||||
|
||||
@c4_bp.route("/contracts/new", methods=["GET", "POST"])
|
||||
@login_required
|
||||
@permission_required("contract.manage")
|
||||
|
|
@ -60,7 +70,8 @@ def contract_detail(contract_id):
|
|||
contract = PhotocopierContract.query.get_or_404(contract_id)
|
||||
periods = contract.periods
|
||||
data = {period.id: calculate_contract_usage(period) for period in periods}
|
||||
return render_template("c4/contract_detail.html", contract=contract, periods=periods, usage=data)
|
||||
projections = {period.id: project_contract_usage(period) for period in periods}
|
||||
return render_template("c4/contract_detail.html", contract=contract, periods=periods, usage=data, projections=projections)
|
||||
|
||||
|
||||
@c4_bp.post("/contracts/<int:contract_id>/equipment")
|
||||
|
|
|
|||
|
|
@ -1,3 +1,13 @@
|
|||
{% extends "base.html" %}
|
||||
{% block title %}{{ contract.name }} — GMAO{% endblock %}
|
||||
{% block content %}<div class="container-fluid"><div class="d-flex justify-content-between"><h1 class="h4">{{ contract.name }}</h1><span class="badge text-bg-secondary">{{ contract.status }}</span></div><p>{{ contract.supplier.name }} · {{ contract.start_date }} → {{ contract.end_date }} · anniversaire {{ '%02d/%02d'|format(contract.anniversary_day, contract.anniversary_month) }}</p><form method="post" action="{{ url_for('c4.close_contract', contract_id=contract.id) }}" class="mb-3"><input type="hidden" name="csrf_token" value="{{ csrf_token() }}"><button class="btn btn-outline-danger btn-sm">Clore le contrat</button></form>{% for period in periods %}{% set u=usage[period.id] %}<section class="card mb-3"><div class="card-header">Période {{ period.start_date }} → {{ period.end_date }}</div><div class="card-body"><div class="row"><div class="col-md-6"><strong>N&B</strong><br>{{ '%.0f'|format(u.bw) }}{% if period.quota_bw is not none %} / {{ period.quota_bw }}{% else %} — sans quota{% endif %}</div><div class="col-md-6"><strong>Couleur</strong><br>{{ '%.0f'|format(u.color) }}{% if period.quota_color is not none %} / {{ period.quota_color }}{% else %} — sans quota{% endif %}</div></div><small>Machines prises en compte : {{ u.machines }} · qualité : {{ u.quality }}</small></div></section>{% endfor %}<h2 class="h5">Machines rattachées</h2><ul>{% for a in contract.assignments %}<li>{{ a.equipment.name }} — {{ a.entry_date }}{% if a.exit_date %} → {{ a.exit_date }}{% endif %}</li>{% else %}<li>Aucune machine.</li>{% endfor %}</ul></div>{% endblock %}
|
||||
{% block content %}
|
||||
<div class="container-fluid">
|
||||
<div class="d-flex justify-content-between"><h1 class="h4">{{ contract.name }}</h1><span class="badge text-bg-secondary">{{ contract.status }}</span></div>
|
||||
<p>{{ contract.supplier.name }} · {{ contract.start_date }} → {{ contract.end_date }} · période quota à partir du {{ contract.quota_start_date or contract.start_date }} · anniversaire {{ '%02d/%02d'|format(contract.anniversary_day, contract.anniversary_month) }}</p>
|
||||
<form method="post" action="{{ url_for('c4.close_contract', contract_id=contract.id) }}" class="mb-3"><input type="hidden" name="csrf_token" value="{{ csrf_token() }}"><button class="btn btn-outline-danger btn-sm">Clore le contrat</button></form>
|
||||
{% for period in periods %}{% set u=usage[period.id] %}{% set p=projections[period.id] %}
|
||||
<section class="card mb-3"><div class="card-header">Période {{ period.start_date }} → {{ period.end_date }}</div><div class="card-body"><div class="row"><div class="col-md-6"><strong>N&B</strong><br>{{ '%.0f'|format(u.bw) }}{% if period.quota_bw is not none %} / {{ period.quota_bw }}{% else %} — sans quota{% endif %}<small class="d-block">Projection : {{ '%.0f'|format(p.projection.bw) if p.projection.bw is not none else 'indisponible' }}</small></div><div class="col-md-6"><strong>Couleur</strong><br>{{ '%.0f'|format(u.color) }}{% if period.quota_color is not none %} / {{ period.quota_color }}{% else %} — sans quota{% endif %}<small class="d-block">Projection : {{ '%.0f'|format(p.projection.color) if p.projection.color is not none else 'indisponible' }}</small></div></div><small>Machines prises en compte : {{ u.machines }} · qualité : {{ u.quality }}{% if p.confidence == 'LOW' %} · projection à faible confiance{% endif %}</small></div></section>
|
||||
{% endfor %}
|
||||
<h2 class="h5">Machines rattachées</h2><ul>{% for a in contract.assignments %}<li><a href="{{ url_for('c4.equipment_detail', equipment_id=a.equipment_id) }}">{{ a.equipment.name }}</a> — {{ a.entry_date }}{% if a.exit_date %} → {{ a.exit_date }}{% endif %}</li>{% else %}<li>Aucune machine.</li>{% endfor %}</ul>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
|||
3
app_new/c4/templates/c4/equipment_detail.html
Normal file
3
app_new/c4/templates/c4/equipment_detail.html
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{% extends "base.html" %}
|
||||
{% block title %}{{ equipment.name }} — C4{% endblock %}
|
||||
{% block content %}<div class="container-fluid"><h1 class="h4">{{ equipment.name }}</h1><div class="card mb-3"><div class="card-body"><div class="row"><div class="col-md-3"><strong>Type</strong><br>{{ equipment.device_type or '—' }}</div><div class="col-md-3"><strong>Fabricant / modèle</strong><br>{{ equipment.manufacturer or '—' }} / {{ equipment.model_reference or '—' }}</div><div class="col-md-3"><strong>N° de série</strong><br>{{ equipment.serial_number or '—' }}</div><div class="col-md-3"><strong>Référence fournisseur</strong><br>{{ equipment.supplier_reference or '—' }}</div><div class="col-md-3 mt-3"><strong>IP / hostname</strong><br>{{ equipment.ip_address or '—' }} / {{ equipment.hostname or '—' }}</div><div class="col-md-3 mt-3"><strong>MAC</strong><br>{{ equipment.mac_address or '—' }}</div><div class="col-md-6 mt-3"><strong>Emplacement</strong><br>{{ equipment.full_path }}</div></div></div></div><h2 class="h5">Contrats</h2><ul>{% for assignment in assignments %}<li><a href="{{ url_for('c4.contract_detail', contract_id=assignment.contract_id) }}">{{ assignment.contract.name }}</a> — {{ assignment.entry_date }}{% if assignment.exit_date %} → {{ assignment.exit_date }}{% endif %}</li>{% else %}<li>Aucun contrat.</li>{% endfor %}</ul><h2 class="h5">Consommables compatibles</h2><ul>{% for link in links %}<li><a href="{{ url_for('c4.consumable_detail', consumable_id=link.consumable_id) }}">{{ link.consumable.name }}</a> — stock {{ link.consumable.quantity }}</li>{% else %}<li>Aucun consommable.</li>{% endfor %}</ul><h2 class="h5">Compteurs</h2><ul>{% for meter in equipment.meters %}<li>{{ meter.name }} — {{ meter.current_value }} {{ meter.unit }}</li>{% else %}<li>Aucun compteur.</li>{% endfor %}</ul></div>{% endblock %}
|
||||
Loading…
Reference in a new issue