Part-DB-server/templates/projects/info/_info.html.twig
MayNiklas 82e55bc83d Add build price summary to project info tab
Displays the total BOM price for N builds on the project info page,
using the existing price-tier logic from PricedetailHelper. The user
can adjust the number of builds via a small form; the unit price is
also shown when N > 1.

New backend:
- ProjectBuildHelper gains calculateTotalBuildPrice(),
  calculateUnitBuildPrice(), roundedTotalBuildPrice(), and
  roundedUnitBuildPrice() — bulk-order quantities are factored in so
  that price tiers apply correctly across N builds.
- ProjectController::info() now reads ?n= and passes number_of_builds
  to the template.

Template (_info.html.twig):
- Adds price badge (hidden when no pricing data is available).
- Adds number-of-builds form that reloads the info page.
2026-04-15 12:38:06 +02:00

103 lines
5 KiB
Twig

{% import "helper.twig" as helper %}
<div class="row mt-2">
<div class="col-md-8">
<div class="row">
<div class="col-md-3 col-lg-4 col-4 mt-auto mb-auto">
{% if project.masterPictureAttachment %}
<a href="{{ entity_url(project.masterPictureAttachment, 'file_view') }}" data-turbo="false" target="_blank" rel="noopener">
<img class="d-block w-100 img-fluid img-thumbnail bg-body-tertiary part-info-image" src="{{ entity_url(project.masterPictureAttachment, 'file_view') }}" alt="">
</a>
{% else %}
<img src="{{ asset('img/part_placeholder.svg') }}" class="img-fluid img-thumbnail bg-body-tertiary mb-2 " alt="Part main image" height="300" width="300">
{% endif %}
</div>
<div class="col-md-9 col-lg-8 col-7">
<h3 class="w-fit" title="{% trans %}name.label{% endtrans %}">{{ project.name }}
{# You need edit permission to use the edit button #}
{% if is_granted('edit', project) %}
<a href="{{ entity_url(project, 'edit') }}"><i class="fas fa-fw fa-sm fa-edit"></i></a>
{% endif %}
</h3>
<h6 class="text-muted w-fit" title="{% trans %}description.label{% endtrans %}"><span>{{ project.description|format_markdown(true) }}</span></h6>
{% if project.buildPart %}
<h6>{% trans %}project.edit.associated_build_part{% endtrans %}:</h6>
<a href="{{ entity_url(project.buildPart) }}">{{ project.buildPart.name }}</a>
{% endif %}
</div>
</div>
</div>
<div class="col-md-4"> {# Sidebar panel with infos about last creation date, etc. #}
<div class="mb-3">
<span class="text-muted" title="{% trans %}lastModified{% endtrans %}">
<i class="fas fa-history fa-fw"></i> {{ helper.date_user_combination(project, true) }}
</span>
<br>
<span class="text-muted mt-1" title="{% trans %}createdAt{% endtrans %}">
<i class="fas fa-calendar-plus fa-fw"></i> {{ helper.date_user_combination(project, false) }}
</span>
</div>
<div class="mt-1">
<h6>
{{ helper.project_status_to_badge(project.status) }}
</h6>
</div>
<div class="mt-1">
<h6>
<span class="badge badge-primary bg-primary">
<i class="fa-solid fa-list-check fa-fw"></i>
{{ project.bomEntries | length }}
{% trans %}project.info.bom_entries_count{% endtrans %}
</span>
</h6>
</div>
{% set n = number_of_builds ?? 1 %}
{% set total_build_price = buildHelper.roundedTotalBuildPrice(project, n, app.user.currency ?? null) %}
{% set unit_build_price = buildHelper.roundedUnitBuildPrice(project, n, app.user.currency ?? null) %}
{% if total_build_price is not null %}
<div class="mt-1">
<h6>
<span class="badge badge-primary bg-success">
<i class="fa-solid fa-money-bill-wave fa-fw"></i>
{% trans %}project.info.total_build_price{% endtrans %}:
{{ total_build_price | format_money(app.user.currency ?? null, 2) }}
{% if n > 1 and unit_build_price is not null %}
<span class="ms-1">
({% trans %}project.info.per_unit_price{% endtrans %}: {{ unit_build_price | format_money(app.user.currency ?? null, 2) }})
</span>
{% endif %}
</span>
</h6>
</div>
{% endif %}
<form method="get" action="{{ path('project_info', {'id': project.id}) }}" class="mt-2">
<div class="input-group input-group-sm">
<span class="input-group-text">{% trans %}project.builds.number_of_builds{% endtrans %}</span>
<input type="number" min="1" class="form-control" name="n" required value="{{ n }}">
<button class="btn btn-outline-secondary" type="submit">{% trans %}project.build.btn_build{% endtrans %}</button>
</div>
</form>
{% if project.children is not empty %}
<div class="mt-1">
<h6>
<span class="badge badge-primary bg-secondary">
<i class="fa-solid fa-folder-tree fa-fw"></i>
{{ project.children | length }}
{% trans %}project.info.sub_projects_count{% endtrans %}
</span>
</h6>
</div>
{% endif %}
</div>
{% if project.comment is not empty %}
<div class="col-12 mt-2">
<h5>{% trans %}comment.label{% endtrans %}:</h5>
{{ project.comment|format_markdown }}
</div>
{% endif %}
</div>