Benutzerdefinierten Bauteilstatus einführen

This commit is contained in:
Marcel Diegelmann 2025-03-24 15:15:15 +01:00
parent 0dc7dbdb03
commit ee54687f9d
56 changed files with 1312 additions and 31 deletions

View file

@ -24,7 +24,7 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co
label: "perm.read"
# If a part can be read by a user, he can also see all the datastructures (except devices)
alsoSet: ['storelocations.read', 'footprints.read', 'categories.read', 'suppliers.read', 'manufacturers.read',
'currencies.read', 'attachment_types.read', 'measurement_units.read']
'currencies.read', 'attachment_types.read', 'measurement_units.read', 'part_custom_states.read']
apiTokenRole: ROLE_API_READ_ONLY
edit:
label: "perm.edit"
@ -137,6 +137,10 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co
<<: *PART_CONTAINING
label: "perm.measurement_units"
part_custom_states:
<<: *PART_CONTAINING
label: "perm.part_custom_states"
tools:
label: "perm.part.tools"
operations:

View file

@ -142,7 +142,7 @@ bundled with Part-DB. Set `DATABASE_MYSQL_SSL_VERIFY_CERT` if you want to accept
* `TABLE_PARTS_DEFAULT_COLUMNS`: The columns in parts tables, which are visible by default (when loading table for first
time).
Also specify the default order of the columns. This is a comma separated list of column names. Available columns
are: `name`, `id`, `ipn`, `description`, `category`, `footprint`, `manufacturer`, `storage_location`, `amount`, `minamount`, `partUnit`, `addedDate`, `lastModified`, `needs_review`, `favorite`, `manufacturing_status`, `manufacturer_product_number`, `mass`, `tags`, `attachments`, `edit`.
are: `name`, `id`, `ipn`, `description`, `category`, `footprint`, `manufacturer`, `storage_location`, `amount`, `minamount`, `partUnit`, `partCustomState`, `addedDate`, `lastModified`, `needs_review`, `favorite`, `manufacturing_status`, `manufacturer_product_number`, `mass`, `tags`, `attachments`, `edit`.
* `TABLE_ASSEMBLIES_DEFAULT_COLUMNS`: The columns in assemblies tables, which are visible by default (when loading table for first time).
Also specify the default order of the columns. This is a comma separated list of column names. Available columns
are: `name`, `id`, `ipn`, `description`, `referencedAssemblies`, `edit`, `addedDate`, `lastModified`.

View file

@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
final class Version20250321075747 extends AbstractMigration
{
public function up(Schema $schema): void
{
$this->addSql('CREATE TABLE `part_custom_states` (id INT AUTO_INCREMENT NOT NULL, parent_id INT DEFAULT NULL, name VARCHAR(255) NOT NULL, comment LONGTEXT NOT NULL, not_selectable TINYINT(1) NOT NULL, alternative_names LONGTEXT DEFAULT NULL, last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, INDEX IDX_F552745D727ACA70 (parent_id), INDEX part_custom_state_name (name), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci`');
$this->addSql('ALTER TABLE `part_custom_states` ADD CONSTRAINT FK_F552745D727ACA70 FOREIGN KEY (parent_id) REFERENCES `part_custom_states` (id)');
}
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE `part_custom_states` DROP FOREIGN KEY FK_F552745D727ACA70');
$this->addSql('DROP TABLE `part_custom_states`');
}
}

View file

@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
final class Version20250321141740 extends AbstractMigration
{
public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE parts ADD id_part_custom_state INT DEFAULT NULL AFTER id_part_unit');
$this->addSql('ALTER TABLE parts ADD CONSTRAINT FK_6940A7FEA3ED1215 FOREIGN KEY (id_part_custom_state) REFERENCES `part_custom_states` (id)');
$this->addSql('CREATE INDEX IDX_6940A7FEA3ED1215 ON parts (id_part_custom_state)');
}
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE `parts` DROP FOREIGN KEY FK_6940A7FEA3ED1215');
$this->addSql('DROP INDEX IDX_6940A7FEA3ED1215 ON `parts`');
$this->addSql('ALTER TABLE `parts` DROP id_part_custom_state');
}
}

View file

@ -121,6 +121,11 @@ class ImportPartKeeprCommand extends Command
$count = $this->datastructureImporter->importPartUnits($data);
$io->success('Imported '.$count.' measurement units.');
//Import the custom states
$io->info('Importing custom states...');
$count = $this->datastructureImporter->importPartCustomStates($data);
$io->success('Imported '.$count.' custom states.');
//Import manufacturers
$io->info('Importing manufacturers...');
$count = $this->datastructureImporter->importManufacturers($data);

View file

@ -233,13 +233,6 @@ abstract class BaseAdminController extends AbstractController
$repo = $this->entityManager->getRepository($this->entity_class);
$showParameters = true;
if ($this instanceof AssemblyAdminController) {
//currently not needed for assemblies
$showParameters = false;
}
return $this->render($this->twig_template, [
'entity' => $entity,
'form' => $form,
@ -249,7 +242,7 @@ abstract class BaseAdminController extends AbstractController
'timeTravel' => $timeTravel_timestamp,
'repo' => $repo,
'partsContainingElement' => $repo instanceof PartsContainingRepositoryInterface,
'showParameters' => $showParameters,
'showParameters' => !($this instanceof PartCustomStateController),
]);
}
@ -403,20 +396,13 @@ abstract class BaseAdminController extends AbstractController
}
}
$showParameters = true;
if ($this instanceof AssemblyAdminController) {
//currently not needed for assemblies
$showParameters = false;
}
return $this->render($this->twig_template, [
'entity' => $new_entity,
'form' => $form,
'import_form' => $import_form,
'mass_creation_form' => $mass_creation_form,
'route_base' => $this->route_base,
'showParameters' => $showParameters,
'showParameters' => !($this instanceof PartCustomStateController),
]);
}

View file

@ -41,6 +41,7 @@ use App\Entity\Parts\Category;
use App\Entity\Parts\Footprint;
use App\Entity\Parts\Manufacturer;
use App\Entity\Parts\MeasurementUnit;
use App\Entity\Parts\PartCustomState;
use App\Entity\Parts\PartLot;
use App\Entity\Parts\StorageLocation;
use App\Entity\Parts\Supplier;
@ -86,6 +87,7 @@ class PartFilter implements FilterInterface
public readonly EntityConstraint $lotOwner;
public readonly EntityConstraint $measurementUnit;
public readonly EntityConstraint $partCustomState;
public readonly TextConstraint $manufacturer_product_url;
public readonly TextConstraint $manufacturer_product_number;
public readonly IntConstraint $attachmentsCount;
@ -128,6 +130,7 @@ class PartFilter implements FilterInterface
$this->favorite = new BooleanConstraint('part.favorite');
$this->needsReview = new BooleanConstraint('part.needs_review');
$this->measurementUnit = new EntityConstraint($nodesListBuilder, MeasurementUnit::class, 'part.partUnit');
$this->partCustomState = new EntityConstraint($nodesListBuilder, PartCustomState::class, 'part.partCustomState');
$this->mass = new NumberConstraint('part.mass');
$this->dbId = new IntConstraint('part.id');
$this->ipn = new TextConstraint('part.ipn');

View file

