Allow to set stocktake date for part lots

This commit is contained in:
Jan Böhmer 2026-02-10 22:23:54 +01:00
parent e5231e29f2
commit 2f9601364e
6 changed files with 53 additions and 25 deletions

View file

@ -68,6 +68,9 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co
move:
label: "perm.parts_stock.move"
apiTokenRole: ROLE_API_EDIT
stocktake:
label: "perm.parts_stock.stocktake"
apiTokenRole: ROLE_API_EDIT
storelocations: &PART_CONTAINING

View file

@ -31,6 +31,7 @@ use App\Form\Type\StructuralEntityType;
use App\Form\Type\UserSelectType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
@ -110,6 +111,14 @@ class PartLotType extends AbstractType
//Do not remove whitespace chars on the beginning and end of the string
'trim' => false,
]);
$builder->add('last_stocktake_at', DateTimeType::class, [
'label' => 'part_lot.edit.last_stocktake_at',
'widget' => 'single_text',
'disabled' => !$this->security->isGranted('@parts_stock.stocktake'),
'required' => false,
'empty_data' => null,
]);
}
public function configureOptions(OptionsResolver $resolver): void

View file

@ -58,13 +58,13 @@ final class PartLotVoter extends Voter
{
}
protected const ALLOWED_PERMS = ['read', 'edit', 'create', 'delete', 'show_history', 'revert_element', 'withdraw', 'add', 'move'];
protected const ALLOWED_PERMS = ['read', 'edit', 'create', 'delete', 'show_history', 'revert_element', 'withdraw', 'add', 'move', 'stocktake'];
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token, ?Vote $vote = null): bool
{
$user = $this->helper->resolveUser($token);
if (in_array($attribute, ['withdraw', 'add', 'move'], true))
if (in_array($attribute, ['withdraw', 'add', 'move', 'stocktake'], true))
{
$base_permission = $this->helper->isGranted($token, 'parts_stock', $attribute, $vote);

View file

@ -110,6 +110,7 @@
{{ form_row(form.comment) }}
{{ form_row(form.owner) }}
{{ form_row(form.user_barcode) }}
{{ form_row(form.last_stocktake_at) }}
</div>
</td>
<td>

View file

@ -19,53 +19,56 @@
<tbody>
{% for lot in part.partLots %}
{# @var lot App\Entity\Parts\PartLot #}
<tr {% if lot.id == highlightLotId %}class="table-primary row-highlight row-pulse"{% endif %}>
<td>{{ lot.description }}</td>
<td>
{% if lot.storageLocation %}
{{ helper.structural_entity_link(lot.storageLocation) }}
{% else %}
<span class="badge rounded-pill bg-warning">
<span class="badge rounded-pill text-bg-warning">
<i class="fas fa-question-circle fa-fw"></i> {% trans %}part_lots.location_unknown{% endtrans %}
</span>
{% endif %}
</td>
<td>
{% if lot.instockUnknown %}
<span class="badge rounded-pill bg-warning">
<span class="badge rounded-pill text-bg-warning">
<i class="fas fa-question-circle fa-fw"></i> {% trans %}part_lots.instock_unknown{% endtrans %}
</span>
{% else %}
{{ lot.amount | format_amount(part.partUnit, {'decimals': 5}) }}
{% endif %}
</td>
<td>
<h6>
{% if lot.owner %}
<span class="badge bg-body-tertiary mb-1" title="{% trans %}part_lot.owner{% endtrans %}">
<td class="d-flex flex-column align-items-start">
{% if lot.owner %}
<span class="badge text-bg-light mb-1" title="{% trans %}part_lot.owner{% endtrans %}">
{{ helper.user_icon_link(lot.owner) }}
</span><br>
{% endif %}
{% if lot.expirationDate %}
<span class="badge bg-info mb-1" title="{% trans %}part_lots.expiration_date{% endtrans %}">
</span>
{% endif %}
{% if lot.expirationDate %}
<span class="badge text-bg-info mb-1" title="{% trans %}part_lots.expiration_date{% endtrans %}">
<i class="fas fa-calendar-alt fa-fw"></i> {{ lot.expirationDate | format_date() }}<br>
</span>
{% endif %}
{% if lot.expired %}
<br>
<span class="badge bg-warning mb-1">
{% endif %}
{% if lot.expired %}
<span class="badge text-bg-warning mb-1">
<i class="fas fa-exclamation-circle fa-fw"></i>
{% trans %}part_lots.is_expired{% endtrans %}
</span>
{% endif %}
{% if lot.needsRefill %}
<br>
<span class="badge bg-warning mb-1">
<i class="fas fa-dolly fa-fw"></i>
{% trans %}part_lots.need_refill{% endtrans %}
</span>
{% endif %}
</h6>
{% endif %}
{% if lot.needsRefill %}
<span class="badge text-bg-warning mb-1">
<i class="fas fa-dolly fa-fw"></i>
{% trans %}part_lots.need_refill{% endtrans %}
</span>
{% endif %}
{% if lot.lastStocktakeAt %}
<span class="badge text-bg-secondary" title="{% trans %}part_lot.edit.last_stocktake_at{% endtrans %}">
<i class="fas fa-clipboard-check fa-fw"></i>
{{ lot.lastStocktakeAt | format_datetime("short") }}
</span>
{% endif %}
</td>
<td>
<div class="btn-group" role="group">

View file

@ -12467,5 +12467,17 @@ Buerklin-API Authentication server:
<target>The default value for newly created purchase infos, if prices include VAT or not.</target>
</segment>
</unit>
<unit id="heWSnAH" name="part_lot.edit.last_stocktake_at">
<segment>
<source>part_lot.edit.last_stocktake_at</source>
<target>Last stocktake</target>
</segment>
</unit>
<unit id=".LP93kG" name="perm.parts_stock.stocktake">
<segment>
<source>perm.parts_stock.stocktake</source>
<target>Stocktake</target>
</segment>
</unit>
</file>
</xliff>