@ -175,6 +175,19 @@ final class PartsDataTable implements DataTableTypeInterface
return $tmp;
}
])
->add('partCustomState', TextColumn::class, [
'label' => $this->translator->trans('part.table.partCustomState'),
'orderField' => 'NATSORT(_partCustomState.name)',
'render' => function($value, Part $context): string {
$partCustomState = $context->getPartCustomState();
if ($partCustomState === null) {
return '';
}
return htmlspecialchars($partCustomState->getName());
}
])
->add('addedDate', LocaleDateTimeColumn::class, [
'label' => $this->translator->trans('part.table.addedDate'),
])
@ -338,6 +351,7 @@ final class PartsDataTable implements DataTableTypeInterface
->addSelect('footprint')
->addSelect('manufacturer')
->addSelect('partUnit')
->addSelect('partCustomState')
->addSelect('master_picture_attachment')
->addSelect('footprint_attachment')
->addSelect('partLots')
@ -356,6 +370,7 @@ final class PartsDataTable implements DataTableTypeInterface
->leftJoin('orderdetails.supplier', 'suppliers')
->leftJoin('part.attachments', 'attachments')
->leftJoin('part.partUnit', 'partUnit')
->leftJoin('part.partCustomState', 'partCustomState')
->leftJoin('part.parameters', 'parameters')
->where('part.id IN (:ids)')
->setParameter('ids', $ids)
@ -373,6 +388,7 @@ final class PartsDataTable implements DataTableTypeInterface
->addGroupBy('suppliers')
->addGroupBy('attachments')
->addGroupBy('partUnit')
->addGroupBy('partCustomState')
->addGroupBy('parameters');
//Get the results in the same order as the IDs were passed
@ -444,6 +460,10 @@ final class PartsDataTable implements DataTableTypeInterface
$builder->leftJoin('part.partUnit', '_partUnit');
$builder->addGroupBy('_partUnit');
}
if (str_contains($dql, '_partCustomState')) {
$builder->leftJoin('part.partCustomState', '_partCustomState');
$builder->addGroupBy('_partCustomState');
}
if (str_contains($dql, '_parameters')) {
$builder->leftJoin('part.parameters', '_parameters');
//Do not group by many-to-* relations, as it would restrict the COUNT having clauses to be maximum 1

View file

@ -97,7 +97,7 @@ use function in_array;
#[DiscriminatorMap(typeProperty: '_type', mapping: self::API_DISCRIMINATOR_MAP)]
abstract class Attachment extends AbstractNamedDBElement
{
private const ORM_DISCRIMINATOR_MAP = ['Part' => PartAttachment::class, 'Device' => ProjectAttachment::class, 'Assembly' => AssemblyAttachment::class,
private const ORM_DISCRIMINATOR_MAP = ['Part' => PartAttachment::class, 'PartCustomState' => PartCustomStateAttachment::class, 'Device' => ProjectAttachment::class, 'Assembly' => AssemblyAttachment::class,
'AttachmentType' => AttachmentTypeAttachment::class,
'Category' => CategoryAttachment::class, 'Footprint' => FootprintAttachment::class, 'Manufacturer' => ManufacturerAttachment::class,
'Currency' => CurrencyAttachment::class, 'Group' => GroupAttachment::class, 'MeasurementUnit' => MeasurementUnitAttachment::class,
@ -107,7 +107,7 @@ abstract class Attachment extends AbstractNamedDBElement
/*
* The discriminator map used for API platform. The key should be the same as the api platform short type (the @type JSONLD field).
*/
private const API_DISCRIMINATOR_MAP = ["Part" => PartAttachment::class, "Project" => ProjectAttachment::class, "Assembly" => AssemblyAttachment::class,
private const API_DISCRIMINATOR_MAP = ["Part" => PartAttachment::class, "PartCustomState" => PartCustomStateAttachment::class, "Project" => ProjectAttachment::class, "Assembly" => AssemblyAttachment::class,
"AttachmentType" => AttachmentTypeAttachment::class,
"Category" => CategoryAttachment::class, "Footprint" => FootprintAttachment::class, "Manufacturer" => ManufacturerAttachment::class,
"Currency" => CurrencyAttachment::class, "Group" => GroupAttachment::class, "MeasurementUnit" => MeasurementUnitAttachment::class,
@ -551,8 +551,8 @@ abstract class Attachment extends AbstractNamedDBElement
*/
#[Groups(['attachment:write'])]
#[SerializedName('url')]
#[ApiProperty(description: 'Set the path of the attachment here.
Provide either an external URL, a path to a builtin file (like %FOOTPRINTS%/Active/ICs/IC_DFS.png) or an empty
#[ApiProperty(description: 'Set the path of the attachment here.
Provide either an external URL, a path to a builtin file (like %FOOTPRINTS%/Active/ICs/IC_DFS.png) or an empty
string if the attachment has an internal file associated and you\'d like to reset the external source.
If you set a new (nonempty) file path any associated internal file will be removed!')]
public function setURL(?string $url): self

View file

@ -0,0 +1,45 @@
<?php
/**
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2022 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace App\Entity\Attachments;
use App\Entity\Parts\PartCustomState;
use App\Serializer\APIPlatform\OverrideClassDenormalizer;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Serializer\Attribute\Context;
/**
* An attachment attached to a part custom state element.
* @extends Attachment<PartCustomState>
*/
#[UniqueEntity(['name', 'attachment_type', 'element'])]
#[ORM\Entity]
class PartCustomStateAttachment extends Attachment
{
final public const ALLOWED_ELEMENT_CLASS = PartCustomState::class;
#[ORM\ManyToOne(targetEntity: PartCustomState::class, inversedBy: 'attachments')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
#[Context(denormalizationContext: [OverrideClassDenormalizer::CONTEXT_KEY => self::ALLOWED_ELEMENT_CLASS])]
protected ?AttachmentContainingDBElement $element = null;
}

View file

@ -36,6 +36,7 @@ use App\Entity\Attachments\LabelAttachment;
use App\Entity\Attachments\ManufacturerAttachment;
use App\Entity\Attachments\MeasurementUnitAttachment;
use App\Entity\Attachments\PartAttachment;
use App\Entity\Attachments\PartCustomStateAttachment;
use App\Entity\Attachments\ProjectAttachment;
use App\Entity\Attachments\StorageLocationAttachment;
use App\Entity\Attachments\SupplierAttachment;
@ -43,6 +44,7 @@ use App\Entity\Attachments\UserAttachment;
use App\Entity\Parameters\AbstractParameter;
use App\Entity\Parts\Category;
use App\Entity\PriceInformations\Pricedetail;
use App\Entity\Parts\PartCustomState;
use App\Entity\ProjectSystem\Project;
use App\Entity\ProjectSystem\ProjectBOMEntry;
use App\Entity\Parts\Footprint;
@ -71,7 +73,41 @@ use Symfony\Component\Serializer\Annotation\Groups;
* Every database table which are managed with this class (or a subclass of it)
* must have the table row "id"!! The ID is the unique key to identify the elements.
*/
#[DiscriminatorMap(typeProperty: 'type', mapping: ['attachment_type' => AttachmentType::class, 'attachment' => Attachment::class, 'attachment_type_attachment' => AttachmentTypeAttachment::class, 'category_attachment' => CategoryAttachment::class, 'currency_attachment' => CurrencyAttachment::class, 'footprint_attachment' => FootprintAttachment::class, 'group_attachment' => GroupAttachment::class, 'label_attachment' => LabelAttachment::class, 'manufacturer_attachment' => ManufacturerAttachment::class, 'measurement_unit_attachment' => MeasurementUnitAttachment::class, 'part_attachment' => PartAttachment::class, 'project_attachment' => ProjectAttachment::class, 'assembly_attachment' => AssemblyAttachment::class, 'storelocation_attachment' => StorageLocationAttachment::class, 'supplier_attachment' => SupplierAttachment::class, 'user_attachment' => UserAttachment::class, 'category' => Category::class, 'project' => Project::class, 'project_bom_entry' => ProjectBOMEntry::class, 'assembly' => Assembly::class, 'assembly_bom_entry' => AssemblyBOMEntry::class, 'footprint' => Footprint::class, 'group' => Group::class, 'manufacturer' => Manufacturer::class, 'orderdetail' => Orderdetail::class, 'part' => Part::class, 'pricedetail' => Pricedetail::class, 'storelocation' => StorageLocation::class, 'part_lot' => PartLot::class, 'currency' => Currency::class, 'measurement_unit' => MeasurementUnit::class, 'parameter' => AbstractParameter::class, 'supplier' => Supplier::class, 'user' => User::class])]
#[DiscriminatorMap(typeProperty: 'type', mapping: [
'attachment_type' => AttachmentType::class,
'attachment' => Attachment::class,
'attachment_type_attachment' => AttachmentTypeAttachment::class,
'category_attachment' => CategoryAttachment::class,
'currency_attachment' => CurrencyAttachment::class,
'footprint_attachment' => FootprintAttachment::class,
'group_attachment' => GroupAttachment::class,
'label_attachment' => LabelAttachment::class,
'manufacturer_attachment' => ManufacturerAttachment::class,
'measurement_unit_attachment' => MeasurementUnitAttachment::class,
'part_attachment' => PartAttachment::class,
'part_custom_state_attachment' => PartCustomStateAttachment::class,
'project_attachment' => ProjectAttachment::class,
'storelocation_attachment' => StorageLocationAttachment::class,
'supplier_attachment' => SupplierAttachment::class,
'user_attachment' => UserAttachment::class,
'category' => Category::class,
'project' => Project::class,
'project_bom_entry' => ProjectBOMEntry::class,
'footprint' => Footprint::class,
'group' => Group::class,
'manufacturer' => Manufacturer::class,
'orderdetail' => Orderdetail::class,
'part' => Part::class,
'part_custom_state' => PartCustomState::class,
'pricedetail' => Pricedetail::class,
'storelocation' => StorageLocation::class,
'part_lot' => PartLot::class,
'currency' => Currency::class,
'measurement_unit' => MeasurementUnit::class,
'parameter' => AbstractParameter::class,
'supplier' => Supplier::class,
'user' => User::class]
)]
#[ORM\MappedSuperclass(repositoryClass: DBElementRepository::class)]
abstract class AbstractDBElement implements JsonSerializable
{

View file

@ -48,6 +48,7 @@ use App\Entity\Attachments\AttachmentType;
use App\Entity\Attachments\AttachmentTypeAttachment;
use App\Entity\Attachments\CategoryAttachment;
use App\Entity\Attachments\CurrencyAttachment;
use App\Entity\Attachments\PartCustomStateAttachment;
use App\Entity\Attachments\ProjectAttachment;
use App\Entity\Attachments\FootprintAttachment;
use App\Entity\Attachments\GroupAttachment;
@ -60,6 +61,8 @@ use App\Entity\Attachments\UserAttachment;
use App\Entity\Base\AbstractDBElement;
use App\Entity\Contracts\LogWithEventUndoInterface;
use App\Entity\Contracts\NamedElementInterface;
use App\Entity\Parameters\PartCustomStateParameter;
use App\Entity\Parts\PartCustomState;
use App\Entity\Parameters\AssemblyParameter;
use App\Entity\ProjectSystem\Project;
use App\Entity\Parameters\AbstractParameter;
@ -162,6 +165,7 @@ class CollectionElementDeleted extends AbstractLogEntry implements LogWithEventU
Part::class => PartParameter::class,
StorageLocation::class => StorageLocationParameter::class,
Supplier::class => SupplierParameter::class,
PartCustomState::class => PartCustomStateParameter::class,
default => throw new \RuntimeException('Unknown target class for parameter: '.$this->getTargetClass()),
};
}
@ -178,6 +182,7 @@ class CollectionElementDeleted extends AbstractLogEntry implements LogWithEventU
Manufacturer::class => ManufacturerAttachment::class,
MeasurementUnit::class => MeasurementUnitAttachment::class,
Part::class => PartAttachment::class,
PartCustomState::class => PartCustomStateAttachment::class,
StorageLocation::class => StorageLocationAttachment::class,
Supplier::class => SupplierAttachment::class,
User::class => UserAttachment::class,

View file

@ -34,6 +34,7 @@ use App\Entity\Parts\Manufacturer;
use App\Entity\Parts\MeasurementUnit;
use App\Entity\Parts\Part;
use App\Entity\Parts\PartAssociation;
use App\Entity\Parts\PartCustomState;
use App\Entity\Parts\PartLot;
use App\Entity\Parts\StorageLocation;
use App\Entity\Parts\Supplier;
@ -75,6 +76,7 @@ enum LogTargetType: int
case BULK_INFO_PROVIDER_IMPORT_JOB_PART = 22;
case ASSEMBLY = 23;
case ASSEMBLY_BOM_ENTRY = 24;
case PART_CUSTOM_STATE = 25;
/**
* Returns the class name of the target type or null if the target type is NONE.
@ -108,6 +110,7 @@ enum LogTargetType: int
self::PART_ASSOCIATION => PartAssociation::class,
self::BULK_INFO_PROVIDER_IMPORT_JOB => BulkInfoProviderImportJob::class,
self::BULK_INFO_PROVIDER_IMPORT_JOB_PART => BulkInfoProviderImportJobPart::class,
self::PART_CUSTOM_STATE => PartCustomState::class
};
}

View file

@ -73,7 +73,8 @@ use function sprintf;
#[ORM\DiscriminatorMap([0 => CategoryParameter::class, 1 => CurrencyParameter::class, 2 => ProjectParameter::class,
3 => FootprintParameter::class, 4 => GroupParameter::class, 5 => ManufacturerParameter::class,
6 => MeasurementUnitParameter::class, 7 => PartParameter::class, 8 => StorageLocationParameter::class,
9 => SupplierParameter::class, 10 => AttachmentTypeParameter::class, 11 => AssemblyParameter::class])]
9 => SupplierParameter::class, 10 => AttachmentTypeParameter::class, 11 => AssemblyParameter::class,
12 => PartCustomStateParameter::class])]
#[ORM\Table('parameters')]
#[ORM\Index(columns: ['name'], name: 'parameter_name_idx')]
#[ORM\Index(columns: ['param_group'], name: 'parameter_group_idx')]
@ -105,7 +106,7 @@ abstract class AbstractParameter extends AbstractNamedDBElement implements Uniqu
"AttachmentType" => AttachmentTypeParameter::class, "Category" => CategoryParameter::class, "Currency" => CurrencyParameter::class,
"Project" => ProjectParameter::class, "Assembly" => AssemblyParameter::class, "Footprint" => FootprintParameter::class, "Group" => GroupParameter::class,
"Manufacturer" => ManufacturerParameter::class, "MeasurementUnit" => MeasurementUnitParameter::class,
"StorageLocation" => StorageLocationParameter::class, "Supplier" => SupplierParameter::class];
"StorageLocation" => StorageLocationParameter::class, "Supplier" => SupplierParameter::class, "PartCustomState" => PartCustomStateParameter::class];
/**
* @var string The class of the element that can be passed to this attachment. Must be overridden in subclasses.
@ -460,7 +461,7 @@ abstract class AbstractParameter extends AbstractNamedDBElement implements Uniqu
return $str;
}
/**
* Returns the class of the element that is allowed to be associated with this attachment.
* @return string

View file

@ -0,0 +1,65 @@
<?php
/*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2022 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
/**
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2022 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace App\Entity\Parameters;
use App\Entity\Base\AbstractDBElement;
use App\Entity\Parts\PartCustomState;
use App\Repository\ParameterRepository;
use App\Serializer\APIPlatform\OverrideClassDenormalizer;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Serializer\Attribute\Context;
#[UniqueEntity(fields: ['name', 'group', 'element'])]
#[ORM\Entity(repositoryClass: ParameterRepository::class)]
class PartCustomStateParameter extends AbstractParameter
{
final public const ALLOWED_ELEMENT_CLASS = PartCustomState::class;
/**
* @var PartCustomState the element this para is associated with
*/
#[ORM\ManyToOne(targetEntity: PartCustomState::class, inversedBy: 'parameters')]
#[ORM\JoinColumn(name: 'element_id', nullable: false, onDelete: 'CASCADE')]
#[Context(denormalizationContext: [OverrideClassDenormalizer::CONTEXT_KEY => self::ALLOWED_ELEMENT_CLASS])]
protected ?AbstractDBElement $element = null;
}

View file

@ -106,7 +106,7 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
denormalizationContext: ['groups' => ['part:write', 'api:basic:write', 'eda_info:write', 'attachment:write', 'parameter:write'], 'openapi_definition_name' => 'Write'],
)]
#[ApiFilter(PropertyFilter::class)]
#[ApiFilter(EntityFilter::class, properties: ["category", "footprint", "manufacturer", "partUnit"])]
#[ApiFilter(EntityFilter::class, properties: ["category", "footprint", "manufacturer", "partUnit", "partCustomState"])]
#[ApiFilter(PartStoragelocationFilter::class, properties: ["storage_location"])]
#[ApiFilter(LikeFilter::class, properties: ["name", "comment", "description", "ipn", "manufacturer_product_number"])]
#[ApiFilter(TagFilter::class, properties: ["tags"])]

View file

@ -0,0 +1,121 @@
<?php
/**
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2022 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace App\Entity\Parts;
use ApiPlatform\Metadata\ApiProperty;
use App\Entity\Attachments\PartCustomStateAttachment;
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Delete;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Patch;
use ApiPlatform\Metadata\Post;
use ApiPlatform\Serializer\Filter\PropertyFilter;
use App\ApiPlatform\Filter\LikeFilter;
use App\Entity\Base\AbstractPartsContainingDBElement;
use App\Entity\Base\AbstractStructuralDBElement;
use App\Entity\Parameters\PartCustomStateParameter;
use App\Repository\Parts\PartCustomStateRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
/**
* This entity represents a custom part state.
* If an organisation uses Part-DB and has its custom part states, this is useful.
*
* @extends AbstractPartsContainingDBElement<PartCustomStateAttachment,PartCustomStateParameter>
*/
#[ORM\Entity(repositoryClass: PartCustomStateRepository::class)]
#[ORM\Table('`part_custom_states`')]
#[ORM\Index(columns: ['name'], name: 'part_custom_state_name')]
#[ApiResource(
operations: [
new Get(security: 'is_granted("read", object)'),
new GetCollection(security: 'is_granted("@part_custom_states.read")'),
new Post(securityPostDenormalize: 'is_granted("create", object)'),
new Patch(security: 'is_granted("edit", object)'),
new Delete(security: 'is_granted("delete", object)'),
],
normalizationContext: ['groups' => ['part_custom_state:read', 'api:basic:read'], 'openapi_definition_name' => 'Read'],
denormalizationContext: ['groups' => ['part_custom_state:write', 'api:basic:write'], 'openapi_definition_name' => 'Write'],
)]
#[ApiFilter(PropertyFilter::class)]
#[ApiFilter(LikeFilter::class, properties: ["name"])]
#[ApiFilter(DateFilter::class, strategy: DateFilterInterface::EXCLUDE_NULL)]
#[ApiFilter(OrderFilter::class, properties: ['name', 'id', 'addedDate', 'lastModified'])]
class PartCustomState extends AbstractPartsContainingDBElement
{
/**
* @var string The comment info for this element as markdown
*/
#[Groups(['part_custom_state:read', 'part_custom_state:write', 'full', 'import'])]
protected string $comment = '';
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class, cascade: ['persist'])]
#[ORM\OrderBy(['name' => Criteria::ASC])]
protected Collection $children;
#[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')]
#[ORM\JoinColumn(name: 'parent_id')]
#[Groups(['part_custom_state:read', 'part_custom_state:write'])]
#[ApiProperty(readableLink: false, writableLink: false)]
protected ?AbstractStructuralDBElement $parent = null;
/**
* @var Collection<int, PartCustomStateAttachment>
*/
#[Assert\Valid]
#[ORM\OneToMany(targetEntity: PartCustomStateAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => Criteria::ASC])]
#[Groups(['part_custom_state:read', 'part_custom_state:write'])]
protected Collection $attachments;
/** @var Collection<int, PartCustomStateAttachment>
*/
#[Assert\Valid]
#[ORM\OneToMany(mappedBy: 'element', targetEntity: PartCustomStateAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['name' => 'ASC'])]
#[Groups(['part_custom_state:read', 'part_custom_state:write'])]
protected Collection $parameters;
#[Groups(['part_custom_state:read'])]
protected ?\DateTimeImmutable $addedDate = null;
#[Groups(['part_custom_state:read'])]
protected ?\DateTimeImmutable $lastModified = null;
public function __construct()
{
parent::__construct();
$this->children = new ArrayCollection();
$this->attachments = new ArrayCollection();
$this->parameters = new ArrayCollection();
}
}

View file

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace App\Entity\Parts\PartTraits;
use App\Entity\Parts\InfoProviderReference;
use App\Entity\Parts\PartCustomState;
use Doctrine\DBAL\Types\Types;
use App\Entity\Parts\Part;
use Doctrine\ORM\Mapping as ORM;
@ -75,6 +76,14 @@ trait AdvancedPropertyTrait
#[Groups(['full', 'part:read'])]
protected InfoProviderReference $providerReference;
/**
* @var ?PartCustomState the custom state for the part
*/
#[Groups(['extended', 'full', 'import', 'part:read', 'part:write'])]
#[ORM\ManyToOne(targetEntity: PartCustomState::class)]
#[ORM\JoinColumn(name: 'id_part_custom_state')]
protected ?PartCustomState $partCustomState = null;
/**
* Checks if this part is marked, for that it needs further review.
*/
@ -182,7 +191,24 @@ trait AdvancedPropertyTrait
return $this;
}
/**
* Gets the custom part state for the part
* Returns null if no specific part state is set.
*/
public function getPartCustomState(): ?PartCustomState
{
return $this->partCustomState;
}
/**
* Sets the custom part state.
*
* @return $this
*/
public function setPartCustomState(?PartCustomState $partCustomState): self
{
$this->partCustomState = $partCustomState;
return $this;
}
}

View file

@ -0,0 +1,27 @@
<?php
/**
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2022 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace App\Form\AdminPages;
class PartCustomStateAdminForm extends BaseEntityAdminForm
{
}

View file

@ -32,6 +32,7 @@ use App\Entity\Parts\Category;
use App\Entity\Parts\Footprint;
use App\Entity\Parts\Manufacturer;
use App\Entity\Parts\MeasurementUnit;
use App\Entity\Parts\PartCustomState;
use App\Entity\Parts\StorageLocation;
use App\Entity\Parts\Supplier;
use App\Entity\ProjectSystem\Project;
@ -139,6 +140,11 @@ class PartFilterType extends AbstractType
'entity_class' => MeasurementUnit::class
]);
$builder->add('partCustomState', StructuralEntityConstraintType::class, [
'label' => 'part.edit.partCustomState',
'entity_class' => PartCustomState::class
]);
$builder->add('lastModified', DateTimeConstraintType::class, [
'label' => 'lastModified'
]);

View file

@ -30,6 +30,7 @@ use App\Entity\Parts\Manufacturer;
use App\Entity\Parts\ManufacturingStatus;
use App\Entity\Parts\MeasurementUnit;
use App\Entity\Parts\Part;
use App\Entity\Parts\PartCustomState;
use App\Entity\PriceInformations\Orderdetail;
use App\Form\AttachmentFormType;
use App\Form\ParameterType;
@ -175,6 +176,12 @@ class PartBaseType extends AbstractType
'disable_not_selectable' => true,
'label' => 'part.edit.partUnit',
])
->add('partCustomState', StructuralEntityType::class, [
'class' => PartCustomState::class,
'required' => false,
'disable_not_selectable' => true,
'label' => 'part.edit.partCustomState',
])
->add('ipn', TextType::class, [
'required' => false,
'empty_data' => null,

View file

@ -0,0 +1,48 @@
<?php
declare(strict_types=1);
/**
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2022 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace App\Repository\Parts;
use App\Entity\Parts\PartCustomState;
use App\Repository\AbstractPartsContainingRepository;
use InvalidArgumentException;
class PartCustomStateRepository extends AbstractPartsContainingRepository
{
public function getParts(object $element, string $nameOrderDirection = "ASC"): array
{
if (!$element instanceof PartCustomState) {
throw new InvalidArgumentException('$element must be an PartCustomState!');
}
return $this->getPartsByField($element, $nameOrderDirection, 'partUnit');
}
public function getPartsCount(object $element): int
{
if (!$element instanceof PartCustomState) {
throw new InvalidArgumentException('$element must be an PartCustomState!');
}
return $this->getPartsCountByField($element, 'partUnit');
}
}

View file

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace App\Security\Voter;
use App\Entity\Attachments\AssemblyAttachment;
use App\Entity\Attachments\PartCustomStateAttachment;
use App\Services\UserSystem\VoterHelper;
use Symfony\Bundle\SecurityBundle\Security;
use App\Entity\Attachments\AttachmentContainingDBElement;
@ -102,6 +103,8 @@ final class AttachmentVoter extends Voter
$param = 'measurement_units';
} elseif (is_a($subject, PartAttachment::class, true)) {
$param = 'parts';
} elseif (is_a($subject, PartCustomStateAttachment::class, true)) {
$param = 'part_custom_states';
} elseif (is_a($subject, StorageLocationAttachment::class, true)) {
$param = 'storelocations';
} elseif (is_a($subject, SupplierAttachment::class, true)) {

View file

@ -22,6 +22,7 @@ declare(strict_types=1);
*/
namespace App\Security\Voter;
use App\Entity\Parameters\PartCustomStateParameter;
use App\Services\UserSystem\VoterHelper;
use Symfony\Bundle\SecurityBundle\Security;
use App\Entity\Base\AbstractDBElement;
@ -97,6 +98,8 @@ final class ParameterVoter extends Voter
$param = 'measurement_units';
} elseif (is_a($subject, PartParameter::class, true)) {
$param = 'parts';
} elseif (is_a($subject, PartCustomStateParameter::class, true)) {
$param = 'part_custom_states';
} elseif (is_a($subject, StorageLocationParameter::class, true)) {
$param = 'storelocations';
} elseif (is_a($subject, SupplierParameter::class, true)) {

View file

@ -24,6 +24,7 @@ namespace App\Security\Voter;
use App\Entity\AssemblySystem\Assembly;
use App\Entity\Attachments\AttachmentType;
use App\Entity\Parts\PartCustomState;
use App\Entity\ProjectSystem\Project;
use App\Entity\Parts\Category;
use App\Entity\Parts\Footprint;
@ -55,6 +56,7 @@ final class StructureVoter extends Voter
Supplier::class => 'suppliers',
Currency::class => 'currencies',
MeasurementUnit::class => 'measurement_units',
PartCustomState::class => 'part_custom_states',
];
public function __construct(private readonly VoterHelper $helper)

View file

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace App\Services\Attachments;
use App\Entity\Parts\Footprint;
use App\Entity\Parts\PartCustomState;
use App\Entity\ProjectSystem\Project;
use App\Entity\Parts\Category;
use App\Entity\Parts\StorageLocation;
@ -103,6 +104,13 @@ class PartPreviewGenerator
}
}
if ($part->getPartCustomState() instanceof PartCustomState) {
$attachment = $part->getPartCustomState()->getMasterPictureAttachment();
if ($this->isAttachmentValidPicture($attachment)) {
$list[] = $attachment;
}
}
if ($part->getManufacturer() instanceof Manufacturer) {
$attachment = $part->getManufacturer()->getMasterPictureAttachment();
if ($this->isAttachmentValidPicture($attachment)) {

View file

@ -233,6 +233,10 @@ class KiCadHelper
}
$result["fields"]["Part-DB Unit"] = $this->createField($unit);
}
if ($part->getPartCustomState() !== null) {
$customState = $part->getPartCustomState()->getName();
$result["fields"]["Part-DB Custom state"] = $this->createField($customState);
}
if ($part->getMass()) {
$result["fields"]["Mass"] = $this->createField($part->getMass() . ' g');
}

View file

@ -37,6 +37,7 @@ use App\Entity\Parts\Manufacturer;
use App\Entity\Parts\MeasurementUnit;
use App\Entity\Parts\Part;
use App\Entity\Parts\PartAssociation;
use App\Entity\Parts\PartCustomState;
use App\Entity\Parts\PartLot;
use App\Entity\Parts\StorageLocation;
use App\Entity\Parts\Supplier;
@ -87,6 +88,7 @@ class ElementTypeNameGenerator
PartAssociation::class => $this->translator->trans('part_association.label'),
BulkInfoProviderImportJob::class => $this->translator->trans('bulk_info_provider_import_job.label'),
BulkInfoProviderImportJobPart::class => $this->translator->trans('bulk_info_provider_import_job_part.label'),
PartCustomState::class => $this->translator->trans('part_custom_state.label'),
];
}

View file

@ -65,6 +65,7 @@ class PartMerger implements EntityMergerInterface
$this->useOtherValueIfNotNull($target, $other, 'footprint');
$this->useOtherValueIfNotNull($target, $other, 'category');
$this->useOtherValueIfNotNull($target, $other, 'partUnit');
$this->useOtherValueIfNotNull($target, $other, 'partCustomState');
//We assume that the higher value is the correct one for minimum instock
$this->useLargerValue($target, $other, 'minamount');

View file

@ -28,6 +28,7 @@ use App\Entity\Attachments\AttachmentType;
use App\Entity\Attachments\PartAttachment;
use App\Entity\Base\AbstractDBElement;
use App\Entity\Parameters\PartParameter;
use App\Entity\Parts\PartCustomState;
use App\Entity\ProjectSystem\Project;
use App\Entity\LabelSystem\LabelProfile;
use App\Entity\Parts\Category;
@ -109,6 +110,7 @@ class EntityURLGenerator
MeasurementUnit::class => 'measurement_unit_edit',
Group::class => 'group_edit',
LabelProfile::class => 'label_profile_edit',
PartCustomState::class => 'part_custom_state_edit',
];
try {
@ -216,6 +218,7 @@ class EntityURLGenerator
MeasurementUnit::class => 'measurement_unit_edit',
Group::class => 'group_edit',
LabelProfile::class => 'label_profile_edit',
PartCustomState::class => 'part_custom_state_edit',
];
return $this->urlGenerator->generate($this->mapToController($map, $entity), ['id' => $entity->getID()]);
@ -247,6 +250,7 @@ class EntityURLGenerator
MeasurementUnit::class => 'measurement_unit_edit',
Group::class => 'group_edit',
LabelProfile::class => 'label_profile_edit',
PartCustomState::class => 'part_custom_state_edit',
];
return $this->urlGenerator->generate($this->mapToController($map, $entity), ['id' => $entity->getID()]);
@ -279,6 +283,7 @@ class EntityURLGenerator
MeasurementUnit::class => 'measurement_unit_new',
Group::class => 'group_new',
LabelProfile::class => 'label_profile_new',
PartCustomState::class => 'part_custom_state_new',
];
return $this->urlGenerator->generate($this->mapToController($map, $entity));
@ -311,6 +316,7 @@ class EntityURLGenerator
MeasurementUnit::class => 'measurement_unit_clone',
Group::class => 'group_clone',
LabelProfile::class => 'label_profile_clone',
PartCustomState::class => 'part_custom_state_clone',
];
return $this->urlGenerator->generate($this->mapToController($map, $entity), ['id' => $entity->getID()]);
@ -358,6 +364,7 @@ class EntityURLGenerator
MeasurementUnit::class => 'measurement_unit_delete',
Group::class => 'group_delete',
LabelProfile::class => 'label_profile_delete',
PartCustomState::class => 'part_custom_state_delete',
];
return $this->urlGenerator->generate($this->mapToController($map, $entity), ['id' => $entity->getID()]);

View file

@ -29,6 +29,7 @@ use App\Entity\Parts\Category;
use App\Entity\Parts\Footprint;
use App\Entity\Parts\Manufacturer;
use App\Entity\Parts\MeasurementUnit;
use App\Entity\Parts\PartCustomState;
use App\Entity\Parts\StorageLocation;
use App\Entity\Parts\Supplier;
use Doctrine\ORM\EntityManagerInterface;
@ -148,6 +149,26 @@ class PKDatastructureImporter
return is_countable($partunit_data) ? count($partunit_data) : 0;
}
public function importPartCustomStates(array $data): int
{
if (!isset($data['partcustomstate'])) {
throw new \RuntimeException('$data must contain a "partcustomstate" key!');
}
$partCustomStateData = $data['partcustomstate'];
foreach ($partCustomStateData as $partCustomState) {
$customState = new PartCustomState();
$customState->setName($partCustomState['name']);
$this->setIDOfEntity($customState, $partCustomState['id']);
$this->em->persist($customState);
}
$this->em->flush();
return is_countable($partCustomStateData) ? count($partCustomStateData) : 0;
}
public function importCategories(array $data): int
{
if (!isset($data['partcategory'])) {

View file

@ -91,6 +91,8 @@ class PKPartImporter
$this->setAssociationField($entity, 'partUnit', MeasurementUnit::class, $part['partUnit_id']);
}
$this->setAssociationField($entity, 'partCustomState', MeasurementUnit::class, $part['partCustomState_id']);
//Create a part lot to store the stock level and location
$lot = new PartLot();
$lot->setAmount((float) ($part['stockLevel'] ?? 0));

View file

@ -133,7 +133,7 @@ final class SandboxedTwigFactory
Supplier::class => ['getShippingCosts', 'getDefaultCurrency'],
Part::class => ['isNeedsReview', 'getTags', 'getMass', 'getIpn', 'getProviderReference',
'getDescription', 'getComment', 'isFavorite', 'getCategory', 'getFootprint',
'getPartLots', 'getPartUnit', 'useFloatAmount', 'getMinAmount', 'getAmountSum', 'isNotEnoughInstock', 'isAmountUnknown', 'getExpiredAmountSum',
'getPartLots', 'getPartUnit', 'getPartCustomState', 'useFloatAmount', 'getMinAmount', 'getAmountSum', 'isNotEnoughInstock', 'isAmountUnknown', 'getExpiredAmountSum',
'getManufacturerProductUrl', 'getCustomProductURL', 'getManufacturingStatus', 'getManufacturer',
'getManufacturerProductNumber', 'getOrderdetails', 'isObsolete',
'getParameters', 'getGroupedParameters',

View file

@ -30,6 +30,7 @@ use App\Entity\Parts\Footprint;
use App\Entity\Parts\Manufacturer;
use App\Entity\Parts\MeasurementUnit;
use App\Entity\Parts\Part;
use App\Entity\Parts\PartCustomState;
use App\Entity\Parts\StorageLocation;
use App\Entity\Parts\Supplier;
use App\Entity\PriceInformations\Currency;
@ -231,6 +232,12 @@ class ToolsTreeBuilder
$this->urlGenerator->generate('label_profile_new')
))->setIcon('fa-fw fa-treeview fa-solid fa-qrcode');
}
if ($this->security->isGranted('read', new PartCustomState())) {
$nodes[] = (new TreeViewNode(
$this->translator->trans('tree.tools.edit.part_custom_state'),
$this->urlGenerator->generate('part_custom_state_new')
))->setIcon('fa-fw fa-treeview fa-solid fa-tools');
}
if ($this->security->isGranted('create', new Part())) {
$nodes[] = (new TreeViewNode(
$this->translator->trans('tree.tools.edit.part'),

View file

@ -102,6 +102,7 @@ class PermissionPresetsHelper
$this->permissionResolver->setAllOperationsOfPermission($perm_holder, 'attachment_types', PermissionData::ALLOW);
$this->permissionResolver->setAllOperationsOfPermission($perm_holder, 'currencies', PermissionData::ALLOW);
$this->permissionResolver->setAllOperationsOfPermission($perm_holder, 'measurement_units', PermissionData::ALLOW);
$this->permissionResolver->setAllOperationsOfPermission($perm_holder, 'part_custom_states', PermissionData::ALLOW);
$this->permissionResolver->setAllOperationsOfPermission($perm_holder, 'suppliers', PermissionData::ALLOW);
$this->permissionResolver->setAllOperationsOfPermission($perm_holder, 'projects', PermissionData::ALLOW);

View file

@ -25,6 +25,7 @@ namespace App\Twig;
use App\Entity\AssemblySystem\Assembly;
use App\Entity\Attachments\Attachment;
use App\Entity\Base\AbstractDBElement;
use App\Entity\Parts\PartCustomState;
use App\Entity\ProjectSystem\Project;
use App\Entity\LabelSystem\LabelProfile;
use App\Entity\Parts\Category;
@ -117,6 +118,7 @@ final class EntityExtension extends AbstractExtension
Currency::class => 'currency',
MeasurementUnit::class => 'measurement_unit',
LabelProfile::class => 'label_profile',
PartCustomState::class => 'part_custom_state',
];
foreach ($map as $class => $type) {

View file

@ -0,0 +1,14 @@
{% extends "admin/base_admin.html.twig" %}
{% block card_title %}
<i class="fas fa-balance-scale fa-tools"></i> {% trans %}part_custom_state.caption{% endtrans %}
{% endblock %}
{% block edit_title %}
{% trans %}part_custom_state.edit{% endtrans %}: {{ entity.name }}
{% endblock %}
{% block new_title %}
{% trans %}part_custom_state.new{% endtrans %}
{% endblock %}

View file

@ -12,4 +12,5 @@
}) }}>
{{ form_row(form.ipn) }}
</div>
{{ form_row(form.partUnit) }}
{{ form_row(form.partUnit) }}
{{ form_row(form.partCustomState) }}

View file

@ -61,6 +61,7 @@
{{ form_row(filterForm.favorite) }}
{{ form_row(filterForm.needsReview) }}
{{ form_row(filterForm.measurementUnit) }}
{{ form_row(filterForm.partCustomState) }}
{{ form_row(filterForm.mass) }}
{{ form_row(filterForm.dbId) }}
{{ form_row(filterForm.ipn) }}

View file

@ -0,0 +1,35 @@
<?php
/**
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2020 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace App\Tests\Controller\AdminPages;
use App\Entity\Parts\PartCustomState;
/**
* @group slow
* @group DB
*/
class PartCustomStateControllerTest extends AbstractAdminControllerTest
{
protected static string $base_path = '/en/part_custom_state';
protected static string $entity_class = PartCustomState::class;
}

View file

@ -31,6 +31,7 @@ use App\Entity\Attachments\AttachmentType;
use App\Entity\Attachments\AttachmentTypeAttachment;
use App\Entity\Attachments\CategoryAttachment;
use App\Entity\Attachments\CurrencyAttachment;
use App\Entity\Attachments\PartCustomStateAttachment;
use App\Entity\Attachments\ProjectAttachment;
use App\Entity\Attachments\FootprintAttachment;
use App\Entity\Attachments\GroupAttachment;
@ -40,6 +41,7 @@ use App\Entity\Attachments\PartAttachment;
use App\Entity\Attachments\StorageLocationAttachment;
use App\Entity\Attachments\SupplierAttachment;
use App\Entity\Attachments\UserAttachment;
use App\Entity\Parts\PartCustomState;
use App\Entity\ProjectSystem\Project;
use App\Entity\Parts\Category;
use App\Entity\Parts\Footprint;
@ -89,6 +91,7 @@ class AttachmentTest extends TestCase
yield [ManufacturerAttachment::class, Manufacturer::class];
yield [MeasurementUnitAttachment::class, MeasurementUnit::class];
yield [PartAttachment::class, Part::class];
yield [PartCustomStateAttachment::class, PartCustomState::class];
yield [StorageLocationAttachment::class, StorageLocation::class];
yield [SupplierAttachment::class, Supplier::class];
yield [UserAttachment::class, User::class];

View file

@ -29,6 +29,7 @@ use App\Entity\Parts\Manufacturer;
use App\Entity\Parts\MeasurementUnit;
use App\Entity\Parts\Part;
use App\Entity\Parts\PartAssociation;
use App\Entity\Parts\PartCustomState;
use App\Entity\Parts\PartLot;
use App\Entity\PriceInformations\Orderdetail;
use App\Services\EntityMergers\Mergers\PartMerger;
@ -54,6 +55,7 @@ class PartMergerTest extends KernelTestCase
$manufacturer1 = new Manufacturer();
$manufacturer2 = new Manufacturer();
$unit = new MeasurementUnit();
$customState = new PartCustomState();
$part1 = (new Part())
->setCategory($category)
@ -62,7 +64,8 @@ class PartMergerTest extends KernelTestCase
$part2 = (new Part())
->setFootprint($footprint)
->setManufacturer($manufacturer2)
->setPartUnit($unit);
->setPartUnit($unit)
->setPartCustomState($customState);
$merged = $this->merger->merge($part1, $part2);
$this->assertSame($merged, $part1);
@ -70,6 +73,7 @@ class PartMergerTest extends KernelTestCase
$this->assertSame($footprint, $merged->getFootprint());
$this->assertSame($manufacturer1, $merged->getManufacturer());
$this->assertSame($unit, $merged->getPartUnit());
$this->assertSame($customState, $merged->getPartCustomState());
}
public function testMergeOfTags(): void

View file

@ -7437,11 +7437,13 @@
<field Field="lowStock" Type="tinyint(1)" Null="NO" Key="" Extra="" Comment="" />
<field Field="metaPart" Type="tinyint(1)" Null="NO" Key="" Default="0" Extra="" Comment="" />
<field Field="partUnit_id" Type="int(11)" Null="YES" Key="MUL" Default="NULL" Extra="" Comment="" />
<field Field="partCustomState_id" Type="int(11)" Null="YES" Key="MUL" Default="NULL" Extra="" Comment="" />
<field Field="storageLocation_id" Type="int(11)" Null="YES" Key="MUL" Default="NULL" Extra="" Comment="" />
<key Table="part" Non_unique="0" Key_name="PRIMARY" Seq_in_index="1" Column_name="id" Collation="A" Cardinality="3" Null="" Index_type="BTREE" Comment="" Index_comment="" Ignored="NO" />
<key Table="part" Non_unique="1" Key_name="IDX_E93DDFF812469DE2" Seq_in_index="1" Column_name="category_id" Collation="A" Cardinality="3" Null="YES" Index_type="BTREE" Comment="" Index_comment="" Ignored="NO" />
<key Table="part" Non_unique="1" Key_name="IDX_E93DDFF851364C98" Seq_in_index="1" Column_name="footprint_id" Collation="A" Cardinality="3" Null="YES" Index_type="BTREE" Comment="" Index_comment="" Ignored="NO" />
<key Table="part" Non_unique="1" Key_name="IDX_E93DDFF8F7A36E87" Seq_in_index="1" Column_name="partUnit_id" Collation="A" Cardinality="3" Null="YES" Index_type="BTREE" Comment="" Index_comment="" Ignored="NO" />
<key Table="part" Non_unique="1" Key_name="IDX_E93DDFF8F7A36E88" Seq_in_index="1" Column_name="partCustomState_id" Collation="A" Cardinality="3" Null="YES" Index_type="BTREE" Comment="" Index_comment="" Ignored="NO" />
<key Table="part" Non_unique="1" Key_name="IDX_E93DDFF873CD58AF" Seq_in_index="1" Column_name="storageLocation_id" Collation="A" Cardinality="3" Null="YES" Index_type="BTREE" Comment="" Index_comment="" Ignored="NO" />
<options Name="part" Engine="InnoDB" Version="10" Row_format="Dynamic" Rows="3" Avg_row_length="5461" Data_length="16384" Max_data_length="0" Index_length="65536" Data_free="0" Auto_increment="4" Create_time="2023-03-22 22:28:36" Update_time="2023-03-22 22:40:40" Collation="utf8mb3_unicode_ci" Create_options="" Comment="" Max_index_length="0" Temporary="N" />
</table_structure>

View file

@ -548,6 +548,12 @@
<target>Měrné jednotky</target>
</segment>
</unit>
<unit id="3bcKBzY" name="part_custom_state.caption">
<segment state="translated">
<source>part_custom_state.caption</source>
<target>Vlastní stav komponenty</target>
</segment>
</unit>
<unit id="crdkzlg" name="storelocation.labelp">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\AdminPages\StorelocationAdmin.html.twig:5</note>
@ -4891,6 +4897,12 @@ Pokud jste to provedli nesprávně nebo pokud počítač již není důvěryhodn
<target>Měrné jednotky</target>
</segment>
</unit>
<unit id="G1hmQdb" name="part.table.partCustomState">
<segment state="translated">
<source>part.table.partCustomState</source>
<target>Vlastní stav součásti</target>
</segment>
</unit>
<unit id="R5pc2FR" name="part.table.addedDate">
<notes>
<note category="file-source" priority="1">Part-DB1\src\DataTables\PartsDataTable.php:236</note>
@ -5755,6 +5767,12 @@ Pokud jste to provedli nesprávně nebo pokud počítač již není důvěryhodn
<target>Měrná jednotka</target>
</segment>
</unit>
<unit id="G1hmQdb" name="part.edit.partCustomState">
<segment state="translated">
<source>part.edit.partCustomState</source>
<target>Vlastní stav součásti</target>
</segment>
</unit>
<unit id="oY_9HE9" name="part.edit.comment">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Form\Part\PartBaseType.php:212</note>
@ -6042,6 +6060,12 @@ Pokud jste to provedli nesprávně nebo pokud počítač již není důvěryhodn
<target>Měrná jednotka</target>
</segment>
</unit>
<unit id="a1mPcMw" name="part_custom_state.label">
<segment state="translated">
<source>part_custom_state.label</source>
<target>Vlastní stav součásti</target>
</segment>
</unit>
<unit id="__SP1Zy" name="currency.label">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Services\ElementTypeNameGenerator.php:90</note>
@ -6285,6 +6309,12 @@ Pokud jste to provedli nesprávně nebo pokud počítač již není důvěryhodn
<target>Měrné jednotky</target>
</segment>
</unit>
<unit id="5adacKb" name="tree.tools.edit.part_custom_state">
<segment state="translated">
<source>tree.tools.edit.part_custom_state</source>
<target>Vlastní stav součásti</target>
</segment>
</unit>
<unit id=".Ux4R3T" name="tree.tools.edit.label_profile">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:203</note>
@ -8561,6 +8591,12 @@ Element 3</target>
<target>Měrná jednotka</target>
</segment>
</unit>
<unit id="1b5ja1c" name="perm.part_custom_states">
<segment state="translated">
<source>perm.part_custom_states</source>
<target>Vlastní stav součásti</target>
</segment>
</unit>
<unit id="coNue69" name="user.settings.pw_old.label">
<notes>
<note priority="1">obsolete</note>
@ -10926,6 +10962,12 @@ Element 3</target>
<target>Měrná jednotka</target>
</segment>
</unit>
<unit id="2COnw1k" name="log.element_edited.changed_fields.partCustomState">
<segment state="translated">
<source>log.element_edited.changed_fields.partCustomState</source>
<target>Vlastní stav součásti</target>
</segment>
</unit>
<unit id="c9XMmAp" name="log.element_edited.changed_fields.expiration_date">
<segment state="translated">
<source>log.element_edited.changed_fields.expiration_date</source>
@ -11509,6 +11551,18 @@ Element 3</target>
<target>Upravit měrnou jednotku</target>
</segment>
</unit>
<unit id="ba52d.g" name="part_custom_state.new">
<segment state="translated">
<source>part_custom_state.new</source>
<target>Nový vlastní stav komponenty</target>
</segment>
</unit>
<unit id="c1.gb2d" name="part_custom_state.edit">
<segment state="translated">
<source>part_custom_state.edit</source>
<target>Upravit vlastní stav komponenty</target>
</segment>
</unit>
<unit id="uW2WHHC" name="user.aboutMe.label">
<segment state="translated">
<source>user.aboutMe.label</source>

View file

@ -548,6 +548,12 @@
<target>Måleenhed</target>
</segment>
</unit>
<unit id="3bcKBzY" name="part_custom_state.caption">
<segment state="translated">
<source>part_custom_state.caption</source>
<target>Brugerdefineret komponentstatus</target>
</segment>
</unit>
<unit id="vZGwiMS" name="storelocation.labelp">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\AdminPages\StorelocationAdmin.html.twig:5</note>
@ -4898,6 +4904,12 @@ Bemærk også, at uden to-faktor-godkendelse er din konto ikke længere så godt
<target>Måleenhed</target>
</segment>
</unit>
<unit id="G1hmQdb" name="part.table.partCustomState">
<segment state="translated">
<source>part.table.partCustomState</source>
<target>Brugerdefineret komponentstatus</target>
</segment>
</unit>
<unit id="pw75u4x" name="part.table.addedDate">
<notes>
<note category="file-source" priority="1">Part-DB1\src\DataTables\PartsDataTable.php:236</note>
@ -5762,6 +5774,12 @@ Bemærk også, at uden to-faktor-godkendelse er din konto ikke længere så godt
<target>Måleenhed</target>
</segment>
</unit>
<unit id="G1hmQdb" name="part.edit.partCustomState">
<segment state="translated">
<source>part.edit.partCustomState</source>
<target>Brugerdefineret deltilstand</target>
</segment>
</unit>
<unit id="LTZRVlq" name="part.edit.comment">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Form\Part\PartBaseType.php:212</note>
@ -6049,6 +6067,12 @@ Bemærk også, at uden to-faktor-godkendelse er din konto ikke længere så godt
<target>Måleenhed</target>
</segment>
</unit>
<unit id="a1mPcMw" name="part_custom_state.label">
<segment state="translated">
<source>part_custom_state.label</source>
<target>Brugerdefineret deltilstand</target>
</segment>
</unit>
<unit id="5lJftbn" name="currency.label">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Services\ElementTypeNameGenerator.php:90</note>
@ -6292,6 +6316,12 @@ Bemærk også, at uden to-faktor-godkendelse er din konto ikke længere så godt
<target>Måleenhed</target>
</segment>
</unit>
<unit id="5adacKb" name="tree.tools.edit.part_custom_state">
<segment state="translated">
<source>tree.tools.edit.part_custom_state</source>
<target>Brugerdefineret komponenttilstand</target>
</segment>
</unit>
<unit id="YAalchf" name="tree.tools.edit.label_profile">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:203</note>
@ -8568,6 +8598,12 @@ Element 3</target>
<target>Måleenhed</target>
</segment>
</unit>
<unit id="1b5ja1c" name="perm.part_custom_states">
<segment state="translated">
<source>perm.part_custom_states</source>
<target>Brugerdefineret komponentstatus</target>
</segment>
</unit>
<unit id="ZrVNh2o" name="user.settings.pw_old.label">
<notes>
<note priority="1">obsolete</note>
@ -10952,6 +10988,12 @@ Element 3</target>
<target>Måleenhed</target>
</segment>
</unit>
<unit id="2COnw1k" name="log.element_edited.changed_fields.partCustomState">
<segment state="translated">
<source>log.element_edited.changed_fields.partCustomState</source>
<target>Brugerdefineret komponentstatus</target>
</segment>
</unit>
<unit id="nwxlI_C" name="log.element_edited.changed_fields.expiration_date">
<segment state="translated">
<source>log.element_edited.changed_fields.expiration_date</source>
@ -11541,6 +11583,18 @@ Oversættelsen
<target>Ret måleenhed</target>
</segment>
</unit>
<unit id="ba52d.g" name="part_custom_state.new">
<segment state="translated">
<source>part_custom_state.new</source>
<target>Ny brugerdefineret komponentstatus</target>
</segment>
</unit>
<unit id="c1.gb2d" name="part_custom_state.edit">
<segment state="translated">
<source>part_custom_state.edit</source>
<target>Rediger brugerdefineret komponentstatus</target>
</segment>
</unit>
<unit id="gRatnCn" name="user.aboutMe.label">
<segment state="translated">
<source>user.aboutMe.label</source>

View file

@ -548,6 +548,12 @@
<target>Maßeinheit</target>
</segment>
</unit>
<unit id="3bcKBzY" name="part_custom_state.caption">
<segment state="translated">
<source>part_custom_state.caption</source>
<target>Benutzerdefinierter Bauteilstatus</target>
</segment>
</unit>
<unit id="crdkzlg" name="storelocation.labelp">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\AdminPages\StorelocationAdmin.html.twig:5</note>
@ -4908,6 +4914,12 @@ Wenn Sie dies fehlerhafterweise gemacht haben oder ein Computer nicht mehr vertr
<target>Maßeinheit</target>
</segment>
</unit>
<unit id="G1hmQdb" name="part.table.partCustomState">
<segment state="translated">
<source>part.table.partCustomState</source>
<target>Benutzerdefinierter Bauteilstatus</target>
</segment>
</unit>
<unit id="R5pc2FR" name="part.table.addedDate">
<notes>
<note category="file-source" priority="1">Part-DB1\src\DataTables\PartsDataTable.php:236</note>
@ -5772,6 +5784,12 @@ Wenn Sie dies fehlerhafterweise gemacht haben oder ein Computer nicht mehr vertr
<target>Maßeinheit</target>
</segment>
</unit>
<unit id="kE1wJ1a" name="part.edit.partCustomState">
<segment state="translated">
<source>part.edit.partCustomState</source>
<target>Benutzerdefinierter Bauteilstatus</target>
</segment>
</unit>
<unit id="oY_9HE9" name="part.edit.comment">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Form\Part\PartBaseType.php:212</note>
@ -6059,6 +6077,12 @@ Wenn Sie dies fehlerhafterweise gemacht haben oder ein Computer nicht mehr vertr
<target>Maßeinheit</target>
</segment>
</unit>
<unit id="a1mPcMw" name="part_custom_state.label">
<segment state="translated">
<source>part_custom_state.label</source>
<target>Benutzerdefinierter Bauteilstatus</target>
</segment>
</unit>
<unit id="__SP1Zy" name="currency.label">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Services\ElementTypeNameGenerator.php:90</note>
@ -6302,6 +6326,12 @@ Wenn Sie dies fehlerhafterweise gemacht haben oder ein Computer nicht mehr vertr
<target>Maßeinheiten</target>
</segment>
</unit>
<unit id="5adacKb" name="tree.tools.edit.part_custom_state">
<segment state="translated">
<source>tree.tools.edit.part_custom_state</source>
<target>Benutzerdefinierter Bauteilstatus</target>
</segment>
</unit>
<unit id=".Ux4R3T" name="tree.tools.edit.label_profile">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:203</note>
@ -8581,6 +8611,12 @@ Element 1 -&gt; Element 1.2</target>
<target>Maßeinheiten</target>
</segment>
</unit>
<unit id="1b5ja1c" name="perm.part_custom_states">
<segment state="translated">
<source>perm.part_custom_states</source>
<target>Benutzerdefinierter Bauteilstatus</target>
</segment>
</unit>
<unit id="coNue69" name="user.settings.pw_old.label">
<notes>
<note priority="1">obsolete</note>
@ -11018,6 +11054,12 @@ Element 1 -&gt; Element 1.2</target>
<target>Maßeinheit</target>
</segment>
</unit>
<unit id="2COnw1k" name="log.element_edited.changed_fields.partCustomState">
<segment state="translated">
<source>log.element_edited.changed_fields.partCustomState</source>
<target>Benutzerdefinierter Bauteilstatus</target>
</segment>
</unit>
<unit id="c9XMmAp" name="log.element_edited.changed_fields.expiration_date">
<segment state="translated">
<source>log.element_edited.changed_fields.expiration_date</source>
@ -11607,6 +11649,18 @@ Element 1 -&gt; Element 1.2</target>
<target>Bearbeite Maßeinheit</target>
</segment>
</unit>
<unit id="ba52d.g" name="part_custom_state.new">
<segment state="translated">
<source>part_custom_state.new</source>
<target>Neuer benutzerdefinierter Bauteilstatus</target>
</segment>
</unit>
<unit id="c1.gb2d" name="part_custom_state.edit">
<segment state="translated">
<source>part_custom_state.edit</source>
<target>Bearbeite benutzerdefinierten Bauteilstatus</target>
</segment>
</unit>
<unit id="uW2WHHC" name="user.aboutMe.label">
<segment state="translated">
<source>user.aboutMe.label</source>

View file

@ -318,6 +318,12 @@
<target>Μονάδα μέτρησης</target>
</segment>
</unit>
<unit id="3bcKBzY" name="part_custom_state.caption">
<segment state="translated">
<source>part_custom_state.caption</source>
<target>Προσαρμοσμένη κατάσταση εξαρτήματος</target>
</segment>
</unit>
<unit id="vZGwiMS" name="storelocation.labelp">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\AdminPages\StorelocationAdmin.html.twig:5</note>
@ -1535,6 +1541,54 @@
<target>Επεξεργασία</target>
</segment>
</unit>
<unit id="1b5ja1c" name="perm.part_custom_states">
<segment state="translated">
<source>perm.part_custom_states</source>
<target>Προσαρμοσμένη κατάσταση εξαρτήματος</target>
</segment>
</unit>
<unit id="5adacKb" name="tree.tools.edit.part_custom_state">
<segment state="translated">
<source>tree.tools.edit.part_custom_state</source>
<target>Προσαρμοσμένη κατάσταση εξαρτήματος</target>
</segment>
</unit>
<unit id="ba52d.g" name="part_custom_state.new">
<segment state="translated">
<source>part_custom_state.new</source>
<target>Νέα προσαρμοσμένη κατάσταση εξαρτήματος</target>
</segment>
</unit>
<unit id="c1.gb2d" name="part_custom_state.edit">
<segment state="translated">
<source>part_custom_state.edit</source>
<target>Επεξεργασία προσαρμοσμένης κατάστασης εξαρτήματος</target>
</segment>
</unit>
<unit id="a1mPcMw" name="part_custom_state.label">
<segment state="translated">
<source>part_custom_state.label</source>
<target>Προσαρμοσμένη κατάσταση μέρους</target>
</segment>
</unit>
<unit id="2COnw1k" name="log.element_edited.changed_fields.partCustomState">
<segment state="translated">
<source>log.element_edited.changed_fields.partCustomState</source>
<target>Προσαρμοσμένη κατάσταση εξαρτήματος</target>
</segment>
</unit>
<unit id="G1hmQdb" name="part.edit.partCustomState">
<segment state="translated">
<source>part.edit.partCustomState</source>
<target>Προσαρμοσμένη κατάσταση εξαρτήματος</target>
</segment>
</unit>
<unit id="G1hmQdb" name="part.table.partCustomState">
<segment state="translated">
<source>part.table.partCustomState</source>
<target>Προσαρμοσμένη κατάσταση μέρους</target>
</segment>
</unit>
<unit id="FV7YOW6" name="part.table.name.value.for_part">
<segment state="translated">
<source>part.table.name.value.for_part</source>

View file

@ -548,6 +548,12 @@
<target>Measurement Unit</target>
</segment>
</unit>
<unit id="3bcKBzY" name="part_custom_state.caption">
<segment state="translated">
<source>part_custom_state.caption</source>
<target>Custom part state</target>
</segment>
</unit>
<unit id="crdkzlg" name="storelocation.labelp">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\AdminPages\StorelocationAdmin.html.twig:5</note>
@ -4909,6 +4915,12 @@ If you have done this incorrectly or if a computer is no longer trusted, you can
<target>Measurement Unit</target>
</segment>
</unit>
<unit id="G1hmQdb" name="part.table.partCustomState">
<segment state="translated">
<source>part.table.partCustomState</source>
<target>Custom part state</target>
</segment>
</unit>
<unit id="R5pc2FR" name="part.table.addedDate">
<notes>
<note category="file-source" priority="1">Part-DB1\src\DataTables\PartsDataTable.php:236</note>
@ -5773,6 +5785,12 @@ If you have done this incorrectly or if a computer is no longer trusted, you can
<target>Measuring unit</target>
</segment>
</unit>
<unit id="G1hmQdb" name="part.edit.partCustomState">
<segment state="translated">
<source>part.edit.partCustomState</source>
<target>Custom part state</target>
</segment>
</unit>
<unit id="oY_9HE9" name="part.edit.comment">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Form\Part\PartBaseType.php:212</note>
@ -6060,6 +6078,12 @@ If you have done this incorrectly or if a computer is no longer trusted, you can
<target>Measurement unit</target>
</segment>
</unit>
<unit id="a1mPcMw" name="part_custom_state.label">
<segment state="translated">
<source>part_custom_state.label</source>
<target>Custom part state</target>
</segment>
</unit>
<unit id="__SP1Zy" name="currency.label">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Services\ElementTypeNameGenerator.php:90</note>
@ -6303,6 +6327,12 @@ If you have done this incorrectly or if a computer is no longer trusted, you can
<target>Measurement Unit</target>
</segment>
</unit>
<unit id="5adacKb" name="tree.tools.edit.part_custom_state">
<segment state="translated">
<source>tree.tools.edit.part_custom_state</source>
<target>Custom part state</target>
</segment>
</unit>
<unit id=".Ux4R3T" name="tree.tools.edit.label_profile">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:203</note>
@ -8582,6 +8612,12 @@ Element 1 -&gt; Element 1.2</target>
<target>Measurement unit</target>
</segment>
</unit>
<unit id="1b5ja1c" name="perm.part_custom_states">
<segment state="translated">
<source>perm.part_custom_states</source>
<target>Custom part state</target>
</segment>
</unit>
<unit id="coNue69" name="user.settings.pw_old.label">
<notes>
<note priority="1">obsolete</note>
@ -11019,6 +11055,12 @@ Element 1 -&gt; Element 1.2</target>
<target>Measuring Unit</target>
</segment>
</unit>
<unit id="2COnw1k" name="log.element_edited.changed_fields.partCustomState">
<segment state="translated">
<source>log.element_edited.changed_fields.partCustomState</source>
<target>Custom part state</target>
</segment>
</unit>
<unit id="c9XMmAp" name="log.element_edited.changed_fields.expiration_date">
<segment state="translated">
<source>log.element_edited.changed_fields.expiration_date</source>
@ -11608,6 +11650,18 @@ Element 1 -&gt; Element 1.2</target>
<target>Edit Measurement Unit</target>
</segment>
</unit>
<unit id="ba52d.g" name="part_custom_state.new">
<segment state="translated">
<source>part_custom_state.new</source>
<target>New custom part state</target>
</segment>
</unit>
<unit id="c1.gb2d" name="part_custom_state.edit">
<segment state="translated">
<source>part_custom_state.edit</source>
<target>Edit custom part state</target>
</segment>
</unit>
<unit id="uW2WHHC" name="user.aboutMe.label">
<segment state="translated">
<source>user.aboutMe.label</source>

View file

@ -548,6 +548,12 @@
<target>Unidad de medida</target>
</segment>
</unit>
<unit id="3bcKBzY" name="part_custom_state.caption">
<segment state="translated">
<source>part_custom_state.caption</source>
<target>Estado personalizado del componente</target>
</segment>
</unit>
<unit id="crdkzlg" name="storelocation.labelp">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\AdminPages\StorelocationAdmin.html.twig:5</note>
@ -4908,6 +4914,12 @@ Subelementos serán desplazados hacia arriba.</target>
<target>Unidad de Medida</target>
</segment>
</unit>
<unit id="G1hmQdb" name="part.table.partCustomState">
<segment state="translated">
<source>part.table.partCustomState</source>
<target>Estado personalizado del componente</target>
</segment>
</unit>
<unit id="R5pc2FR" name="part.table.addedDate">
<notes>
<note category="file-source" priority="1">Part-DB1\src\DataTables\PartsDataTable.php:236</note>
@ -5772,6 +5784,12 @@ Subelementos serán desplazados hacia arriba.</target>
<target>Unidad de medida</target>
</segment>
</unit>
<unit id="G1hmQdb" name="part.edit.partCustomState">
<segment state="translated">
<source>part.edit.partCustomState</source>
<target>Estado personalizado de la pieza</target>
</segment>
</unit>
<unit id="oY_9HE9" name="part.edit.comment">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Form\Part\PartBaseType.php:212</note>
@ -6059,6 +6077,12 @@ Subelementos serán desplazados hacia arriba.</target>
<target>Unidad de medida</target>
</segment>
</unit>
<unit id="a1mPcMw" name="part_custom_state.label">
<segment state="translated">
<source>part_custom_state.label</source>
<target>Estado personalizado de la pieza</target>
</segment>
</unit>
<unit id="__SP1Zy" name="currency.label">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Services\ElementTypeNameGenerator.php:90</note>
@ -6302,6 +6326,12 @@ Subelementos serán desplazados hacia arriba.</target>
<target>Unidad de medida</target>
</segment>
</unit>
<unit id="5adacKb" name="tree.tools.edit.part_custom_state">
<segment state="translated">
<source>tree.tools.edit.part_custom_state</source>
<target>Estado personalizado del componente</target>
</segment>
</unit>
<unit id=".Ux4R3T" name="tree.tools.edit.label_profile">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:203</note>
@ -8578,6 +8608,12 @@ Elemento 3</target>
<target>Unidad de medida</target>
</segment>
</unit>
<unit id="1b5ja1c" name="perm.part_custom_states">
<segment state="translated">
<source>perm.part_custom_states</source>
<target>Estado personalizado del componente</target>
</segment>
</unit>
<unit id="coNue69" name="user.settings.pw_old.label">
<notes>
<note priority="1">obsolete</note>
@ -10962,6 +10998,12 @@ Elemento 3</target>
<target>Unidad de medida</target>
</segment>
</unit>
<unit id="2COnw1k" name="log.element_edited.changed_fields.partCustomState">
<segment state="translated">
<source>log.element_edited.changed_fields.partCustomState</source>
<target>Estado personalizado del componente</target>
</segment>
</unit>
<unit id="c9XMmAp" name="log.element_edited.changed_fields.expiration_date">
<segment state="translated">
<source>log.element_edited.changed_fields.expiration_date</source>
@ -11545,6 +11587,18 @@ Elemento 3</target>
<target>Editar Unidad de Medida</target>
</segment>
</unit>
<unit id="ba52d.g" name="part_custom_state.new">
<segment state="translated">
<source>part_custom_state.new</source>
<target>Nuevo estado personalizado del componente</target>
</segment>
</unit>
<unit id="c1.gb2d" name="part_custom_state.edit">
<segment state="translated">
<source>part_custom_state.edit</source>
<target>Editar estado personalizado del componente</target>
</segment>
</unit>
<unit id="uW2WHHC" name="user.aboutMe.label">
<segment state="translated">
<source>user.aboutMe.label</source>

View file

@ -517,6 +517,12 @@
<target>Unité de mesure</target>
</segment>
</unit>
<unit id="3bcKBzY" name="part_custom_state.caption">
<segment state="translated">
<source>part_custom_state.caption</source>
<target>État personnalisé du composant</target>
</segment>
</unit>
<unit id="vZGwiMS" name="storelocation.labelp">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\AdminPages\StorelocationAdmin.html.twig:5</note>
@ -4871,6 +4877,12 @@ Si vous avez fait cela de manière incorrecte ou si un ordinateur n'est plus fia
<target>Unité de mesure</target>
</segment>
</unit>
<unit id="G1hmQdb" name="part.table.partCustomState">
<segment state="translated">
<source>part.table.partCustomState</source>
<target>État personnalisé de la pièce</target>
</segment>
</unit>
<unit id="pw75u4x" name="part.table.addedDate">
<notes>
<note category="file-source" priority="1">Part-DB1\src\DataTables\PartsDataTable.php:236</note>
@ -5735,6 +5747,12 @@ Si vous avez fait cela de manière incorrecte ou si un ordinateur n'est plus fia
<target>Unité de mesure</target>
</segment>
</unit>
<unit id="G1hmQdb" name="part.edit.partCustomState">
<segment state="translated">
<source>part.edit.partCustomState</source>
<target>État personnalisé de la pièce</target>
</segment>
</unit>
<unit id="LTZRVlq" name="part.edit.comment">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Form\Part\PartBaseType.php:212</note>
@ -6012,6 +6030,12 @@ Si vous avez fait cela de manière incorrecte ou si un ordinateur n'est plus fia
<target>Unité de mesure</target>
</segment>
</unit>
<unit id="a1mPcMw" name="part_custom_state.label">
<segment state="translated">
<source>part_custom_state.label</source>
<target>État personnalisé de la pièce</target>
</segment>
</unit>
<unit id="5lJftbn" name="currency.label">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Services\ElementTypeNameGenerator.php:90</note>
@ -6244,6 +6268,12 @@ Si vous avez fait cela de manière incorrecte ou si un ordinateur n'est plus fia
<target>Unité de mesure</target>
</segment>
</unit>
<unit id="5adacKb" name="tree.tools.edit.part_custom_state">
<segment state="translated">
<source>tree.tools.edit.part_custom_state</source>
<target>État personnalisé de la pièce</target>
</segment>
</unit>
<unit id="YAalchf" name="tree.tools.edit.label_profile">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:203</note>
@ -8507,6 +8537,12 @@ exemple de ville</target>
<target>Unités de mesure</target>
</segment>
</unit>
<unit id="1b5ja1c" name="perm.part_custom_states">
<segment state="translated">
<source>perm.part_custom_states</source>
<target>État personnalisé du composant</target>
</segment>
</unit>
<unit id="ZrVNh2o" name="user.settings.pw_old.label">
<notes>
<note priority="1">obsolete</note>
@ -10128,5 +10164,23 @@ exemple de ville</target>
<target>Un préfixe suggéré lors de la saisie de l'IPN d'une pièce.</target>
</segment>
</unit>
<unit id="ba52d.g" name="part_custom_state.new">
<segment state="translated">
<source>part_custom_state.new</source>
<target>Nouveau statut personnalisé du composant</target>
</segment>
</unit>
<unit id="c1.gb2d" name="part_custom_state.edit">
<segment state="translated">
<source>part_custom_state.edit</source>
<target>Modifier le statut personnalisé du composant</target>
</segment>
</unit>
<unit id="2COnw1k" name="log.element_edited.changed_fields.partCustomState">
<segment state="translated">
<source>log.element_edited.changed_fields.partCustomState</source>
<target>État personnalisé de la pièce</target>
</segment>
</unit>
</file>
</xliff>

View file

@ -548,6 +548,12 @@
<target>Unità di misura</target>
</segment>
</unit>
<unit id="3bcKBzY" name="part_custom_state.caption">
<segment state="translated">
<source>part_custom_state.caption</source>
<target>Stato personalizzato del componente</target>
</segment>
</unit>
<unit id="crdkzlg" name="storelocation.labelp">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\AdminPages\StorelocationAdmin.html.twig:5</note>
@ -4910,6 +4916,12 @@ Se è stato fatto in modo errato o se un computer non è più attendibile, puoi
<target>Unità di misura</target>
</segment>
</unit>
<unit id="G1hmQdb" name="part.table.partCustomState">
<segment state="translated">
<source>part.table.partCustomState</source>
<target>Stato personalizzato del componente</target>
</segment>
</unit>
<unit id="R5pc2FR" name="part.table.addedDate">
<notes>
<note category="file-source" priority="1">Part-DB1\src\DataTables\PartsDataTable.php:236</note>
@ -5774,6 +5786,12 @@ Se è stato fatto in modo errato o se un computer non è più attendibile, puoi
<target>Unità di misura</target>
</segment>
</unit>
<unit id="G1hmQdb" name="part.edit.partCustomState">
<segment state="translated">
<source>part.edit.partCustomState</source>
<target>Stato personalizzato della parte</target>
</segment>
</unit>
<unit id="oY_9HE9" name="part.edit.comment">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Form\Part\PartBaseType.php:212</note>
@ -6061,6 +6079,12 @@ Se è stato fatto in modo errato o se un computer non è più attendibile, puoi
<target>Unità di misura</target>
</segment>
</unit>
<unit id="a1mPcMw" name="part_custom_state.label">
<segment state="translated">
<source>part_custom_state.label</source>
<target>Stato personalizzato della parte</target>
</segment>
</unit>
<unit id="__SP1Zy" name="currency.label">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Services\ElementTypeNameGenerator.php:90</note>
@ -6304,6 +6328,12 @@ Se è stato fatto in modo errato o se un computer non è più attendibile, puoi
<target>Unità di misura</target>
</segment>
</unit>
<unit id="5adacKb" name="tree.tools.edit.part_custom_state">
<segment state="translated">
<source>tree.tools.edit.part_custom_state</source>
<target>Stato personalizzato del componente</target>
</segment>
</unit>
<unit id=".Ux4R3T" name="tree.tools.edit.label_profile">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:203</note>
@ -8580,6 +8610,12 @@ Element 3</target>
<target>Unità di misura</target>
</segment>
</unit>
<unit id="1b5ja1c" name="perm.part_custom_states">
<segment state="translated">
<source>perm.part_custom_states</source>
<target>Stato personalizzato del componente</target>
</segment>
</unit>
<unit id="coNue69" name="user.settings.pw_old.label">
<notes>
<note priority="1">obsolete</note>
@ -10964,6 +11000,12 @@ Element 3</target>
<target>Unità di misura</target>
</segment>
</unit>
<unit id="2COnw1k" name="log.element_edited.changed_fields.partCustomState">
<segment state="translated">
<source>log.element_edited.changed_fields.partCustomState</source>
<target>Stato personalizzato della parte</target>
</segment>
</unit>
<unit id="c9XMmAp" name="log.element_edited.changed_fields.expiration_date">
<segment state="translated">
<source>log.element_edited.changed_fields.expiration_date</source>
@ -11547,6 +11589,18 @@ Element 3</target>
<target>Modificare l'unità di misura</target>
</segment>
</unit>
<unit id="ba52d.g" name="part_custom_state.new">
<segment state="translated">
<source>part_custom_state.new</source>
<target>Nuovo stato personalizzato del componente</target>
</segment>
</unit>
<unit id="c1.gb2d" name="part_custom_state.edit">
<segment state="translated">
<source>part_custom_state.edit</source>
<target>Modifica stato personalizzato del componente</target>
</segment>
</unit>
<unit id="uW2WHHC" name="user.aboutMe.label">
<segment state="translated">
<source>user.aboutMe.label</source>

View file

@ -517,6 +517,12 @@
<target>単位</target>
</segment>
</unit>
<unit id="3bcKBzY" name="part_custom_state.caption">
<segment state="translated">
<source>part_custom_state.caption</source>
<target>部品のカスタム状態</target>
</segment>
</unit>
<unit id="vZGwiMS" name="storelocation.labelp">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\AdminPages\StorelocationAdmin.html.twig:5</note>
@ -4871,6 +4877,12 @@
<target>単位</target>
</segment>
</unit>
<unit id="G1hmQdb" name="part.table.partCustomState">
<segment state="translated">
<source>part.table.partCustomState</source>
<target>部品のカスタム状態</target>
</segment>
</unit>
<unit id="pw75u4x" name="part.table.addedDate">
<notes>
<note category="file-source" priority="1">Part-DB1\src\DataTables\PartsDataTable.php:236</note>
@ -5735,6 +5747,12 @@
<target>単位</target>
</segment>
</unit>
<unit id="G1hmQdb" name="part.edit.partCustomState">
<segment state="translated">
<source>part.edit.partCustomState</source>
<target>部品のカスタム状態</target>
</segment>
</unit>
<unit id="LTZRVlq" name="part.edit.comment">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Form\Part\PartBaseType.php:212</note>
@ -6012,6 +6030,12 @@
<target>単位</target>
</segment>
</unit>
<unit id="a1mPcMw" name="part_custom_state.label">
<segment state="translated">
<source>part_custom_state.label</source>
<target>部品のカスタム状態</target>
</segment>
</unit>
<unit id="5lJftbn" name="currency.label">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Services\ElementTypeNameGenerator.php:90</note>
@ -6244,6 +6268,12 @@
<target>単位</target>
</segment>
</unit>
<unit id="5adacKb" name="tree.tools.edit.part_custom_state">
<segment state="translated">
<source>tree.tools.edit.part_custom_state</source>
<target>部品のカスタム状態</target>
</segment>
</unit>
<unit id="YAalchf" name="tree.tools.edit.label_profile">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:203</note>
@ -8508,6 +8538,12 @@ Exampletown</target>
<target>単位</target>
</segment>
</unit>
<unit id="1b5ja1c" name="perm.part_custom_states">
<segment state="translated">
<source>perm.part_custom_states</source>
<target>部品のカスタム状態</target>
</segment>
</unit>
<unit id="ZrVNh2o" name="user.settings.pw_old.label">
<notes>
<note priority="1">obsolete</note>
@ -9841,5 +9877,23 @@ Exampletown</target>
<target>部品のIPN入力時に提案される接頭辞。</target>
</segment>
</unit>
<unit id="ba52d.g" name="part_custom_state.new">
<segment state="translated">
<source>part_custom_state.new</source>
<target>部品の新しいカスタム状態</target>
</segment>
</unit>
<unit id="c1.gb2d" name="part_custom_state.edit">
<segment state="translated">
<source>part_custom_state.edit</source>
<target>部品のカスタム状態を編集</target>
</segment>
</unit>
<unit id="2COnw1k" name="log.element_edited.changed_fields.partCustomState">
<segment state="translated">
<source>log.element_edited.changed_fields.partCustomState</source>
<target>部品のカスタム状態</target>
</segment>
</unit>
</file>
</xliff>

View file

@ -548,6 +548,12 @@
<target>Meeteenheden</target>
</segment>
</unit>
<unit id="3bcKBzY" name="part_custom_state.caption">
<segment state="translated">
<source>part_custom_state.caption</source>
<target>Aangepaste status van het onderdeel</target>
</segment>
</unit>
<unit id="vZGwiMS" name="storelocation.labelp">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\AdminPages\StorelocationAdmin.html.twig:5</note>
@ -724,6 +730,54 @@
<target>Weet u zeker dat u wilt doorgaan?</target>
</segment>
</unit>
<unit id="1b5ja1c" name="perm.part_custom_states">
<segment state="translated">
<source>perm.part_custom_states</source>
<target>Aangepaste status van onderdeel</target>
</segment>
</unit>
<unit id="5adacKb" name="tree.tools.edit.part_custom_state">
<segment state="translated">
<source>tree.tools.edit.part_custom_state</source>
<target>Aangepaste status van het onderdeel</target>
</segment>
</unit>
<unit id="ba52d.g" name="part_custom_state.new">
<segment state="translated">
<source>part_custom_state.new</source>
<target>Nieuwe aangepaste status van het onderdeel</target>
</segment>
</unit>
<unit id="c1.gb2d" name="part_custom_state.edit">
<segment state="translated">
<source>part_custom_state.edit</source>
<target>Aangepaste status van het onderdeel bewerken</target>
</segment>
</unit>
<unit id="a1mPcMw" name="part_custom_state.label">
<segment state="translated">
<source>part_custom_state.label</source>
<target>Aangepaste staat van onderdeel</target>
</segment>
</unit>
<unit id="2COnw1k" name="log.element_edited.changed_fields.partCustomState">
<segment state="translated">
<source>log.element_edited.changed_fields.partCustomState</source>
<target>Aangepaste staat van het onderdeel</target>
</segment>
</unit>
<unit id="G1hmQdb" name="part.edit.partCustomState">
<segment state="translated">
<source>part.edit.partCustomState</source>
<target>Aangepaste staat van het onderdeel</target>
</segment>
</unit>
<unit id="G1hmQdb" name="part.table.partCustomState">
<segment state="translated">
<source>part.table.partCustomState</source>
<target>Aangepaste status van onderdeel</target>
</segment>
</unit>
<unit id="FV7YOW6" name="part.table.name.value.for_part">
<segment state="translated">
<source>part.table.name.value.for_part</source>

View file

@ -548,6 +548,12 @@
<target>Jednostka miary</target>
</segment>
</unit>
<unit id="3bcKBzY" name="part_custom_state.caption">
<segment state="translated">
<source>part_custom_state.caption</source>
<target>Stan niestandardowy komponentu</target>
</segment>
</unit>
<unit id="crdkzlg" name="storelocation.labelp">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\AdminPages\StorelocationAdmin.html.twig:5</note>
@ -4913,6 +4919,12 @@ Jeśli zrobiłeś to niepoprawnie lub komputer nie jest już godny zaufania, mo
<target>Jednostka pomiarowa</target>
</segment>
</unit>
<unit id="G1hmQdb" name="part.table.partCustomState">
<segment state="translated">
<source>part.table.partCustomState</source>
<target>Niestandardowy stan części</target>
</segment>
</unit>
<unit id="R5pc2FR" name="part.table.addedDate">
<notes>
<note category="file-source" priority="1">Part-DB1\src\DataTables\PartsDataTable.php:236</note>
@ -5777,6 +5789,12 @@ Jeśli zrobiłeś to niepoprawnie lub komputer nie jest już godny zaufania, mo
<target>Jednostka pomiarowa</target>
</segment>
</unit>
<unit id="G1hmQdb" name="part.edit.partCustomState">
<segment state="translated">
<source>part.edit.partCustomState</source>
<target>Własny stan części</target>
</segment>
</unit>
<unit id="oY_9HE9" name="part.edit.comment">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Form\Part\PartBaseType.php:212</note>
@ -6064,6 +6082,12 @@ Jeśli zrobiłeś to niepoprawnie lub komputer nie jest już godny zaufania, mo
<target>Jednostka pomiarowa</target>
</segment>
</unit>
<unit id="a1mPcMw" name="part_custom_state.label">
<segment state="translated">
<source>part_custom_state.label</source>
<target>Własny stan części</target>
</segment>
</unit>
<unit id="__SP1Zy" name="currency.label">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Services\ElementTypeNameGenerator.php:90</note>
@ -6307,6 +6331,12 @@ Jeśli zrobiłeś to niepoprawnie lub komputer nie jest już godny zaufania, mo
<target>Jednostka miary</target>
</segment>
</unit>
<unit id="5adacKb" name="tree.tools.edit.part_custom_state">
<segment state="translated">
<source>tree.tools.edit.part_custom_state</source>
<target>Niestandardowy stan części</target>
</segment>
</unit>
<unit id=".Ux4R3T" name="tree.tools.edit.label_profile">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:203</note>
@ -8583,6 +8613,12 @@ Element 3</target>
<target>Jednostka miary</target>
</segment>
</unit>
<unit id="1b5ja1c" name="perm.part_custom_states">
<segment state="translated">
<source>perm.part_custom_states</source>
<target>Stan niestandardowy komponentu</target>
</segment>
</unit>
<unit id="coNue69" name="user.settings.pw_old.label">
<notes>
<note priority="1">obsolete</note>
@ -10967,6 +11003,12 @@ Element 3</target>
<target>Jednostka pomiarowa</target>
</segment>
</unit>
<unit id="2COnw1k" name="log.element_edited.changed_fields.partCustomState">
<segment state="translated">
<source>log.element_edited.changed_fields.partCustomState</source>
<target>Niestandardowy stan części</target>
</segment>
</unit>
<unit id="c9XMmAp" name="log.element_edited.changed_fields.expiration_date">
<segment state="translated">
<source>log.element_edited.changed_fields.expiration_date</source>
@ -11550,6 +11592,18 @@ Element 3</target>
<target>Edytuj jednostkę miary</target>
</segment>
</unit>
<unit id="ba52d.g" name="part_custom_state.new">
<segment state="translated">
<source>part_custom_state.new</source>
<target>Nowy niestandardowy stan części</target>
</segment>
</unit>
<unit id="c1.gb2d" name="part_custom_state.edit">
<segment state="translated">
<source>part_custom_state.edit</source>
<target>Edytuj niestandardowy stan części</target>
</segment>
</unit>
<unit id="uW2WHHC" name="user.aboutMe.label">
<segment state="translated">
<source>user.aboutMe.label</source>

View file

@ -548,6 +548,12 @@
<target>Единица измерения</target>
</segment>
</unit>
<unit id="3bcKBzY" name="part_custom_state.caption">
<segment state="translated">
<source>part_custom_state.caption</source>
<target>Пользовательское состояние компонента</target>
</segment>
</unit>
<unit id="crdkzlg" name="storelocation.labelp">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\AdminPages\StorelocationAdmin.html.twig:5</note>
@ -4919,6 +4925,12 @@
<target>Единица измерения</target>
</segment>
</unit>
<unit id="G1hmQdb" name="part.table.partCustomState">
<segment state="translated">
<source>part.table.partCustomState</source>
<target>Пользовательское состояние детали</target>
</segment>
</unit>
<unit id="R5pc2FR" name="part.table.addedDate">
<notes>
<note category="file-source" priority="1">Part-DB1\src\DataTables\PartsDataTable.php:236</note>
@ -5783,6 +5795,12 @@
<target>Единица измерения</target>
</segment>
</unit>
<unit id="G1hmQdb" name="part.edit.partCustomState">
<segment state="translated">
<source>part.edit.partCustomState</source>
<target>Пользовательское состояние части</target>
</segment>
</unit>
<unit id="oY_9HE9" name="part.edit.comment">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Form\Part\PartBaseType.php:212</note>
@ -6070,6 +6088,12 @@
<target>Единица измерения</target>
</segment>
</unit>
<unit id="a1mPcMw" name="part_custom_state.label">
<segment state="translated">
<source>part_custom_state.label</source>
<target>Пользовательское состояние детали</target>
</segment>
</unit>
<unit id="__SP1Zy" name="currency.label">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Services\ElementTypeNameGenerator.php:90</note>
@ -6313,6 +6337,12 @@
<target>Единица измерения</target>
</segment>
</unit>
<unit id="5adacKb" name="tree.tools.edit.part_custom_state">
<segment state="translated">
<source>tree.tools.edit.part_custom_state</source>
<target>Пользовательское состояние компонента</target>
</segment>
</unit>
<unit id=".Ux4R3T" name="tree.tools.edit.label_profile">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:203</note>
@ -8587,6 +8617,12 @@
<target>Единица измерения</target>
</segment>
</unit>
<unit id="1b5ja1c" name="perm.part_custom_states">
<segment state="translated">
<source>perm.part_custom_states</source>
<target>Пользовательское состояние компонента</target>
</segment>
</unit>
<unit id="coNue69" name="user.settings.pw_old.label">
<notes>
<note priority="1">obsolete</note>
@ -10971,6 +11007,12 @@
<target>Единица измерения</target>
</segment>
</unit>
<unit id="2COnw1k" name="log.element_edited.changed_fields.partCustomState">
<segment state="translated">
<source>log.element_edited.changed_fields.partCustomState</source>
<target>Пользовательское состояние детали</target>
</segment>
</unit>
<unit id="c9XMmAp" name="log.element_edited.changed_fields.expiration_date">
<segment state="translated">
<source>log.element_edited.changed_fields.expiration_date</source>
@ -11554,6 +11596,18 @@
<target>Изменить единицу измерения</target>
</segment>
</unit>
<unit id="ba52d.g" name="part_custom_state.new">
<segment state="translated">
<source>part_custom_state.new</source>
<target>Новое пользовательское состояние компонента</target>
</segment>
</unit>
<unit id="c1.gb2d" name="part_custom_state.edit">
<segment state="translated">
<source>part_custom_state.edit</source>
<target>Редактировать пользовательское состояние компонента</target>
</segment>
</unit>
<unit id="uW2WHHC" name="user.aboutMe.label">
<segment state="translated">
<source>user.aboutMe.label</source>

View file

@ -548,6 +548,12 @@
<target>计量单位</target>
</segment>
</unit>
<unit id="3bcKBzY" name="part_custom_state.caption">
<segment state="translated">
<source>part_custom_state.caption</source>
<target>部件的自定义状态</target>
</segment>
</unit>
<unit id="vZGwiMS" name="storelocation.labelp">
<notes>
<note category="file-source" priority="1">Part-DB1\templates\AdminPages\StorelocationAdmin.html.twig:5</note>
@ -4917,6 +4923,12 @@
<target>计量单位</target>
</segment>
</unit>
<unit id="G1hmQdb" name="part.table.partCustomState">
<segment state="translated">
<source>part.table.partCustomState</source>
<target>部件的自定义状态</target>
</segment>
</unit>
<unit id="pw75u4x" name="part.table.addedDate">
<notes>
<note category="file-source" priority="1">Part-DB1\src\DataTables\PartsDataTable.php:236</note>
@ -5781,6 +5793,12 @@
<target>计量单位</target>
</segment>
</unit>
<unit id="G1hmQdb" name="part.edit.partCustomState">
<segment state="translated">
<source>part.edit.partCustomState</source>
<target>部件的自定义状态</target>
</segment>
</unit>
<unit id="LTZRVlq" name="part.edit.comment">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Form\Part\PartBaseType.php:212</note>
@ -6068,6 +6086,12 @@
<target>计量单位</target>
</segment>
</unit>
<unit id="a1mPcMw" name="part_custom_state.label">
<segment state="translated">
<source>part_custom_state.label</source>
<target>部件自定义状态</target>
</segment>
</unit>
<unit id="5lJftbn" name="currency.label">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Services\ElementTypeNameGenerator.php:90</note>
@ -6311,6 +6335,12 @@
<target>计量单位</target>
</segment>
</unit>
<unit id="5adacKb" name="tree.tools.edit.part_custom_state">
<segment state="translated">
<source>tree.tools.edit.part_custom_state</source>
<target>部件自定义状态</target>
</segment>
</unit>
<unit id="YAalchf" name="tree.tools.edit.label_profile">
<notes>
<note category="file-source" priority="1">Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:203</note>
@ -8586,6 +8616,12 @@ Element 3</target>
<target>计量单位</target>
</segment>
</unit>
<unit id="1b5ja1c" name="perm.part_custom_states">
<segment state="translated">
<source>perm.part_custom_states</source>
<target>部件的自定义状态</target>
</segment>
</unit>
<unit id="ZrVNh2o" name="user.settings.pw_old.label">
<notes>
<note priority="1">obsolete</note>
@ -10970,6 +11006,12 @@ Element 3</target>
<target>计量单位</target>
</segment>
</unit>
<unit id="2COnw1k" name="log.element_edited.changed_fields.partCustomState">
<segment state="translated">
<source>log.element_edited.changed_fields.partCustomState</source>
<target>部件的自定义状态</target>
</segment>
</unit>
<unit id="nwxlI_C" name="log.element_edited.changed_fields.expiration_date">
<segment state="translated">
<source>log.element_edited.changed_fields.expiration_date</source>
@ -11553,6 +11595,18 @@ Element 3</target>
<target>编辑度量单位</target>
</segment>
</unit>
<unit id="ba52d.g" name="part_custom_state.new">
<segment state="translated">
<source>part_custom_state.new</source>
<target>部件的新自定义状态</target>
</segment>
</unit>
<unit id="c1.gb2d" name="part_custom_state.edit">
<segment state="translated">
<source>part_custom_state.edit</source>
<target>编辑部件的自定义状态</target>
</segment>
</unit>
<unit id="gRatnCn" name="user.aboutMe.label">
<segment state="translated">
<source>user.aboutMe.label</source>