diff --git a/assets/controllers/elements/assembly_select_controller.js b/assets/controllers/elements/assembly_select_controller.js new file mode 100644 index 000000000..98702d419 --- /dev/null +++ b/assets/controllers/elements/assembly_select_controller.js @@ -0,0 +1,70 @@ +import {Controller} from "@hotwired/stimulus"; + +import "tom-select/dist/css/tom-select.bootstrap5.css"; +import '../../css/components/tom-select_extensions.css'; +import TomSelect from "tom-select"; +import {marked} from "marked"; + +export default class extends Controller { + _tomSelect; + + connect() { + + let settings = { + allowEmptyOption: true, + plugins: ['dropdown_input', 'clear_button'], + searchField: ["name", "description", "category", "footprint"], + valueField: "id", + labelField: "name", + preload: "focus", + render: { + item: (data, escape) => { + return '' + (data.image ? "" : "") + escape(data.name) + ''; + }, + option: (data, escape) => { + if(data.text) { + return '' + escape(data.text) + ''; + } + + let tmp = '
' + + "
" + + (data.image ? "" : "") + + "
" + + "
" + + '
' + escape(data.name) + '
' + + (data.description ? '

' + marked.parseInline(data.description) + '

' : "") + + (data.category ? '

' + escape(data.category) : ""); + + return tmp + '

' + + '
'; + } + } + }; + + + if (this.element.dataset.autocomplete) { + const base_url = this.element.dataset.autocomplete; + settings.valueField = "id"; + settings.load = (query, callback) => { + const url = base_url.replace('__QUERY__', encodeURIComponent(query)); + + fetch(url) + .then(response => response.json()) + .then(json => {callback(json);}) + .catch(() => { + callback() + }); + }; + + + this._tomSelect = new TomSelect(this.element, settings); + //this._tomSelect.clearOptions(); + } + } + + disconnect() { + super.disconnect(); + //Destroy the TomSelect instance + this._tomSelect.destroy(); + } +} \ No newline at end of file diff --git a/assets/controllers/elements/part_select_controller.js b/assets/controllers/elements/part_select_controller.js index 0658f4b46..2b658d526 100644 --- a/assets/controllers/elements/part_select_controller.js +++ b/assets/controllers/elements/part_select_controller.js @@ -12,7 +12,7 @@ export default class extends Controller { let settings = { allowEmptyOption: true, - plugins: ['dropdown_input'], + plugins: ['dropdown_input', 'clear_button'], searchField: ["name", "description", "category", "footprint"], valueField: "id", labelField: "name", diff --git a/assets/controllers/elements/toggle_visibility_controller.js b/assets/controllers/elements/toggle_visibility_controller.js new file mode 100644 index 000000000..51c9cb338 --- /dev/null +++ b/assets/controllers/elements/toggle_visibility_controller.js @@ -0,0 +1,62 @@ +import { Controller } from "@hotwired/stimulus"; + +export default class extends Controller { + + static values = { + classes: Array + }; + + connect() { + this.displayCheckbox = this.element.querySelector("#display"); + this.displaySelect = this.element.querySelector("select#display"); + + if (this.displayCheckbox) { + this.toggleContainers(this.displayCheckbox.checked); + + this.displayCheckbox.addEventListener("change", (event) => { + this.toggleContainers(event.target.checked); + }); + } + + if (this.displaySelect) { + this.toggleContainers(this.hasDisplaySelectValue()); + + this.displaySelect.addEventListener("change", () => { + this.toggleContainers(this.hasDisplaySelectValue()); + }); + } + + } + + /** + * Check whether a value was selected in the selectbox + * @returns {boolean} True when a value has not been selected that is not empty + */ + hasDisplaySelectValue() { + return this.displaySelect && this.displaySelect.value !== ""; + } + + /** + * Hides specified containers if the state is active (checkbox checked or select with value). + * + * @param {boolean} isActive - True when the checkbox is activated or the selectbox has a value. + */ + toggleContainers(isActive) { + if (!Array.isArray(this.classesValue) || this.classesValue.length === 0) { + return; + } + + this.classesValue.forEach((cssClass) => { + const elements = document.querySelectorAll(`.${cssClass}`); + + if (!elements.length) { + return; + } + + elements.forEach((element) => { + element.style.display = isActive ? "none" : ""; + }); + }); + } + +} diff --git a/assets/controllers/pages/dont_check_quantity_checkbox_controller.js b/assets/controllers/pages/dont_check_quantity_checkbox_controller.js index 2abd3d77b..f3e8cb900 100644 --- a/assets/controllers/pages/dont_check_quantity_checkbox_controller.js +++ b/assets/controllers/pages/dont_check_quantity_checkbox_controller.js @@ -38,7 +38,7 @@ export default class extends Controller { connect() { //Add event listener to the checkbox - this.getCheckbox().addEventListener('change', this.toggleInputLimits.bind(this)); + this.getCheckbox()?.addEventListener('change', this.toggleInputLimits.bind(this)); } toggleInputLimits() { diff --git a/assets/css/app/images.css b/assets/css/app/images.css index 0212a85b7..132cab99b 100644 --- a/assets/css/app/images.css +++ b/assets/css/app/images.css @@ -61,3 +61,8 @@ .object-fit-cover { object-fit: cover; } + +.assembly-table-image { + max-height: 40px; + object-fit: contain; +} diff --git a/assets/js/lib/datatables.js b/assets/js/lib/datatables.js index 67bab02db..2f078283f 100644 --- a/assets/js/lib/datatables.js +++ b/assets/js/lib/datatables.js @@ -18,6 +18,12 @@ //CHANGED jbtronics: Preserve the get parameters (needed so we can pass additional params to query) $.fn.initDataTables.defaults.url = window.location.origin + window.location.pathname + window.location.search; + $.fn.dataTable.ext.errMode = function(settings, helpPage, message) { + if (message.includes('ColReorder')) { + console.warn('ColReorder does not fit the number of columns', message); + } + }; + var root = this, config = $.extend({}, $.fn.initDataTables.defaults, config), state = '' @@ -105,7 +111,6 @@ } } - root.html(data.template); dt = $('table', root).DataTable(dtOpts); if (config.state !== 'none') { diff --git a/config/permissions.yaml b/config/permissions.yaml index 8cbd60c3f..8709fdb77 100644 --- a/config/permissions.yaml +++ b/config/permissions.yaml @@ -121,6 +121,10 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co <<: *PART_CONTAINING label: "perm.projects" + assemblies: + <<: *PART_CONTAINING + label: "perm.assemblies" + attachment_types: <<: *PART_CONTAINING label: "perm.part.attachment_types" diff --git a/config/services.yaml b/config/services.yaml index 17611ceab..b1af60b0f 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -164,6 +164,9 @@ services: arguments: $saml_enabled: '%partdb.saml.enabled%' + App\Validator\Constraints\AssemblySystem\AssemblyCycleValidator: + tags: [ 'validator.constraint_validator' ] + #################################################################################################################### # Table settings #################################################################################################################### diff --git a/docs/configuration.md b/docs/configuration.md index d4b217816..d2f1310a8 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -137,6 +137,13 @@ bundled with Part-DB. Set `DATABASE_MYSQL_SSL_VERIFY_CERT` if you want to accept 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`. +* `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`. +* `TABLE_ASSEMBLIES_BOM_DEFAULT_COLUMNS`: The columns in assemblies bom 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: `quantity`, `name`, `id`, `ipn`, `description`, `category`, `footprint`, `manufacturer`, `designator`, `mountnames`, `storage_location`, `amount`, `addedDate`, `lastModified`. +* `CREATE_ASSEMBLY_USE_IPN_PLACEHOLDER_IN_NAME`: Use an %%ipn%% placeholder in the name of a assembly. Placeholder is replaced with the ipn input while saving. ### History/Eventlog-related settings diff --git a/migrations/Version20251016141941.php b/migrations/Version20251016141941.php new file mode 100644 index 000000000..f5e57b641 --- /dev/null +++ b/migrations/Version20251016141941.php @@ -0,0 +1,236 @@ +addSql(<<<'SQL' + CREATE TABLE assemblies ( + id INT AUTO_INCREMENT NOT NULL, + parent_id INT DEFAULT NULL, + id_preview_attachment INT DEFAULT NULL, + name VARCHAR(255) NOT NULL, + comment LONGTEXT NOT NULL, + not_selectable TINYINT(1) NOT NULL, + alternative_names LONGTEXT DEFAULT NULL, + order_quantity INT NOT NULL, + status VARCHAR(64) DEFAULT NULL, + ipn VARCHAR(100) DEFAULT NULL, + order_only_missing_parts TINYINT(1) NOT NULL, + description LONGTEXT NOT NULL, + last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + INDEX IDX_5F3832C0727ACA70 (parent_id), + INDEX IDX_5F3832C0EA7100A1 (id_preview_attachment), + UNIQUE INDEX UNIQ_5F3832C03D721C14 (ipn), + INDEX assembly_idx_ipn (ipn), + PRIMARY KEY(id) + ) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` + SQL); + $this->addSql(<<<'SQL' + ALTER TABLE assemblies + ADD CONSTRAINT FK_5F3832C0727ACA70 FOREIGN KEY (parent_id) REFERENCES assemblies (id) + SQL); + $this->addSql(<<<'SQL' + ALTER TABLE assemblies + ADD CONSTRAINT FK_5F3832C0EA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES `attachments` (id) ON DELETE SET NULL + SQL); + + $this->addSql(<<<'SQL' + CREATE TABLE assembly_bom_entries ( + id INT AUTO_INCREMENT NOT NULL, + id_assembly INT DEFAULT NULL, + id_part INT DEFAULT NULL, + id_referenced_assembly INT DEFAULT NULL, + quantity DOUBLE PRECISION NOT NULL, + mountnames LONGTEXT NOT NULL, + designator LONGTEXT NOT NULL, + name VARCHAR(255) DEFAULT NULL, + comment LONGTEXT NOT NULL, + price NUMERIC(11, 5) DEFAULT NULL, + price_currency_id INT DEFAULT NULL, + last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + INDEX IDX_8C74887E4AD2039E (id_assembly), + INDEX IDX_8C74887EC22F6CC4 (id_part), + INDEX IDX_8C74887E22522999 (id_referenced_assembly), + INDEX IDX_8C74887E3FFDCD60 (price_currency_id), + PRIMARY KEY(id) + ) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` + SQL); + $this->addSql(<<<'SQL' + ALTER TABLE assembly_bom_entries + ADD CONSTRAINT FK_8C74887E4AD2039E FOREIGN KEY (id_assembly) REFERENCES assemblies (id) + SQL); + $this->addSql(<<<'SQL' + ALTER TABLE assembly_bom_entries + ADD CONSTRAINT FK_8C74887EC22F6CC4 FOREIGN KEY (id_part) REFERENCES `parts` (id) + SQL); + $this->addSql(<<<'SQL' + ALTER TABLE assembly_bom_entries + ADD CONSTRAINT FK_8C74887E22522999 FOREIGN KEY (id_referenced_assembly) REFERENCES assemblies (id) ON DELETE SET NULL + SQL); + $this->addSql(<<<'SQL' + ALTER TABLE assembly_bom_entries + ADD CONSTRAINT FK_8C74887E3FFDCD60 FOREIGN KEY (price_currency_id) REFERENCES currencies (id) + SQL); + } + + public function mySQLDown(Schema $schema): void + { + $this->addSql('DROP TABLE assembly_bom_entries'); + $this->addSql('DROP TABLE assemblies'); + } + + public function sqLiteUp(Schema $schema): void + { + $this->addSql(<<<'SQL' + CREATE TABLE assemblies ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + parent_id INTEGER DEFAULT NULL, + id_preview_attachment INTEGER DEFAULT NULL, + order_quantity INTEGER NOT NULL, + order_only_missing_parts BOOLEAN NOT NULL, + comment CLOB NOT NULL, + not_selectable BOOLEAN NOT NULL, + name VARCHAR(255) NOT NULL, + last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + status VARCHAR(64) DEFAULT NULL, + ipn VARCHAR(100) DEFAULT NULL, + description CLOB NOT NULL, + alternative_names CLOB DEFAULT NULL, + CONSTRAINT FK_5F3832C0727ACA70 FOREIGN KEY (parent_id) REFERENCES assemblies (id) NOT DEFERRABLE INITIALLY IMMEDIATE, + CONSTRAINT FK_5F3832C0EA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES "attachments" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE + ) + SQL); + $this->addSql('CREATE INDEX IDX_5F3832C0727ACA70 ON assemblies (parent_id)'); + $this->addSql('CREATE INDEX IDX_5F3832C0EA7100A1 ON assemblies (id_preview_attachment)'); + $this->addSql('CREATE UNIQUE INDEX UNIQ_5F3832C03D721C14 ON assemblies (ipn)'); + $this->addSql('CREATE INDEX assembly_idx_ipn ON assemblies (ipn)'); + + $this->addSql(<<<'SQL' + CREATE TABLE assembly_bom_entries ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + id_assembly INTEGER DEFAULT NULL, + id_part INTEGER DEFAULT NULL, + id_referenced_assembly INTEGER DEFAULT NULL, + price_currency_id INTEGER DEFAULT NULL, + quantity DOUBLE PRECISION NOT NULL, + mountnames CLOB NOT NULL, + designator CLOB NOT NULL, + name VARCHAR(255) DEFAULT NULL, + comment CLOB NOT NULL, + price NUMERIC(11, 5) DEFAULT NULL, + last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + CONSTRAINT FK_8C74887E4AD2039E FOREIGN KEY (id_assembly) REFERENCES assemblies (id) NOT DEFERRABLE INITIALLY IMMEDIATE, + CONSTRAINT FK_8C74887EC22F6CC4 FOREIGN KEY (id_part) REFERENCES "parts" (id) NOT DEFERRABLE INITIALLY IMMEDIATE, + CONSTRAINT FK_8C74887E22522999 FOREIGN KEY (id_referenced_assembly) REFERENCES assemblies (id) ON UPDATE NO ACTION ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE, + CONSTRAINT FK_8C74887E3FFDCD60 FOREIGN KEY (price_currency_id) REFERENCES currencies (id) NOT DEFERRABLE INITIALLY IMMEDIATE + ) + SQL); + $this->addSql('CREATE INDEX IDX_8C74887E4AD2039E ON assembly_bom_entries (id_assembly)'); + $this->addSql('CREATE INDEX IDX_8C74887EC22F6CC4 ON assembly_bom_entries (id_part)'); + $this->addSql('CREATE INDEX IDX_8C74887E22522999 ON assembly_bom_entries (id_referenced_assembly)'); + $this->addSql('CREATE INDEX IDX_8C74887E3FFDCD60 ON assembly_bom_entries (price_currency_id)'); + } + + public function sqLiteDown(Schema $schema): void + { + $this->addSql('DROP TABLE assembly_bom_entries'); + $this->addSql('DROP TABLE assemblies'); + } + + public function postgreSQLUp(Schema $schema): void + { + $this->addSql(<<<'SQL' + CREATE TABLE assemblies ( + id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + name VARCHAR(255) NOT NULL, + last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, + datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, + comment TEXT NOT NULL, + not_selectable BOOLEAN NOT NULL, + alternative_names TEXT DEFAULT NULL, + order_quantity INT NOT NULL, + status VARCHAR(64) DEFAULT NULL, + ipn VARCHAR(100) DEFAULT NULL, + order_only_missing_parts BOOLEAN NOT NULL, + description TEXT NOT NULL, + parent_id INT DEFAULT NULL, + id_preview_attachment INT DEFAULT NULL, + PRIMARY KEY(id) + ) + SQL); + $this->addSql('CREATE INDEX IDX_5F3832C0727ACA70 ON assemblies (parent_id)'); + $this->addSql('CREATE INDEX IDX_5F3832C0EA7100A1 ON assemblies (id_preview_attachment)'); + $this->addSql('CREATE UNIQUE INDEX UNIQ_5F3832C03D721C14 ON assemblies (ipn)'); + $this->addSql('CREATE INDEX assembly_idx_ipn ON assemblies (ipn)'); + $this->addSql(<<<'SQL' + ALTER TABLE assemblies + ADD CONSTRAINT FK_5F3832C0727ACA70 FOREIGN KEY (parent_id) REFERENCES assemblies (id) NOT DEFERRABLE INITIALLY IMMEDIATE + SQL); + $this->addSql(<<<'SQL' + ALTER TABLE assemblies + ADD CONSTRAINT FK_5F3832C0EA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES "attachments" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE + SQL); + + $this->addSql(<<<'SQL' + CREATE TABLE assembly_bom_entries ( + id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + id_assembly INT DEFAULT NULL, + id_part INT DEFAULT NULL, + id_referenced_assembly INT DEFAULT NULL, + quantity DOUBLE PRECISION NOT NULL, + mountnames TEXT NOT NULL, + designator TEXT NOT NULL, + name VARCHAR(255) DEFAULT NULL, + comment TEXT NOT NULL, + price NUMERIC(11, 5) DEFAULT NULL, + price_currency_id INT DEFAULT NULL, + last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, + datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, + PRIMARY KEY(id) + ) + SQL); + $this->addSql('CREATE INDEX IDX_8C74887E4AD2039E ON assembly_bom_entries (id_assembly)'); + $this->addSql('CREATE INDEX IDX_8C74887EC22F6CC4 ON assembly_bom_entries (id_part)'); + $this->addSql('CREATE INDEX IDX_8C74887E22522999 ON assembly_bom_entries (id_referenced_assembly)'); + $this->addSql('CREATE INDEX IDX_8C74887E3FFDCD60 ON assembly_bom_entries (price_currency_id)'); + $this->addSql(<<<'SQL' + ALTER TABLE assembly_bom_entries + ADD CONSTRAINT FK_8C74887E4AD2039E FOREIGN KEY (id_assembly) REFERENCES assemblies (id) NOT DEFERRABLE INITIALLY IMMEDIATE + SQL); + $this->addSql(<<<'SQL' + ALTER TABLE assembly_bom_entries + ADD CONSTRAINT FK_8C74887EC22F6CC4 FOREIGN KEY (id_part) REFERENCES "parts" (id) NOT DEFERRABLE INITIALLY IMMEDIATE + SQL); + $this->addSql(<<<'SQL' + ALTER TABLE assembly_bom_entries + ADD CONSTRAINT FK_8C74887E22522999 FOREIGN KEY (id_referenced_assembly) REFERENCES assemblies (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE + SQL); + $this->addSql(<<<'SQL' + ALTER TABLE assembly_bom_entries + ADD CONSTRAINT FK_8C74887E3FFDCD60 FOREIGN KEY (price_currency_id) REFERENCES currencies (id) NOT DEFERRABLE INITIALLY IMMEDIATE + SQL); + } + + public function postgreSQLDown(Schema $schema): void + { + $this->addSql('DROP TABLE assembly_bom_entries'); + $this->addSql('DROP TABLE assemblies'); + } +} diff --git a/src/Command/Migrations/ConvertBBCodeCommand.php b/src/Command/Migrations/ConvertBBCodeCommand.php index 201263ffd..b0c083921 100644 --- a/src/Command/Migrations/ConvertBBCodeCommand.php +++ b/src/Command/Migrations/ConvertBBCodeCommand.php @@ -22,6 +22,7 @@ namespace App\Command\Migrations; +use App\Entity\AssemblySystem\Assembly; use Symfony\Component\Console\Attribute\AsCommand; use App\Entity\Attachments\AttachmentType; use App\Entity\Base\AbstractNamedDBElement; @@ -88,6 +89,7 @@ protected function getTargetsLists(): array AttachmentType::class => ['comment'], StorageLocation::class => ['comment'], Project::class => ['comment'], + Assembly::class => ['comment'], Category::class => ['comment'], Manufacturer::class => ['comment'], MeasurementUnit::class => ['comment'], diff --git a/src/Controller/AdminPages/AssemblyAdminController.php b/src/Controller/AdminPages/AssemblyAdminController.php new file mode 100644 index 000000000..20f640923 --- /dev/null +++ b/src/Controller/AdminPages/AssemblyAdminController.php @@ -0,0 +1,80 @@ +. + */ + +declare(strict_types=1); + +namespace App\Controller\AdminPages; + +use App\Entity\AssemblySystem\Assembly; +use App\Entity\Attachments\AssemblyAttachment; +use App\Entity\Parameters\AssemblyParameter; +use App\Form\AdminPages\AssemblyAdminForm; +use App\Services\ImportExportSystem\EntityExporter; +use App\Services\ImportExportSystem\EntityImporter; +use App\Services\Trees\StructuralElementRecursionHelper; +use Doctrine\ORM\EntityManagerInterface; +use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Routing\Attribute\Route; + +#[Route(path: '/assembly')] +class AssemblyAdminController extends BaseAdminController +{ + protected string $entity_class = Assembly::class; + protected string $twig_template = 'admin/assembly_admin.html.twig'; + protected string $form_class = AssemblyAdminForm::class; + protected string $route_base = 'assembly'; + protected string $attachment_class = AssemblyAttachment::class; + protected ?string $parameter_class = AssemblyParameter::class; + + #[Route(path: '/{id}', name: 'assembly_delete', methods: ['DELETE'])] + public function delete(Request $request, Assembly $entity, StructuralElementRecursionHelper $recursionHelper): RedirectResponse + { + return $this->_delete($request, $entity, $recursionHelper); + } + + #[Route(path: '/{id}/edit/{timestamp}', name: 'assembly_edit', requirements: ['id' => '\d+'])] + #[Route(path: '/{id}/edit', requirements: ['id' => '\d+'])] + public function edit(Assembly $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null): Response + { + return $this->_edit($entity, $request, $em, $timestamp); + } + + #[Route(path: '/new', name: 'assembly_new')] + #[Route(path: '/{id}/clone', name: 'assembly_clone')] + #[Route(path: '/')] + public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer, ?Assembly $entity = null): Response + { + return $this->_new($request, $em, $importer, $entity); + } + + #[Route(path: '/export', name: 'assembly_export_all')] + public function exportAll(EntityManagerInterface $em, EntityExporter $exporter, Request $request): Response + { + return $this->_exportAll($em, $exporter, $request); + } + + #[Route(path: '/{id}/export', name: 'assembly_export')] + public function exportEntity(Assembly $entity, EntityExporter $exporter, Request $request): Response + { + return $this->_exportEntity($entity, $exporter, $request); + } +} diff --git a/src/Controller/AdminPages/BaseAdminController.php b/src/Controller/AdminPages/BaseAdminController.php index edc5917ac..d928deb41 100644 --- a/src/Controller/AdminPages/BaseAdminController.php +++ b/src/Controller/AdminPages/BaseAdminController.php @@ -23,6 +23,8 @@ namespace App\Controller\AdminPages; use App\DataTables\LogDataTable; +use App\Entity\AssemblySystem\Assembly; +use App\Entity\AssemblySystem\AssemblyBOMEntry; use App\Entity\Attachments\Attachment; use App\Entity\Attachments\AttachmentContainingDBElement; use App\Entity\Attachments\AttachmentUpload; @@ -193,6 +195,15 @@ protected function _edit(AbstractNamedDBElement $entity, Request $request, Entit $entity->setMasterPictureAttachment(null); } + if ($entity instanceof Assembly) { + /* Replace ipn placeholder with the IPN information if applicable. + * The '%%ipn%%' placeholder is automatically inserted into the Name property, + * depending on CREATE_ASSEMBLY_USE_IPN_PLACEHOLDER_IN_NAME, when creating a new one, + * to avoid having to insert it manually */ + + $entity->setName(str_ireplace('%%ipn%%', $entity->getIpn() ?? '', $entity->getName())); + } + $this->commentHelper->setMessage($form['log_comment']->getData()); $em->persist($entity); @@ -286,6 +297,15 @@ protected function _new(Request $request, EntityManagerInterface $em, EntityImpo $new_entity->setMasterPictureAttachment(null); } + if ($new_entity instanceof Assembly) { + /* Replace ipn placeholder with the IPN information if applicable. + * The '%%ipn%%' placeholder is automatically inserted into the Name property, + * depending on CREATE_ASSEMBLY_USE_IPN_PLACEHOLDER_IN_NAME, when creating a new one, + * to avoid having to insert it manually */ + + $new_entity->setName(str_ireplace('%%ipn%%', $new_entity->getIpn() ?? '', $new_entity->getName())); + } + $this->commentHelper->setMessage($form['log_comment']->getData()); $em->persist($new_entity); $em->flush(); @@ -434,6 +454,10 @@ protected function _delete(Request $request, AbstractNamedDBElement $entity, Str return $this->redirectToRoute($this->route_base.'_edit', ['id' => $entity->getID()]); } } else { + if ($entity instanceof Assembly) { + $this->markReferencedBomEntry($entity); + } + if ($entity instanceof AbstractStructuralDBElement) { $parent = $entity->getParent(); @@ -481,4 +505,16 @@ protected function _exportEntity(AbstractNamedDBElement $entity, EntityExporter return $exporter->exportEntityFromRequest($entity, $request); } + + private function markReferencedBomEntry(Assembly $referencedAssembly): void + { + $bomEntries = $this->entityManager->getRepository(AssemblyBOMEntry::class)->findBy(['referencedAssembly' => $referencedAssembly]); + + foreach ($bomEntries as $entry) { + $entry->setReferencedAssembly(null); + $entry->setName($referencedAssembly->getName(). ' DELETED'); + + $this->entityManager->persist($entry); + } + } } diff --git a/src/Controller/AssemblyController.php b/src/Controller/AssemblyController.php new file mode 100644 index 000000000..be97045b5 --- /dev/null +++ b/src/Controller/AssemblyController.php @@ -0,0 +1,318 @@ +. + */ +namespace App\Controller; + +use App\DataTables\AssemblyBomEntriesDataTable; +use App\DataTables\AssemblyDataTable; +use App\DataTables\ErrorDataTable; +use App\DataTables\Filters\AssemblyFilter; +use App\Entity\AssemblySystem\Assembly; +use App\Entity\AssemblySystem\AssemblyBOMEntry; +use App\Entity\Parts\Part; +use App\Exceptions\InvalidRegexException; +use App\Form\AssemblySystem\AssemblyAddPartsType; +use App\Form\Filters\AssemblyFilterType; +use App\Services\ImportExportSystem\BOMImporter; +use App\Services\Trees\NodesListBuilder; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\DBAL\Exception\DriverException; +use Doctrine\ORM\EntityManagerInterface; +use League\Csv\SyntaxError; +use Omines\DataTablesBundle\DataTableFactory; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\Form\Extension\Core\Type\CheckboxType; +use Symfony\Component\Form\Extension\Core\Type\ChoiceType; +use Symfony\Component\Form\Extension\Core\Type\FileType; +use Symfony\Component\Form\Extension\Core\Type\SubmitType; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Routing\Attribute\Route; +use Symfony\Component\Validator\Validator\ValidatorInterface; + +use Symfony\Contracts\Translation\TranslatorInterface; +use function Symfony\Component\Translation\t; + +#[Route(path: '/assembly')] +class AssemblyController extends AbstractController +{ + public function __construct( + private readonly DataTableFactory $dataTableFactory, + private readonly TranslatorInterface $translator, + private readonly NodesListBuilder $nodesListBuilder + ) { + } + + #[Route(path: '/list', name: 'assemblies_list')] + public function showAll(Request $request): Response + { + return $this->showListWithFilter($request,'assemblies/lists/all_list.html.twig'); + } + + /** + * Common implementation for the part list pages. + * @param Request $request The request to parse + * @param string $template The template that should be rendered + * @param callable|null $filter_changer A function that is called with the filter object as parameter. This function can be used to customize the filter + * @param callable|null $form_changer A function that is called with the form object as parameter. This function can be used to customize the form + * @param array $additonal_template_vars Any additional template variables that should be passed to the template + * @param array $additional_table_vars Any additional variables that should be passed to the table creation + */ + protected function showListWithFilter(Request $request, string $template, ?callable $filter_changer = null, ?callable $form_changer = null, array $additonal_template_vars = [], array $additional_table_vars = []): Response + { + $this->denyAccessUnlessGranted('@assemblies.read'); + + $formRequest = clone $request; + $formRequest->setMethod('GET'); + $filter = new AssemblyFilter($this->nodesListBuilder); + if($filter_changer !== null){ + $filter_changer($filter); + } + + $filterForm = $this->createForm(AssemblyFilterType::class, $filter, ['method' => 'GET']); + if($form_changer !== null) { + $form_changer($filterForm); + } + + $filterForm->handleRequest($formRequest); + + $table = $this->dataTableFactory->createFromType( + AssemblyDataTable::class, + array_merge(['filter' => $filter], $additional_table_vars), + ['lengthMenu' => AssemblyDataTable::LENGTH_MENU] + ) + ->handleRequest($request); + + if ($table->isCallback()) { + try { + try { + return $table->getResponse(); + } catch (DriverException $driverException) { + if ($driverException->getCode() === 1139) { + //Convert the driver exception to InvalidRegexException so it has the same handler as for SQLite + throw InvalidRegexException::fromDriverException($driverException); + } else { + throw $driverException; + } + } + } catch (InvalidRegexException $exception) { + $errors = $this->translator->trans('assembly.table.invalid_regex').': '.$exception->getReason(); + $request->request->set('order', []); + + return ErrorDataTable::errorTable($this->dataTableFactory, $request, $errors); + } + } + + return $this->render($template, array_merge([ + 'datatable' => $table, + 'filterForm' => $filterForm->createView(), + ], $additonal_template_vars)); + } + + #[Route(path: '/{id}/info', name: 'assembly_info', requirements: ['id' => '\d+'])] + public function info(Assembly $assembly, Request $request): Response + { + $this->denyAccessUnlessGranted('read', $assembly); + + $table = $this->dataTableFactory->createFromType(AssemblyBomEntriesDataTable::class, ['assembly' => $assembly]) + ->handleRequest($request); + + if ($table->isCallback()) { + return $table->getResponse(); + } + + return $this->render('assemblies/info/info.html.twig', [ + 'datatable' => $table, + 'assembly' => $assembly, + ]); + } + + #[Route(path: '/{id}/import_bom', name: 'assembly_import_bom', requirements: ['id' => '\d+'])] + public function importBOM(Request $request, EntityManagerInterface $entityManager, Assembly $assembly, + BOMImporter $BOMImporter, ValidatorInterface $validator): Response + { + $this->denyAccessUnlessGranted('edit', $assembly); + + $builder = $this->createFormBuilder(); + $builder->add('file', FileType::class, [ + 'label' => 'import.file', + 'required' => true, + 'attr' => [ + 'accept' => '.csv, .json' + ] + ]); + $builder->add('type', ChoiceType::class, [ + 'label' => 'assembly.bom_import.type', + 'required' => true, + 'choices' => [ + 'assembly.bom_import.type.json' => 'json', + 'assembly.bom_import.type.csv' => 'csv', + 'assembly.bom_import.type.kicad_pcbnew' => 'kicad_pcbnew', + 'assembly.bom_import.type.kicad_schematic' => 'kicad_schematic', + ] + ]); + $builder->add('clear_existing_bom', CheckboxType::class, [ + 'label' => 'assembly.bom_import.clear_existing_bom', + 'required' => false, + 'data' => false, + 'help' => 'assembly.bom_import.clear_existing_bom.help', + ]); + $builder->add('submit', SubmitType::class, [ + 'label' => 'import.btn', + ]); + + $form = $builder->getForm(); + + $form->handleRequest($request); + if ($form->isSubmitted() && $form->isValid()) { + // Clear existing entries if requested + if ($form->get('clear_existing_bom')->getData()) { + $assembly->getBomEntries()->clear(); + $entityManager->flush(); + } + + try { + $importerResult = $BOMImporter->importFileIntoAssembly($form->get('file')->getData(), $assembly, [ + 'type' => $form->get('type')->getData(), + ]); + + //Validate the assembly entries + $errors = $validator->validateProperty($assembly, 'bom_entries'); + + //If no validation errors occured, save the changes and redirect to edit page + if (count ($errors) === 0 && $importerResult->getViolations()->count() === 0) { + $entries = $importerResult->getBomEntries(); + + $this->addFlash('success', t('assembly.bom_import.flash.success', ['%count%' => count($entries)])); + $entityManager->flush(); + + return $this->redirectToRoute('assembly_edit', ['id' => $assembly->getID()]); + } + + //Show validation errors + $this->addFlash('error', t('assembly.bom_import.flash.invalid_entries')); + } catch (\UnexpectedValueException|\RuntimeException|SyntaxError $e) { + $this->addFlash('error', t('assembly.bom_import.flash.invalid_file', ['%message%' => $e->getMessage()])); + } + } + + $jsonTemplate = [ + [ + "quantity" => 1.0, + "name" => $this->translator->trans('assembly.bom_import.template.entry.name'), + "part" => [ + "id" => null, + "ipn" => $this->translator->trans('assembly.bom_import.template.entry.part.ipn'), + "mpnr" => $this->translator->trans('assembly.bom_import.template.entry.part.mpnr'), + "name" => $this->translator->trans('assembly.bom_import.template.entry.part.name'), + "description" => null, + "manufacturer" => [ + "id" => null, + "name" => $this->translator->trans('assembly.bom_import.template.entry.part.manufacturer.name') + ], + "category" => [ + "id" => null, + "name" => $this->translator->trans('assembly.bom_import.template.entry.part.category.name') + ] + ] + ] + ]; + + return $this->render('assemblies/import_bom.html.twig', [ + 'assembly' => $assembly, + 'jsonTemplate' => $jsonTemplate, + 'form' => $form, + 'validationErrors' => $errors ?? null, + 'importerErrors' => isset($importerResult) ? $importerResult->getViolations() : null, + ]); + } + + #[Route(path: '/add_parts', name: 'assembly_add_parts_no_id')] + #[Route(path: '/{id}/add_parts', name: 'assembly_add_parts', requirements: ['id' => '\d+'])] + public function addPart(Request $request, EntityManagerInterface $entityManager, ?Assembly $assembly): Response + { + if($assembly instanceof Assembly) { + $this->denyAccessUnlessGranted('edit', $assembly); + } else { + $this->denyAccessUnlessGranted('@assemblies.edit'); + } + + $form = $this->createForm(AssemblyAddPartsType::class, null, [ + 'assembly' => $assembly, + ]); + + //Preset the BOM entries with the selected parts, when the form was not submitted yet + $preset_data = new ArrayCollection(); + foreach (explode(',', (string) $request->get('parts', '')) as $part_id) { + //Skip empty part IDs. Postgres seems to be especially sensitive to empty strings, as it does not allow them in integer columns + if ($part_id === '') { + continue; + } + + $part = $entityManager->getRepository(Part::class)->find($part_id); + if (null !== $part) { + //If there is already a BOM entry for this part, we use this one (we edit it then) + $bom_entry = $entityManager->getRepository(AssemblyBOMEntry::class)->findOneBy([ + 'assembly' => $assembly, + 'part' => $part + ]); + if ($bom_entry !== null) { + $preset_data->add($bom_entry); + } else { //Otherwise create an empty one + $entry = new AssemblyBOMEntry(); + $entry->setAssembly($assembly); + $entry->setPart($part); + $preset_data->add($entry); + } + } + } + $form['bom_entries']->setData($preset_data); + + $form->handleRequest($request); + if ($form->isSubmitted() && $form->isValid()) { + $target_assembly = $assembly ?? $form->get('assembly')->getData(); + + //Ensure that we really have acces to the selected assembly + $this->denyAccessUnlessGranted('edit', $target_assembly); + + $data = $form->getData(); + $bom_entries = $data['bom_entries']; + foreach ($bom_entries as $bom_entry){ + $target_assembly->addBOMEntry($bom_entry); + } + + $entityManager->flush(); + + //If a redirect query parameter is set, redirect to this page + if ($request->query->get('_redirect')) { + return $this->redirect($request->query->get('_redirect')); + } + //Otherwise just show the assembly info page + return $this->redirectToRoute('assembly_info', ['id' => $target_assembly->getID()]); + } + + return $this->render('assemblies/add_parts.html.twig', [ + 'assembly' => $assembly, + 'form' => $form, + ]); + } +} diff --git a/src/Controller/ProjectController.php b/src/Controller/ProjectController.php index 2a6d19ee2..e510506f3 100644 --- a/src/Controller/ProjectController.php +++ b/src/Controller/ProjectController.php @@ -46,14 +46,16 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Validator\Validator\ValidatorInterface; - +use Symfony\Contracts\Translation\TranslatorInterface; use function Symfony\Component\Translation\t; #[Route(path: '/project')] class ProjectController extends AbstractController { - public function __construct(private readonly DataTableFactory $dataTableFactory) - { + public function __construct( + private readonly DataTableFactory $dataTableFactory, + private readonly TranslatorInterface $translator, + ) { } #[Route(path: '/{id}/info', name: 'project_info', requirements: ['id' => '\d+'])] @@ -147,6 +149,8 @@ public function importBOM( 'label' => 'project.bom_import.type', 'required' => true, 'choices' => [ + 'project.bom_import.type.json' => 'json', + 'project.bom_import.type.csv' => 'csv', 'project.bom_import.type.kicad_pcbnew' => 'kicad_pcbnew', 'project.bom_import.type.kicad_schematic' => 'kicad_schematic', 'project.bom_import.type.generic_csv' => 'generic_csv', @@ -189,17 +193,20 @@ public function importBOM( } // For PCB imports, proceed directly - $entries = $BOMImporter->importFileIntoProject($form->get('file')->getData(), $project, [ + $importerResult = $BOMImporter->importFileIntoProject($form->get('file')->getData(), $project, [ 'type' => $import_type, ]); // Validate the project entries $errors = $validator->validateProperty($project, 'bom_entries'); - // If no validation errors occurred, save the changes and redirect to edit page - if (count($errors) === 0) { + //If no validation errors occurred, save the changes and redirect to edit page + if (count($errors) === 0 && $importerResult->getViolations()->count() === 0) { + $entries = $importerResult->getBomEntries(); + $this->addFlash('success', t('project.bom_import.flash.success', ['%count%' => count($entries)])); $entityManager->flush(); + return $this->redirectToRoute('project_edit', ['id' => $project->getID()]); } @@ -211,10 +218,29 @@ public function importBOM( } } + $jsonTemplate = [ + [ + "quantity" => 1.0, + "name" => $this->translator->trans('project.bom_import.template.entry.name'), + "part" => [ + "id" => null, + "ipn" => $this->translator->trans('project.bom_import.template.entry.part.ipn'), + "mpnr" => $this->translator->trans('project.bom_import.template.entry.part.mpnr'), + "name" => $this->translator->trans('project.bom_import.template.entry.part.name'), + "manufacturer" => [ + "id" => null, + "name" => $this->translator->trans('project.bom_import.template.entry.part.manufacturer.name') + ], + ] + ] + ]; + return $this->render('projects/import_bom.html.twig', [ 'project' => $project, + 'jsonTemplate' => $jsonTemplate, 'form' => $form, - 'errors' => $errors ?? null, + 'validationErrors' => $errors ?? null, + 'importerErrors' => isset($importerResult) ? $importerResult->getViolations() : null, ]); } @@ -395,7 +421,7 @@ public function importBOMMapFields( } // Import with field mapping and priorities (validation already passed) - $entries = $BOMImporter->stringToBOMEntries($file_content, [ + $entries = $BOMImporter->stringToBOMEntries($project, $file_content, [ 'type' => 'kicad_schematic', 'field_mapping' => $field_mapping, 'field_priorities' => $field_priorities, diff --git a/src/Controller/TreeController.php b/src/Controller/TreeController.php index 71f8ba5c6..0ba3a1584 100644 --- a/src/Controller/TreeController.php +++ b/src/Controller/TreeController.php @@ -22,6 +22,7 @@ namespace App\Controller; +use App\Entity\AssemblySystem\Assembly; use Symfony\Component\HttpFoundation\Response; use App\Entity\ProjectSystem\Project; use App\Entity\Parts\Category; @@ -129,4 +130,17 @@ public function deviceTree(?Project $device = null): JsonResponse return new JsonResponse($tree); } + + #[Route(path: '/assembly/{id}', name: 'tree_assembly')] + #[Route(path: '/assemblies', name: 'tree_assembly_root')] + public function assemblyTree(?Assembly $assembly = null): JsonResponse + { + if ($this->isGranted('@assemblies.read')) { + $tree = $this->treeGenerator->getTreeView(Assembly::class, $assembly, 'assemblies'); + } else { + return new JsonResponse("Access denied", Response::HTTP_FORBIDDEN); + } + + return new JsonResponse($tree); + } } diff --git a/src/Controller/TypeaheadController.php b/src/Controller/TypeaheadController.php index 89eac7ff7..246c7fee6 100644 --- a/src/Controller/TypeaheadController.php +++ b/src/Controller/TypeaheadController.php @@ -22,7 +22,9 @@ namespace App\Controller; +use App\Entity\AssemblySystem\Assembly; use App\Entity\Parameters\AbstractParameter; +use App\Services\Attachments\AssemblyPreviewGenerator; use Symfony\Component\HttpFoundation\Response; use App\Entity\Attachments\Attachment; use App\Entity\Parts\Category; @@ -53,6 +55,8 @@ use Symfony\Component\Serializer\Encoder\JsonEncoder; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; use Symfony\Component\Serializer\Serializer; +use Symfony\Contracts\Translation\TranslatorInterface; +use InvalidArgumentException; /** * In this controller the endpoints for the typeaheads are collected. @@ -60,8 +64,11 @@ #[Route(path: '/typeahead')] class TypeaheadController extends AbstractController { - public function __construct(protected AttachmentURLGenerator $urlGenerator, protected Packages $assets) - { + public function __construct( + protected AttachmentURLGenerator $urlGenerator, + protected Packages $assets, + protected TranslatorInterface $translator + ) { } #[Route(path: '/builtInResources/search', name: 'typeahead_builtInRessources')] @@ -109,19 +116,22 @@ private function typeToParameterClass(string $type): string 'group' => GroupParameter::class, 'measurement_unit' => MeasurementUnitParameter::class, 'currency' => Currency::class, - default => throw new \InvalidArgumentException('Invalid parameter type: '.$type), + default => throw new InvalidArgumentException('Invalid parameter type: '.$type), }; } #[Route(path: '/parts/search/{query}', name: 'typeahead_parts')] - public function parts(EntityManagerInterface $entityManager, PartPreviewGenerator $previewGenerator, - AttachmentURLGenerator $attachmentURLGenerator, string $query = ""): JsonResponse - { + public function parts( + EntityManagerInterface $entityManager, + PartPreviewGenerator $previewGenerator, + AttachmentURLGenerator $attachmentURLGenerator, + string $query = "" + ): JsonResponse { $this->denyAccessUnlessGranted('@parts.read'); - $repo = $entityManager->getRepository(Part::class); + $partRepository = $entityManager->getRepository(Part::class); - $parts = $repo->autocompleteSearch($query, 100); + $parts = $partRepository->autocompleteSearch($query, 100); $data = []; foreach ($parts as $part) { @@ -141,12 +151,50 @@ public function parts(EntityManagerInterface $entityManager, PartPreviewGenerato 'footprint' => $part->getFootprint() instanceof Footprint ? $part->getFootprint()->getName() : '', 'description' => mb_strimwidth($part->getDescription(), 0, 127, '...'), 'image' => $preview_url, - ]; + ]; } return new JsonResponse($data); } + #[Route(path: '/assemblies/search/{query}', name: 'typeahead_assemblies')] + public function assemblies( + EntityManagerInterface $entityManager, + AssemblyPreviewGenerator $assemblyPreviewGenerator, + AttachmentURLGenerator $attachmentURLGenerator, + string $query = "" + ): JsonResponse { + $this->denyAccessUnlessGranted('@assemblies.read'); + + $result = []; + + $assemblyRepository = $entityManager->getRepository(Assembly::class); + + $assemblies = $assemblyRepository->autocompleteSearch($query, 100); + + foreach ($assemblies as $assembly) { + $preview_attachment = $assemblyPreviewGenerator->getTablePreviewAttachment($assembly); + + if($preview_attachment instanceof Attachment) { + $preview_url = $attachmentURLGenerator->getThumbnailURL($preview_attachment, 'thumbnail_sm'); + } else { + $preview_url = ''; + } + + /** @var Assembly $assembly */ + $result[] = [ + 'id' => $assembly->getID(), + 'name' => $assembly->getName(), + 'category' => '', + 'footprint' => '', + 'description' => mb_strimwidth($assembly->getDescription(), 0, 127, '...'), + 'image' => $preview_url, + ]; + } + + return new JsonResponse($result); + } + #[Route(path: '/parameters/{type}/search/{query}', name: 'typeahead_parameters', requirements: ['type' => '.+'])] public function parameters(string $type, EntityManagerInterface $entityManager, string $query = ""): JsonResponse { diff --git a/src/DataFixtures/DataStructureFixtures.php b/src/DataFixtures/DataStructureFixtures.php index fc713d4df..6dd6cfe18 100644 --- a/src/DataFixtures/DataStructureFixtures.php +++ b/src/DataFixtures/DataStructureFixtures.php @@ -22,6 +22,7 @@ namespace App\DataFixtures; +use App\Entity\AssemblySystem\Assembly; use App\Entity\Attachments\AttachmentType; use App\Entity\Base\AbstractStructuralDBElement; use App\Entity\ProjectSystem\Project; @@ -49,8 +50,8 @@ public function __construct(protected EntityManagerInterface $em) public function load(ObjectManager $manager): void { //Reset autoincrement - $types = [AttachmentType::class, Project::class, Category::class, Footprint::class, Manufacturer::class, - MeasurementUnit::class, StorageLocation::class, Supplier::class,]; + $types = [AttachmentType::class, Project::class, Assembly::class, Category::class, Footprint::class, + Manufacturer::class, MeasurementUnit::class, StorageLocation::class, Supplier::class,]; foreach ($types as $type) { $this->createNodesForClass($type, $manager); diff --git a/src/DataFixtures/GroupFixtures.php b/src/DataFixtures/GroupFixtures.php index d8e54b9f5..ddb74b1cc 100644 --- a/src/DataFixtures/GroupFixtures.php +++ b/src/DataFixtures/GroupFixtures.php @@ -58,6 +58,7 @@ public function load(ObjectManager $manager): void $users->setName('users'); $this->permission_presets->applyPreset($users, PermissionPresetsHelper::PRESET_EDITOR); $this->addDevicesPermissions($users); + $this->addAssemblyPermissions($users); $this->setReference(self::USERS, $users); $manager->persist($users); @@ -69,4 +70,9 @@ private function addDevicesPermissions(Group $group): void $this->permissionManager->setAllOperationsOfPermission($group, 'projects', true); } + private function addAssemblyPermissions(Group $group): void + { + $this->permissionManager->setAllOperationsOfPermission($group, 'assemblies', true); + } + } diff --git a/src/DataTables/AssemblyBomEntriesDataTable.php b/src/DataTables/AssemblyBomEntriesDataTable.php new file mode 100644 index 000000000..90924cfe1 --- /dev/null +++ b/src/DataTables/AssemblyBomEntriesDataTable.php @@ -0,0 +1,241 @@ +. + */ +namespace App\DataTables; + +use App\DataTables\Column\EntityColumn; +use App\DataTables\Column\LocaleDateTimeColumn; +use App\DataTables\Column\MarkdownColumn; +use App\DataTables\Helpers\AssemblyDataTableHelper; +use App\DataTables\Helpers\ColumnSortHelper; +use App\DataTables\Helpers\PartDataTableHelper; +use App\Entity\AssemblySystem\Assembly; +use App\Entity\Attachments\Attachment; +use App\Entity\Parts\Part; +use App\Entity\AssemblySystem\AssemblyBOMEntry; +use App\Services\Formatters\AmountFormatter; +use App\Settings\BehaviorSettings\TableSettings; +use Doctrine\ORM\QueryBuilder; +use Omines\DataTablesBundle\Adapter\Doctrine\ORM\SearchCriteriaProvider; +use Omines\DataTablesBundle\Adapter\Doctrine\ORMAdapter; +use Omines\DataTablesBundle\Column\TextColumn; +use Omines\DataTablesBundle\DataTable; +use Omines\DataTablesBundle\DataTableTypeInterface; +use Symfony\Contracts\Translation\TranslatorInterface; + +class AssemblyBomEntriesDataTable implements DataTableTypeInterface +{ + public function __construct( + private readonly TranslatorInterface $translator, + private readonly PartDataTableHelper $partDataTableHelper, + private readonly AssemblyDataTableHelper $assemblyDataTableHelper, + private readonly AmountFormatter $amountFormatter, + private readonly ColumnSortHelper $csh, + private readonly TableSettings $tableSettings, + ) { + } + + public function configure(DataTable $dataTable, array $options): void + { + $this->csh + ->add('picture', TextColumn::class, [ + 'label' => '', + 'className' => 'no-colvis', + 'render' => function ($value, AssemblyBOMEntry $context) { + if(!$context->getPart() instanceof Part) { + return ''; + } + return $this->partDataTableHelper->renderPicture($context->getPart()); + }, + ]) + ->add('id', TextColumn::class, [ + 'label' => $this->translator->trans('part.table.id'), + ]) + ->add('quantity', TextColumn::class, [ + 'label' => $this->translator->trans('assembly.bom.quantity'), + 'className' => 'text-center', + 'orderField' => 'bom_entry.quantity', + 'render' => function ($value, AssemblyBOMEntry $context): float|string { + //If we have a non-part entry, only show the rounded quantity + if (!$context->getPart() instanceof Part) { + return round($context->getQuantity()); + } + //Otherwise use the unit of the part to format the quantity + return htmlspecialchars($this->amountFormatter->format($context->getQuantity(), $context->getPart()->getPartUnit())); + }, + ]) + ->add('name', TextColumn::class, [ + 'label' => $this->translator->trans('part.table.name'), + 'orderField' => 'NATSORT(part.name)', + 'render' => function ($value, AssemblyBOMEntry $context) { + if(!$context->getPart() instanceof Part && !$context->getReferencedAssembly() instanceof Assembly) { + return htmlspecialchars((string) $context->getName()); + } + + $tmp = $context->getName(); + + if ($context->getPart() !== null) { + $tmp = $this->partDataTableHelper->renderName($context->getPart()); + $tmp = $this->translator->trans('part.table.name.value.for_part', ['%value%' => $tmp]); + + if($context->getName() !== null && $context->getName() !== '') { + $tmp .= '
'.htmlspecialchars($context->getName()).''; + } + } elseif ($context->getReferencedAssembly() !== null) { + $tmp = $this->assemblyDataTableHelper->renderName($context->getReferencedAssembly()); + $tmp = $this->translator->trans('part.table.name.value.for_assembly', ['%value%' => $tmp]); + + if($context->getName() !== null && $context->getName() !== '') { + $tmp .= '
'.htmlspecialchars($context->getName()).''; + } + } + + return $tmp; + }, + + ]) + ->add('ipn', TextColumn::class, [ + 'label' => $this->translator->trans('part.table.ipn'), + 'orderField' => 'NATSORT(part.ipn)', + 'render' => function ($value, AssemblyBOMEntry $context) { + if($context->getPart() instanceof Part) { + return $context->getPart()->getIpn(); + } elseif($context->getReferencedAssembly() instanceof Assembly) { + return $context->getReferencedAssembly()->getIpn(); + } + + return ''; + } + ]) + ->add('description', MarkdownColumn::class, [ + 'label' => $this->translator->trans('part.table.description'), + 'data' => function (AssemblyBOMEntry $context) { + if ($context->getPart() instanceof Part) { + return $context->getPart()->getDescription(); + } elseif ($context->getReferencedAssembly() instanceof Assembly) { + return $context->getReferencedAssembly()->getDescription(); + } + //For non-part BOM entries show the comment field + return $context->getComment(); + }, + ]) + ->add('category', EntityColumn::class, [ + 'label' => $this->translator->trans('part.table.category'), + 'property' => 'part.category', + 'orderField' => 'NATSORT(category.name)', + ]) + ->add('footprint', EntityColumn::class, [ + 'property' => 'part.footprint', + 'label' => $this->translator->trans('part.table.footprint'), + 'orderField' => 'NATSORT(footprint.name)', + ]) + ->add('manufacturer', EntityColumn::class, [ + 'property' => 'part.manufacturer', + 'label' => $this->translator->trans('part.table.manufacturer'), + 'orderField' => 'NATSORT(manufacturer.name)', + ]) + ->add('mountnames', TextColumn::class, [ + 'label' => 'assembly.bom.mountnames', + 'render' => function ($value, AssemblyBOMEntry $context) { + $html = ''; + + foreach (explode(',', $context->getMountnames()) as $mountname) { + $html .= sprintf('%s ', htmlspecialchars($mountname)); + } + return $html; + }, + ]) + ->add('designator', TextColumn::class, [ + 'label' => 'assembly.bom.designator', + 'render' => function ($value, AssemblyBOMEntry $context) { + return htmlspecialchars($context->getDesignator()); + }, + ]) + ->add('instockAmount', TextColumn::class, [ + 'label' => 'assembly.bom.instockAmount', + 'visible' => false, + 'render' => function ($value, AssemblyBOMEntry $context) { + if ($context->getPart() !== null) { + return $this->partDataTableHelper->renderAmount($context->getPart()); + } + + return ''; + } + ]) + ->add('storageLocations', TextColumn::class, [ + 'label' => 'part.table.storeLocations', + 'visible' => false, + 'render' => function ($value, AssemblyBOMEntry $context) { + if ($context->getPart() !== null) { + return $this->partDataTableHelper->renderStorageLocations($context->getPart()); + } + + return ''; + } + ]) + ->add('addedDate', LocaleDateTimeColumn::class, [ + 'label' => $this->translator->trans('part.table.addedDate'), + ]) + ->add('lastModified', LocaleDateTimeColumn::class, [ + 'label' => $this->translator->trans('part.table.lastModified'), + ]); + + //Apply the user configured order and visibility and add the columns to the table + $this->csh->applyVisibilityAndConfigureColumns($dataTable, $this->tableSettings->assembliesBomDefaultColumns, + "TABLE_ASSEMBLIES_BOM_DEFAULT_COLUMNS"); + + $dataTable->addOrderBy('name'); + + $dataTable->createAdapter(ORMAdapter::class, [ + 'entity' => Attachment::class, + 'query' => function (QueryBuilder $builder) use ($options): void { + $this->getQuery($builder, $options); + }, + 'criteria' => [ + function (QueryBuilder $builder) use ($options): void { + $this->buildCriteria($builder, $options); + }, + new SearchCriteriaProvider(), + ], + ]); + } + + private function getQuery(QueryBuilder $builder, array $options): void + { + $builder->select('bom_entry') + ->addSelect('part') + ->from(AssemblyBOMEntry::class, 'bom_entry') + ->leftJoin('bom_entry.part', 'part') + ->leftJoin('bom_entry.referencedAssembly', 'referencedAssembly') + ->leftJoin('part.category', 'category') + ->leftJoin('part.footprint', 'footprint') + ->leftJoin('part.manufacturer', 'manufacturer') + ->where('bom_entry.assembly = :assembly') + ->setParameter('assembly', $options['assembly']) + ; + } + + private function buildCriteria(QueryBuilder $builder, array $options): void + { + + } +} diff --git a/src/DataTables/AssemblyDataTable.php b/src/DataTables/AssemblyDataTable.php new file mode 100644 index 000000000..aaad2e45e --- /dev/null +++ b/src/DataTables/AssemblyDataTable.php @@ -0,0 +1,250 @@ +. + */ + +declare(strict_types=1); + +namespace App\DataTables; + +use App\DataTables\Adapters\TwoStepORMAdapter; +use App\DataTables\Column\IconLinkColumn; +use App\DataTables\Column\LocaleDateTimeColumn; +use App\DataTables\Column\MarkdownColumn; +use App\DataTables\Column\SelectColumn; +use App\DataTables\Filters\AssemblyFilter; +use App\DataTables\Filters\AssemblySearchFilter; +use App\DataTables\Helpers\AssemblyDataTableHelper; +use App\DataTables\Helpers\ColumnSortHelper; +use App\Doctrine\Helpers\FieldHelper; +use App\Entity\AssemblySystem\Assembly; +use App\Services\EntityURLGenerator; +use App\Settings\BehaviorSettings\TableSettings; +use Doctrine\ORM\AbstractQuery; +use Doctrine\ORM\QueryBuilder; +use Omines\DataTablesBundle\Adapter\Doctrine\ORM\SearchCriteriaProvider; +use Omines\DataTablesBundle\Column\TextColumn; +use Omines\DataTablesBundle\DataTable; +use Omines\DataTablesBundle\DataTableTypeInterface; +use Symfony\Bundle\SecurityBundle\Security; +use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Contracts\Translation\TranslatorInterface; + +final class AssemblyDataTable implements DataTableTypeInterface +{ + const LENGTH_MENU = [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]]; + + public function __construct( + private readonly EntityURLGenerator $urlGenerator, + private readonly TranslatorInterface $translator, + private readonly AssemblyDataTableHelper $assemblyDataTableHelper, + private readonly Security $security, + private readonly ColumnSortHelper $csh, + private readonly TableSettings $tableSettings, + ) { + } + + public function configureOptions(OptionsResolver $optionsResolver): void + { + $optionsResolver->setDefaults([ + 'filter' => null, + 'search' => null + ]); + + $optionsResolver->setAllowedTypes('filter', [AssemblyFilter::class, 'null']); + $optionsResolver->setAllowedTypes('search', [AssemblySearchFilter::class, 'null']); + } + + public function configure(DataTable $dataTable, array $options): void + { + $resolver = new OptionsResolver(); + $this->configureOptions($resolver); + $options = $resolver->resolve($options); + + $this->csh + ->add('select', SelectColumn::class, visibility_configurable: false) + ->add('picture', TextColumn::class, [ + 'label' => '', + 'className' => 'no-colvis', + 'render' => fn($value, Assembly $context) => $this->assemblyDataTableHelper->renderPicture($context), + ], visibility_configurable: false) + ->add('name', TextColumn::class, [ + 'label' => $this->translator->trans('assembly.table.name'), + 'render' => fn($value, Assembly $context) => $this->assemblyDataTableHelper->renderName($context), + 'orderField' => 'NATSORT(assembly.name)' + ]) + ->add('id', TextColumn::class, [ + 'label' => $this->translator->trans('assembly.table.id'), + ]) + ->add('ipn', TextColumn::class, [ + 'label' => $this->translator->trans('assembly.table.ipn'), + 'orderField' => 'NATSORT(assembly.ipn)' + ]) + ->add('description', MarkdownColumn::class, [ + 'label' => $this->translator->trans('assembly.table.description'), + ]) + ->add('addedDate', LocaleDateTimeColumn::class, [ + 'label' => $this->translator->trans('assembly.table.addedDate'), + ]) + ->add('lastModified', LocaleDateTimeColumn::class, [ + 'label' => $this->translator->trans('assembly.table.lastModified'), + ]); + + //Add a assembly column to list where the assembly is used as referenced assembly as bom-entry, when the user has the permission to see the assemblies + if ($this->security->isGranted('read', Assembly::class)) { + $this->csh->add('referencedAssemblies', TextColumn::class, [ + 'label' => $this->translator->trans('assembly.referencedAssembly.labelp'), + 'render' => function ($value, Assembly $context): string { + $assemblies = $context->getAllReferencedAssembliesRecursive($context); + + $max = 5; + $tmp = ""; + + for ($i = 0; $i < min($max, count($assemblies)); $i++) { + $tmp .= $this->assemblyDataTableHelper->renderName($assemblies[$i]); + if ($i < count($assemblies) - 1) { + $tmp .= ", "; + } + } + + if (count($assemblies) > $max) { + $tmp .= ", + ".(count($assemblies) - $max); + } + + return $tmp; + } + ]); + } + + $this->csh + ->add('edit', IconLinkColumn::class, [ + 'label' => $this->translator->trans('assembly.table.edit'), + 'href' => fn($value, Assembly $context) => $this->urlGenerator->editURL($context), + 'disabled' => fn($value, Assembly $context) => !$this->security->isGranted('edit', $context), + 'title' => $this->translator->trans('assembly.table.edit.title'), + ]); + + //Apply the user configured order and visibility and add the columns to the table + $this->csh->applyVisibilityAndConfigureColumns($dataTable, $this->tableSettings->assembliesDefaultColumns, + "TABLE_ASSEMBLIES_DEFAULT_COLUMNS"); + + $dataTable->addOrderBy('name') + ->createAdapter(TwoStepORMAdapter::class, [ + 'filter_query' => $this->getFilterQuery(...), + 'detail_query' => $this->getDetailQuery(...), + 'entity' => Assembly::class, + 'hydrate' => AbstractQuery::HYDRATE_OBJECT, + //Use the simple total query, as we just want to get the total number of assemblies without any conditions + //For this the normal query would be pretty slow + 'simple_total_query' => true, + 'criteria' => [ + function (QueryBuilder $builder) use ($options): void { + $this->buildCriteria($builder, $options); + }, + new SearchCriteriaProvider(), + ], + 'query_modifier' => $this->addJoins(...), + ]); + } + + + private function getFilterQuery(QueryBuilder $builder): void + { + /* In the filter query we only select the IDs. The fetching of the full entities is done in the detail query. + * We only need to join the entities here, so we can filter by them. + * The filter conditions are added to this QB in the buildCriteria method. + * + * The amountSum field and the joins are dynamically added by the addJoins method, if the fields are used in the query. + * This improves the performance, as we do not need to join all tables, if we do not need them. + */ + $builder + ->select('assembly.id') + ->from(Assembly::class, 'assembly') + + //The other group by fields, are dynamically added by the addJoins method + ->addGroupBy('assembly'); + } + + private function getDetailQuery(QueryBuilder $builder, array $filter_results): void + { + $ids = array_map(static fn($row) => $row['id'], $filter_results); + + /* + * In this query we take the IDs which were filtered, paginated and sorted in the filter query, and fetch the + * full entities. + * We can do complex fetch joins, as we do not need to filter or sort here (which would kill the performance). + * The only condition should be for the IDs. + * It is important that elements are ordered the same way, as the IDs are passed, or ordering will be wrong. + * + * We do not require the subqueries like amountSum here, as it is not used to render the table (and only for sorting) + */ + $builder + ->select('assembly') + ->addSelect('master_picture_attachment') + ->addSelect('attachments') + ->from(Assembly::class, 'assembly') + ->leftJoin('assembly.master_picture_attachment', 'master_picture_attachment') + ->leftJoin('assembly.attachments', 'attachments') + ->where('assembly.id IN (:ids)') + ->setParameter('ids', $ids) + ->addGroupBy('assembly') + ->addGroupBy('master_picture_attachment') + ->addGroupBy('attachments'); + + //Get the results in the same order as the IDs were passed + FieldHelper::addOrderByFieldParam($builder, 'assembly.id', 'ids'); + } + + /** + * This function is called right before the filter query is executed. + * We use it to dynamically add joins to the query, if the fields are used in the query. + * @param QueryBuilder $builder + * @return QueryBuilder + */ + private function addJoins(QueryBuilder $builder): QueryBuilder + { + //Check if the query contains certain conditions, for which we need to add additional joins + //The join fields get prefixed with an underscore, so we can check if they are used in the query easy without confusing them for a assembly subfield + $dql = $builder->getDQL(); + + if (str_contains($dql, '_master_picture_attachment')) { + $builder->leftJoin('assembly.master_picture_attachment', '_master_picture_attachment'); + $builder->addGroupBy('_master_picture_attachment'); + } + if (str_contains($dql, '_attachments')) { + $builder->leftJoin('assembly.attachments', '_attachments'); + } + + return $builder; + } + + private function buildCriteria(QueryBuilder $builder, array $options): void + { + //Apply the search criterias first + if ($options['search'] instanceof AssemblySearchFilter) { + $search = $options['search']; + $search->apply($builder); + } + + //We do the most stuff here in the filter class + if ($options['filter'] instanceof AssemblyFilter) { + $filter = $options['filter']; + $filter->apply($builder); + } + } +} diff --git a/src/DataTables/Filters/AssemblyFilter.php b/src/DataTables/Filters/AssemblyFilter.php new file mode 100644 index 000000000..d8d07a1ec --- /dev/null +++ b/src/DataTables/Filters/AssemblyFilter.php @@ -0,0 +1,68 @@ +. + */ +namespace App\DataTables\Filters; + +use App\DataTables\Filters\Constraints\DateTimeConstraint; +use App\DataTables\Filters\Constraints\EntityConstraint; +use App\DataTables\Filters\Constraints\IntConstraint; +use App\DataTables\Filters\Constraints\TextConstraint; +use App\Entity\Attachments\AttachmentType; +use App\Services\Trees\NodesListBuilder; +use Doctrine\ORM\QueryBuilder; + +class AssemblyFilter implements FilterInterface +{ + + use CompoundFilterTrait; + + public readonly IntConstraint $dbId; + public readonly TextConstraint $ipn; + public readonly TextConstraint $name; + public readonly TextConstraint $description; + public readonly TextConstraint $comment; + public readonly DateTimeConstraint $lastModified; + public readonly DateTimeConstraint $addedDate; + + public readonly IntConstraint $attachmentsCount; + public readonly EntityConstraint $attachmentType; + public readonly TextConstraint $attachmentName; + + public function __construct(NodesListBuilder $nodesListBuilder) + { + $this->name = new TextConstraint('assembly.name'); + $this->description = new TextConstraint('assembly.description'); + $this->comment = new TextConstraint('assembly.comment'); + $this->dbId = new IntConstraint('assembly.id'); + $this->ipn = new TextConstraint('assembly.ipn'); + $this->addedDate = new DateTimeConstraint('assembly.addedDate'); + $this->lastModified = new DateTimeConstraint('assembly.lastModified'); + $this->attachmentsCount = new IntConstraint('COUNT(_attachments)'); + $this->attachmentType = new EntityConstraint($nodesListBuilder, AttachmentType::class, '_attachments.attachment_type'); + $this->attachmentName = new TextConstraint('_attachments.name'); + } + + public function apply(QueryBuilder $queryBuilder): void + { + $this->applyAllChildFilters($queryBuilder); + } +} diff --git a/src/DataTables/Filters/AssemblySearchFilter.php b/src/DataTables/Filters/AssemblySearchFilter.php new file mode 100644 index 000000000..2ab33c839 --- /dev/null +++ b/src/DataTables/Filters/AssemblySearchFilter.php @@ -0,0 +1,172 @@ +. + */ +namespace App\DataTables\Filters; +use Doctrine\ORM\QueryBuilder; + +class AssemblySearchFilter implements FilterInterface +{ + + /** @var boolean Whether to use regex for searching */ + protected bool $regex = false; + + /** @var bool Use name field for searching */ + protected bool $name = true; + + /** @var bool Use description for searching */ + protected bool $description = true; + + /** @var bool Use comment field for searching */ + protected bool $comment = true; + + /** @var bool Use ordernr for searching */ + protected bool $ordernr = true; + + /** @var bool Use Internal part number for searching */ + protected bool $ipn = true; + + public function __construct( + /** @var string The string to query for */ + protected string $keyword + ) + { + } + + protected function getFieldsToSearch(): array + { + $fields_to_search = []; + + if($this->name) { + $fields_to_search[] = 'assembly.name'; + } + if($this->description) { + $fields_to_search[] = 'assembly.description'; + } + if ($this->comment) { + $fields_to_search[] = 'assembly.comment'; + } + if ($this->ipn) { + $fields_to_search[] = 'assembly.ipn'; + } + + return $fields_to_search; + } + + public function apply(QueryBuilder $queryBuilder): void + { + $fields_to_search = $this->getFieldsToSearch(); + + //If we have nothing to search for, do nothing + if ($fields_to_search === [] || $this->keyword === '') { + return; + } + + //Convert the fields to search to a list of expressions + $expressions = array_map(function (string $field): string { + if ($this->regex) { + return sprintf("REGEXP(%s, :search_query) = TRUE", $field); + } + + return sprintf("ILIKE(%s, :search_query) = TRUE", $field); + }, $fields_to_search); + + //Add Or concatenation of the expressions to our query + $queryBuilder->andWhere( + $queryBuilder->expr()->orX(...$expressions) + ); + + //For regex, we pass the query as is, for like we add % to the start and end as wildcards + if ($this->regex) { + $queryBuilder->setParameter('search_query', $this->keyword); + } else { + $queryBuilder->setParameter('search_query', '%' . $this->keyword . '%'); + } + } + + public function getKeyword(): string + { + return $this->keyword; + } + + public function setKeyword(string $keyword): AssemblySearchFilter + { + $this->keyword = $keyword; + return $this; + } + + public function isRegex(): bool + { + return $this->regex; + } + + public function setRegex(bool $regex): AssemblySearchFilter + { + $this->regex = $regex; + return $this; + } + + public function isName(): bool + { + return $this->name; + } + + public function setName(bool $name): AssemblySearchFilter + { + $this->name = $name; + return $this; + } + + public function isDescription(): bool + { + return $this->description; + } + + public function setDescription(bool $description): AssemblySearchFilter + { + $this->description = $description; + return $this; + } + + public function isIPN(): bool + { + return $this->ipn; + } + + public function setIPN(bool $ipn): AssemblySearchFilter + { + $this->ipn = $ipn; + return $this; + } + + public function isComment(): bool + { + return $this->comment; + } + + public function setComment(bool $comment): AssemblySearchFilter + { + $this->comment = $comment; + return $this; + } + + +} diff --git a/src/DataTables/Helpers/AssemblyDataTableHelper.php b/src/DataTables/Helpers/AssemblyDataTableHelper.php new file mode 100644 index 000000000..dda563ea4 --- /dev/null +++ b/src/DataTables/Helpers/AssemblyDataTableHelper.php @@ -0,0 +1,77 @@ +. + */ + +namespace App\DataTables\Helpers; + +use App\Entity\AssemblySystem\Assembly; +use App\Entity\Attachments\Attachment; +use App\Services\Attachments\AssemblyPreviewGenerator; +use App\Services\Attachments\AttachmentURLGenerator; +use App\Services\EntityURLGenerator; + +/** + * A helper service which contains common code to render columns for assembly related tables + */ +class AssemblyDataTableHelper +{ + public function __construct( + private readonly EntityURLGenerator $entityURLGenerator, + private readonly AssemblyPreviewGenerator $previewGenerator, + private readonly AttachmentURLGenerator $attachmentURLGenerator + ) { + } + + public function renderName(Assembly $context): string + { + $icon = ''; + + return sprintf( + '%s%s', + $this->entityURLGenerator->infoURL($context), + $icon, + htmlspecialchars($context->getName()) + ); + } + + public function renderPicture(Assembly $context): string + { + $preview_attachment = $this->previewGenerator->getTablePreviewAttachment($context); + if (!$preview_attachment instanceof Attachment) { + return ''; + } + + $title = htmlspecialchars($preview_attachment->getName()); + if ($preview_attachment->getFilename()) { + $title .= ' ('.htmlspecialchars($preview_attachment->getFilename()).')'; + } + + return sprintf( + '%s', + 'Assembly image', + $this->attachmentURLGenerator->getThumbnailURL($preview_attachment), + $this->attachmentURLGenerator->getThumbnailURL($preview_attachment, 'thumbnail_md'), + 'hoverpic assembly-table-image', + $title + ); + } +} diff --git a/src/DataTables/PartsDataTable.php b/src/DataTables/PartsDataTable.php index a97762b11..7c205d1fe 100644 --- a/src/DataTables/PartsDataTable.php +++ b/src/DataTables/PartsDataTable.php @@ -39,6 +39,7 @@ use App\DataTables\Helpers\ColumnSortHelper; use App\DataTables\Helpers\PartDataTableHelper; use App\Doctrine\Helpers\FieldHelper; +use App\Entity\AssemblySystem\Assembly; use App\Entity\Parts\ManufacturingStatus; use App\Entity\Parts\Part; use App\Entity\Parts\PartLot; @@ -240,6 +241,34 @@ public function configure(DataTable $dataTable, array $options): void ]); } + //Add a assembly column to list where the part is used, when the user has the permission to see the assemblies + if ($this->security->isGranted('read', Assembly::class)) { + $this->csh->add('assemblies', TextColumn::class, [ + 'label' => $this->translator->trans('assembly.labelp'), + 'render' => function ($value, Part $context): string { + //Only show the first 5 assembly names + $assemblies = $context->getAssemblies(); + $tmp = ""; + + $max = 5; + + for ($i = 0; $i < min($max, count($assemblies)); $i++) { + $url = $this->urlGenerator->infoURL($assemblies[$i]); + $tmp .= sprintf('%s', $url, htmlspecialchars($assemblies[$i]->getName())); + if ($i < count($assemblies) - 1) { + $tmp .= ", "; + } + } + + if (count($assemblies) > $max) { + $tmp .= ", + ".(count($assemblies) - $max); + } + + return $tmp; + } + ]); + } + $this->csh ->add('edit', IconLinkColumn::class, [ 'label' => $this->translator->trans('part.table.edit'), diff --git a/src/Entity/AssemblySystem/Assembly.php b/src/Entity/AssemblySystem/Assembly.php new file mode 100644 index 000000000..20a7aa1b0 --- /dev/null +++ b/src/Entity/AssemblySystem/Assembly.php @@ -0,0 +1,373 @@ +. + */ + +declare(strict_types=1); + +namespace App\Entity\AssemblySystem; + +use App\Repository\AssemblyRepository; +use App\Validator\Constraints\AssemblySystem\AssemblyCycle; +use App\Validator\Constraints\AssemblySystem\AssemblyInvalidBomEntry; +use Doctrine\Common\Collections\Criteria; +use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Post; +use ApiPlatform\OpenApi\Model\Operation; +use ApiPlatform\Serializer\Filter\PropertyFilter; +use App\ApiPlatform\Filter\LikeFilter; +use App\Entity\Attachments\Attachment; +use App\Validator\Constraints\UniqueObjectCollection; +use App\Validator\Constraints\AssemblySystem\UniqueReferencedAssembly; +use Doctrine\DBAL\Types\Types; +use App\Entity\Attachments\AssemblyAttachment; +use App\Entity\Base\AbstractStructuralDBElement; +use App\Entity\Parameters\AssemblyParameter; +use App\Entity\Parts\Part; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; +use Doctrine\ORM\Mapping as ORM; +use InvalidArgumentException; +use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; +use Symfony\Component\Serializer\Annotation\Groups; +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Constraints\Length; +use Symfony\Component\Validator\Context\ExecutionContextInterface; + +/** + * This class represents a assembly in the database. + * + * @extends AbstractStructuralDBElement + */ +#[ORM\Entity(repositoryClass: AssemblyRepository::class)] +#[ORM\Table(name: 'assemblies')] +#[UniqueEntity(fields: ['ipn'], message: 'assembly.ipn.must_be_unique')] +#[ORM\Index(columns: ['ipn'], name: 'assembly_idx_ipn')] +#[ApiResource( + operations: [ + new Get(security: 'is_granted("read", object)'), + new GetCollection(security: 'is_granted("@assemblies.read")'), + new Post(securityPostDenormalize: 'is_granted("create", object)'), + new Patch(security: 'is_granted("edit", object)'), + new Delete(security: 'is_granted("delete", object)'), + ], + normalizationContext: ['groups' => ['assembly:read', 'api:basic:read'], 'openapi_definition_name' => 'Read'], + denormalizationContext: ['groups' => ['assembly:write', 'api:basic:write', 'attachment:write', 'parameter:write'], 'openapi_definition_name' => 'Write'], +)] +#[ApiResource( + uriTemplate: '/assemblies/{id}/children.{_format}', + operations: [ + new GetCollection( + openapi: new Operation(summary: 'Retrieves the children elements of a assembly.'), + security: 'is_granted("@assemblies.read")' + ) + ], + uriVariables: [ + 'id' => new Link(fromProperty: 'children', fromClass: Assembly::class) + ], + normalizationContext: ['groups' => ['assembly:read', 'api:basic:read'], 'openapi_definition_name' => 'Read'] +)] +#[ApiFilter(PropertyFilter::class)] +#[ApiFilter(LikeFilter::class, properties: ["name", "comment", "ipn"])] +#[ApiFilter(OrderFilter::class, properties: ['name', 'id', 'addedDate', 'lastModified'])] +class Assembly extends AbstractStructuralDBElement +{ + #[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)] + #[ORM\OrderBy(['name' => Criteria::ASC])] + protected Collection $children; + + #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')] + #[ORM\JoinColumn(name: 'parent_id')] + #[Groups(['assembly:read', 'assembly:write'])] + #[ApiProperty(readableLink: false, writableLink: false)] + protected ?AbstractStructuralDBElement $parent = null; + + #[Groups(['assembly:read', 'assembly:write'])] + protected string $comment = ''; + + /** + * @var Collection + */ + #[Assert\Valid] + #[AssemblyCycle] + #[AssemblyInvalidBomEntry] + #[UniqueReferencedAssembly] + #[Groups(['extended', 'full', 'import'])] + #[ORM\OneToMany(targetEntity: AssemblyBOMEntry::class, mappedBy: 'assembly', cascade: ['persist', 'remove'], orphanRemoval: true)] + #[UniqueObjectCollection(message: 'assembly.bom_entry.part_already_in_bom', fields: ['part'])] + #[UniqueObjectCollection(message: 'assembly.bom_entry.name_already_in_bom', fields: ['name'])] + protected Collection $bom_entries; + + #[ORM\Column(type: Types::INTEGER)] + protected int $order_quantity = 0; + + /** + * @var string|null The current status of the assembly + */ + #[Assert\Choice(['draft', 'planning', 'in_production', 'finished', 'archived'])] + #[Groups(['extended', 'full', 'assembly:read', 'assembly:write', 'import'])] + #[ORM\Column(type: Types::STRING, length: 64, nullable: true)] + protected ?string $status = null; + + /** + * @var string|null The internal ipn number of the assembly + */ + #[Assert\Length(max: 100)] + #[Groups(['extended', 'full', 'assembly:read', 'assembly:write', 'import'])] + #[ORM\Column(type: Types::STRING, length: 100, unique: true, nullable: true)] + #[Length(max: 100)] + protected ?string $ipn = null; + + #[ORM\Column(type: Types::BOOLEAN)] + protected bool $order_only_missing_parts = false; + + #[Groups(['simple', 'extended', 'full', 'assembly:read', 'assembly:write'])] + #[ORM\Column(type: Types::TEXT)] + protected string $description = ''; + + /** + * @var Collection + */ + #[ORM\OneToMany(mappedBy: 'element', targetEntity: AssemblyAttachment::class, cascade: ['persist', 'remove'], orphanRemoval: true)] + #[ORM\OrderBy(['name' => Criteria::ASC])] + #[Groups(['assembly:read', 'assembly:write'])] + protected Collection $attachments; + + #[ORM\ManyToOne(targetEntity: AssemblyAttachment::class)] + #[ORM\JoinColumn(name: 'id_preview_attachment', onDelete: 'SET NULL')] + #[Groups(['assembly:read', 'assembly:write'])] + protected ?Attachment $master_picture_attachment = null; + + /** @var Collection + */ + #[ORM\OneToMany(mappedBy: 'element', targetEntity: AssemblyParameter::class, cascade: ['persist', 'remove'], orphanRemoval: true)] + #[ORM\OrderBy(['group' => Criteria::ASC, 'name' => 'ASC'])] + #[Groups(['assembly:read', 'assembly:write'])] + protected Collection $parameters; + + #[Groups(['assembly:read'])] + protected ?\DateTimeImmutable $addedDate = null; + #[Groups(['assembly:read'])] + protected ?\DateTimeImmutable $lastModified = null; + + + /******************************************************************************** + * + * Getters + * + *********************************************************************************/ + + public function __construct() + { + $this->attachments = new ArrayCollection(); + $this->parameters = new ArrayCollection(); + parent::__construct(); + $this->bom_entries = new ArrayCollection(); + $this->children = new ArrayCollection(); + } + + public function __clone() + { + //When cloning this assembly, we have to clone each bom entry too. + if ($this->id) { + $bom_entries = $this->bom_entries; + $this->bom_entries = new ArrayCollection(); + //Set master attachment is needed + foreach ($bom_entries as $bom_entry) { + $clone = clone $bom_entry; + $this->addBomEntry($clone); + } + } + + //Parent has to be last call, as it resets the ID + parent::__clone(); + } + + /** + * Get the order quantity of this assembly. + * + * @return int the order quantity + */ + public function getOrderQuantity(): int + { + return $this->order_quantity; + } + + /** + * Get the "order_only_missing_parts" attribute. + * + * @return bool the "order_only_missing_parts" attribute + */ + public function getOrderOnlyMissingParts(): bool + { + return $this->order_only_missing_parts; + } + + /******************************************************************************** + * + * Setters + * + *********************************************************************************/ + + /** + * Set the order quantity. + * + * @param int $new_order_quantity the new order quantity + * + * @return $this + */ + public function setOrderQuantity(int $new_order_quantity): self + { + if ($new_order_quantity < 0) { + throw new InvalidArgumentException('The new order quantity must not be negative!'); + } + $this->order_quantity = $new_order_quantity; + + return $this; + } + + /** + * Set the "order_only_missing_parts" attribute. + * + * @param bool $new_order_only_missing_parts the new "order_only_missing_parts" attribute + */ + public function setOrderOnlyMissingParts(bool $new_order_only_missing_parts): self + { + $this->order_only_missing_parts = $new_order_only_missing_parts; + + return $this; + } + + public function getBomEntries(): Collection + { + return $this->bom_entries; + } + + /** + * @return $this + */ + public function addBomEntry(AssemblyBOMEntry $entry): self + { + $entry->setAssembly($this); + $this->bom_entries->add($entry); + return $this; + } + + /** + * @return $this + */ + public function removeBomEntry(AssemblyBOMEntry $entry): self + { + $this->bom_entries->removeElement($entry); + return $this; + } + + public function getDescription(): string + { + return $this->description; + } + + public function setDescription(string $description): Assembly + { + $this->description = $description; + return $this; + } + + /** + * @return string + */ + public function getStatus(): ?string + { + return $this->status; + } + + /** + * @param string $status + */ + public function setStatus(?string $status): void + { + $this->status = $status; + } + + /** + * Returns the internal part number of the assembly. + * @return string + */ + public function getIpn(): ?string + { + return $this->ipn; + } + + /** + * Sets the internal part number of the assembly. + * @param string $ipn The new IPN of the assembly + */ + public function setIpn(?string $ipn): Assembly + { + $this->ipn = $ipn; + return $this; + } + + #[Assert\Callback] + public function validate(ExecutionContextInterface $context, $payload): void + { + } + + /** + * Get all assemblies and sub-assemblies recursive that are referenced in the assembly bom entries. + * + * @param Assembly $assembly Assembly, which is to be processed recursively. + * @param array $processedAssemblies (optional) a list of the already edited assemblies to avoid circulatory references. + * @return Assembly[] A flat list of all recursively found assemblies. + */ + public function getAllReferencedAssembliesRecursive(Assembly $assembly, array &$processedAssemblies = []): array + { + $assemblies = []; + + // Avoid circular references + if (in_array($assembly, $processedAssemblies, true)) { + return $assemblies; + } + + // Add the current assembly to the processed + $processedAssemblies[] = $assembly; + + // Iterate by the bom entries of the current assembly + foreach ($assembly->getBomEntries() as $bomEntry) { + if ($bomEntry->getReferencedAssembly() !== null) { + $referencedAssembly = $bomEntry->getReferencedAssembly(); + + $assemblies[] = $referencedAssembly; + + // Continue recursively to process sub-assemblies + $assemblies = array_merge($assemblies, $this->getAllReferencedAssembliesRecursive($referencedAssembly, $processedAssemblies)); + } + } + + return $assemblies; + } + +} diff --git a/src/Entity/AssemblySystem/AssemblyBOMEntry.php b/src/Entity/AssemblySystem/AssemblyBOMEntry.php new file mode 100644 index 000000000..500a44015 --- /dev/null +++ b/src/Entity/AssemblySystem/AssemblyBOMEntry.php @@ -0,0 +1,340 @@ +. + */ + +declare(strict_types=1); + +namespace App\Entity\AssemblySystem; + +use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; +use ApiPlatform\Doctrine\Orm\Filter\RangeFilter; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Post; +use ApiPlatform\OpenApi\Model\Operation; +use ApiPlatform\Serializer\Filter\PropertyFilter; +use App\ApiPlatform\Filter\LikeFilter; +use App\Entity\Contracts\TimeStampableInterface; +use App\Repository\DBElementRepository; +use App\Validator\Constraints\AssemblySystem\AssemblyCycle; +use App\Validator\Constraints\AssemblySystem\AssemblyInvalidBomEntry; +use App\Validator\UniqueValidatableInterface; +use Doctrine\DBAL\Types\Types; +use App\Entity\Base\AbstractDBElement; +use App\Entity\Base\TimestampTrait; +use App\Entity\Parts\Part; +use App\Entity\PriceInformations\Currency; +use App\Validator\Constraints\BigDecimal\BigDecimalPositive; +use App\Validator\Constraints\Selectable; +use Brick\Math\BigDecimal; +use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Serializer\Annotation\Groups; +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Context\ExecutionContextInterface; + +/** + * The AssemblyBOMEntry class represents an entry in a assembly's BOM. + */ +#[ORM\HasLifecycleCallbacks] +#[ORM\Entity(repositoryClass: DBElementRepository::class)] +#[ORM\Table('assembly_bom_entries')] +#[ApiResource( + operations: [ + new Get(uriTemplate: '/assembly_bom_entries/{id}.{_format}', security: 'is_granted("read", object)',), + new GetCollection(uriTemplate: '/assembly_bom_entries.{_format}', security: 'is_granted("@assemblies.read")',), + new Post(uriTemplate: '/assembly_bom_entries.{_format}', securityPostDenormalize: 'is_granted("create", object)',), + new Patch(uriTemplate: '/assembly_bom_entries/{id}.{_format}', security: 'is_granted("edit", object)',), + new Delete(uriTemplate: '/assembly_bom_entries/{id}.{_format}', security: 'is_granted("delete", object)',), + ], + normalizationContext: ['groups' => ['bom_entry:read', 'api:basic:read'], 'openapi_definition_name' => 'Read'], + denormalizationContext: ['groups' => ['bom_entry:write', 'api:basic:write'], 'openapi_definition_name' => 'Write'], +)] +#[ApiResource( + uriTemplate: '/assemblies/{id}/bom.{_format}', + operations: [ + new GetCollection( + openapi: new Operation(summary: 'Retrieves the BOM entries of the given assembly.'), + security: 'is_granted("@assemblies.read")' + ) + ], + uriVariables: [ + 'id' => new Link(fromProperty: 'bom_entries', fromClass: Assembly::class) + ], + normalizationContext: ['groups' => ['bom_entry:read', 'api:basic:read'], 'openapi_definition_name' => 'Read'] +)] +#[ApiFilter(PropertyFilter::class)] +#[ApiFilter(LikeFilter::class, properties: ["name", 'mountnames', 'designator', "comment"])] +#[ApiFilter(RangeFilter::class, properties: ['quantity'])] +#[ApiFilter(OrderFilter::class, properties: ['name', 'id', 'addedDate', 'lastModified', 'quantity'])] +class AssemblyBOMEntry extends AbstractDBElement implements UniqueValidatableInterface, TimeStampableInterface +{ + use TimestampTrait; + + #[Assert\Positive] + #[ORM\Column(name: 'quantity', type: Types::FLOAT)] + #[Groups(['bom_entry:read', 'bom_entry:write', 'import', 'simple', 'extended', 'full'])] + protected float $quantity = 1.0; + + /** + * @var string A comma separated list of the names, where this parts should be placed + */ + #[ORM\Column(name: 'mountnames', type: Types::TEXT)] + #[Groups(['bom_entry:read', 'bom_entry:write', 'import', 'simple', 'extended', 'full'])] + protected string $mountnames = ''; + + /** + * @var string Reference mark on the circuit diagram/PCB + */ + #[ORM\Column(name: 'designator', type: Types::TEXT)] + #[Groups(['bom_entry:read', 'bom_entry:write', 'import', 'simple', 'extended', 'full'])] + protected string $designator = ''; + + /** + * @var string|null An optional name describing this BOM entry (useful for non-part entries) + */ + #[Assert\Expression('this.getPart() !== null or this.getReferencedAssembly() !== null or this.getName() !== null', message: 'validator.assembly.bom_entry.name_or_part_needed')] + #[ORM\Column(type: Types::STRING, nullable: true)] + #[Groups(['bom_entry:read', 'bom_entry:write', 'import', 'simple', 'extended', 'full'])] + protected ?string $name = null; + + /** + * @var string An optional comment for this BOM entry + */ + #[ORM\Column(type: Types::TEXT)] + #[Groups(['bom_entry:read', 'bom_entry:write', 'import', 'extended', 'full'])] + protected string $comment = ''; + + /** + * @var Assembly|null + */ + #[ORM\ManyToOne(targetEntity: Assembly::class, inversedBy: 'bom_entries')] + #[ORM\JoinColumn(name: 'id_assembly', nullable: true)] + #[Groups(['bom_entry:read', 'bom_entry:write'])] + protected ?Assembly $assembly = null; + + /** + * @var Part|null The part associated with this + */ + #[ORM\ManyToOne(targetEntity: Part::class, inversedBy: 'assembly_bom_entries')] + #[ORM\JoinColumn(name: 'id_part')] + #[Groups(['bom_entry:read', 'bom_entry:write', 'full'])] + protected ?Part $part = null; + + /** + * @var Assembly|null The associated assembly + */ + #[Assert\Expression( + '(this.getPart() === null or this.getReferencedAssembly() === null) and (this.getName() === null or (this.getName() != null and this.getName() != ""))', + message: 'validator.assembly.bom_entry.only_part_or_assembly_allowed' + )] + #[AssemblyCycle] + #[AssemblyInvalidBomEntry] + #[ORM\ManyToOne(targetEntity: Assembly::class)] + #[ORM\JoinColumn(name: 'id_referenced_assembly', nullable: true, onDelete: 'SET NULL')] + #[Groups(['bom_entry:read', 'bom_entry:write'])] + protected ?Assembly $referencedAssembly = null; + + /** + * @var BigDecimal|null The price of this non-part BOM entry + */ + #[Assert\AtLeastOneOf([new BigDecimalPositive(), new Assert\IsNull()])] + #[ORM\Column(type: 'big_decimal', precision: 11, scale: 5, nullable: true)] + #[Groups(['bom_entry:read', 'bom_entry:write', 'import', 'extended', 'full'])] + protected ?BigDecimal $price = null; + + /** + * @var ?Currency The currency for the price of this non-part BOM entry + */ + #[ORM\ManyToOne(targetEntity: Currency::class)] + #[ORM\JoinColumn] + #[Selectable] + protected ?Currency $price_currency = null; + + public function __construct() + { + } + + public function getQuantity(): float + { + return $this->quantity; + } + + public function setQuantity(float $quantity): AssemblyBOMEntry + { + $this->quantity = $quantity; + return $this; + } + + public function getMountnames(): string + { + return $this->mountnames; + } + + public function setMountnames(string $mountnames): AssemblyBOMEntry + { + $this->mountnames = $mountnames; + return $this; + } + + public function getDesignator(): string + { + return $this->designator; + } + + public function setDesignator(string $designator): AssemblyBOMEntry + { + $this->designator = $designator; + return $this; + } + + /** + * @return string + */ + public function getName(): ?string + { + return trim($this->name ?? '') === '' ? null : $this->name; + } + + /** + * @param string $name + */ + public function setName(?string $name): AssemblyBOMEntry + { + $this->name = trim($name ?? '') === '' ? null : $name; + return $this; + } + + public function getComment(): string + { + return $this->comment; + } + + public function setComment(string $comment): AssemblyBOMEntry + { + $this->comment = $comment; + return $this; + } + + public function getAssembly(): ?Assembly + { + return $this->assembly; + } + + public function setAssembly(?Assembly $assembly): AssemblyBOMEntry + { + $this->assembly = $assembly; + return $this; + } + + public function getPart(): ?Part + { + return $this->part; + } + + public function setPart(?Part $part): AssemblyBOMEntry + { + $this->part = $part; + return $this; + } + + public function getReferencedAssembly(): ?Assembly + { + return $this->referencedAssembly; + } + + public function setReferencedAssembly(?Assembly $referencedAssembly): AssemblyBOMEntry + { + $this->referencedAssembly = $referencedAssembly; + return $this; + } + + /** + * Returns the price of this BOM entry, if existing. + * Prices are only valid on non-Part BOM entries. + */ + public function getPrice(): ?BigDecimal + { + return $this->price; + } + + /** + * Sets the price of this BOM entry. + * Prices are only valid on non-Part BOM entries. + */ + public function setPrice(?BigDecimal $price): void + { + $this->price = $price; + } + + public function getPriceCurrency(): ?Currency + { + return $this->price_currency; + } + + public function setPriceCurrency(?Currency $price_currency): void + { + $this->price_currency = $price_currency; + } + + /** + * Checks whether this BOM entry is a part associated BOM entry or not. + * @return bool True if this BOM entry is a part associated BOM entry, false otherwise. + */ + public function isPartBomEntry(): bool + { + return $this->part instanceof Part; + } + + /** + * Checks whether this BOM entry is a assembly associated BOM entry or not. + * @return bool True if this BOM entry is a assembly associated BOM entry, false otherwise. + */ + public function isAssemblyBomEntry(): bool + { + return $this->referencedAssembly !== null; + } + + #[Assert\Callback] + public function validate(ExecutionContextInterface $context, $payload): void + { + //Round quantity to whole numbers, if the part is not a decimal part + if ($this->part instanceof Part && (!$this->part->getPartUnit() || $this->part->getPartUnit()->isInteger())) { + $this->quantity = round($this->quantity); + } + //Non-Part BOM entries are rounded + if (!$this->part instanceof Part) { + $this->quantity = round($this->quantity); + } + } + + + public function getComparableFields(): array + { + return [ + 'name' => $this->getName(), + 'part' => $this->getPart()?->getID(), + 'referencedAssembly' => $this->getReferencedAssembly()?->getID(), + ]; + } +} diff --git a/src/Entity/Attachments/AssemblyAttachment.php b/src/Entity/Attachments/AssemblyAttachment.php new file mode 100644 index 000000000..bb9a11c8f --- /dev/null +++ b/src/Entity/Attachments/AssemblyAttachment.php @@ -0,0 +1,48 @@ +. + */ + +declare(strict_types=1); + +namespace App\Entity\Attachments; + +use App\Entity\AssemblySystem\Assembly; +use App\Serializer\APIPlatform\OverrideClassDenormalizer; +use Doctrine\ORM\Mapping as ORM; +use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; +use Symfony\Component\Serializer\Attribute\Context; + +/** + * A attachment attached to a device element. + * @extends Attachment + */ +#[UniqueEntity(['name', 'attachment_type', 'element'])] +#[UniqueEntity(['name', 'attachment_type', 'element'])] +#[ORM\Entity] +class AssemblyAttachment extends Attachment +{ + final public const ALLOWED_ELEMENT_CLASS = Assembly::class; + /** + * @var Assembly|null the element this attachment is associated with + */ + #[ORM\ManyToOne(targetEntity: Assembly::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; +} diff --git a/src/Entity/Attachments/Attachment.php b/src/Entity/Attachments/Attachment.php index 00cf581a8..808c60623 100644 --- a/src/Entity/Attachments/Attachment.php +++ b/src/Entity/Attachments/Attachment.php @@ -97,7 +97,7 @@ #[DiscriminatorMap(typeProperty: '_type', mapping: self::API_DISCRIMINATOR_MAP)] abstract class Attachment extends AbstractNamedDBElement { - private const ORM_DISCRIMINATOR_MAP = ['Part' => PartAttachment::class, 'Device' => ProjectAttachment::class, + private const ORM_DISCRIMINATOR_MAP = ['Part' => PartAttachment::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,8 @@ 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, "AttachmentType" => AttachmentTypeAttachment::class, + private const API_DISCRIMINATOR_MAP = ["Part" => PartAttachment::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, "StorageLocation" => StorageLocationAttachment::class, "Supplier" => SupplierAttachment::class, "User" => UserAttachment::class, "LabelProfile" => LabelAttachment::class]; diff --git a/src/Entity/Base/AbstractDBElement.php b/src/Entity/Base/AbstractDBElement.php index 9fb5d6489..ad9c534b0 100644 --- a/src/Entity/Base/AbstractDBElement.php +++ b/src/Entity/Base/AbstractDBElement.php @@ -22,6 +22,9 @@ namespace App\Entity\Base; +use App\Entity\AssemblySystem\Assembly; +use App\Entity\AssemblySystem\AssemblyBOMEntry; +use App\Entity\Attachments\AssemblyAttachment; use App\Entity\Attachments\AttachmentType; use App\Entity\Attachments\Attachment; use App\Entity\Attachments\AttachmentTypeAttachment; @@ -68,7 +71,7 @@ * 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, '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, '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, '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])] #[ORM\MappedSuperclass(repositoryClass: DBElementRepository::class)] abstract class AbstractDBElement implements JsonSerializable { diff --git a/src/Entity/LogSystem/CollectionElementDeleted.php b/src/Entity/LogSystem/CollectionElementDeleted.php index 16bf33f59..be19bb0c8 100644 --- a/src/Entity/LogSystem/CollectionElementDeleted.php +++ b/src/Entity/LogSystem/CollectionElementDeleted.php @@ -41,6 +41,8 @@ namespace App\Entity\LogSystem; +use App\Entity\AssemblySystem\Assembly; +use App\Entity\Attachments\AssemblyAttachment; use App\Entity\Attachments\Attachment; use App\Entity\Attachments\AttachmentType; use App\Entity\Attachments\AttachmentTypeAttachment; @@ -58,6 +60,7 @@ use App\Entity\Base\AbstractDBElement; use App\Entity\Contracts\LogWithEventUndoInterface; use App\Entity\Contracts\NamedElementInterface; +use App\Entity\Parameters\AssemblyParameter; use App\Entity\ProjectSystem\Project; use App\Entity\Parameters\AbstractParameter; use App\Entity\Parameters\AttachmentTypeParameter; @@ -147,6 +150,7 @@ private function resolveAbstractClassToInstantiableClass(string $abstract_class) { if (is_a($abstract_class, AbstractParameter::class, true)) { return match ($this->getTargetClass()) { + Assembly::class => AssemblyParameter::class, AttachmentType::class => AttachmentTypeParameter::class, Category::class => CategoryParameter::class, Currency::class => CurrencyParameter::class, @@ -168,6 +172,7 @@ private function resolveAbstractClassToInstantiableClass(string $abstract_class) Category::class => CategoryAttachment::class, Currency::class => CurrencyAttachment::class, Project::class => ProjectAttachment::class, + Assembly::class => AssemblyAttachment::class, Footprint::class => FootprintAttachment::class, Group::class => GroupAttachment::class, Manufacturer::class => ManufacturerAttachment::class, diff --git a/src/Entity/LogSystem/LogTargetType.php b/src/Entity/LogSystem/LogTargetType.php index 61a2b081c..d5bc9ce0e 100644 --- a/src/Entity/LogSystem/LogTargetType.php +++ b/src/Entity/LogSystem/LogTargetType.php @@ -22,6 +22,8 @@ */ namespace App\Entity\LogSystem; +use App\Entity\AssemblySystem\Assembly; +use App\Entity\AssemblySystem\AssemblyBOMEntry; use App\Entity\Attachments\Attachment; use App\Entity\Attachments\AttachmentType; use App\Entity\InfoProviderSystem\BulkInfoProviderImportJob; @@ -72,6 +74,9 @@ enum LogTargetType: int case BULK_INFO_PROVIDER_IMPORT_JOB = 21; case BULK_INFO_PROVIDER_IMPORT_JOB_PART = 22; + case ASSEMBLY = 23; + case ASSEMBLY_BOM_ENTRY = 24; + /** * Returns the class name of the target type or null if the target type is NONE. * @return string|null @@ -86,6 +91,8 @@ public function toClass(): ?string self::CATEGORY => Category::class, self::PROJECT => Project::class, self::BOM_ENTRY => ProjectBOMEntry::class, + self::ASSEMBLY => Assembly::class, + self::ASSEMBLY_BOM_ENTRY => AssemblyBOMEntry::class, self::FOOTPRINT => Footprint::class, self::GROUP => Group::class, self::MANUFACTURER => Manufacturer::class, diff --git a/src/Entity/Parameters/AbstractParameter.php b/src/Entity/Parameters/AbstractParameter.php index 39f333dad..b6ef0412b 100644 --- a/src/Entity/Parameters/AbstractParameter.php +++ b/src/Entity/Parameters/AbstractParameter.php @@ -73,7 +73,7 @@ #[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])] + 9 => SupplierParameter::class, 10 => AttachmentTypeParameter::class, 11 => AssemblyParameter::class])] #[ORM\Table('parameters')] #[ORM\Index(columns: ['name'], name: 'parameter_name_idx')] #[ORM\Index(columns: ['param_group'], name: 'parameter_group_idx')] @@ -103,7 +103,7 @@ abstract class AbstractParameter extends AbstractNamedDBElement implements Uniqu */ private const API_DISCRIMINATOR_MAP = ["Part" => PartParameter::class, "AttachmentType" => AttachmentTypeParameter::class, "Category" => CategoryParameter::class, "Currency" => CurrencyParameter::class, - "Project" => ProjectParameter::class, "Footprint" => FootprintParameter::class, "Group" => GroupParameter::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]; diff --git a/src/Entity/Parameters/AssemblyParameter.php b/src/Entity/Parameters/AssemblyParameter.php new file mode 100644 index 000000000..349fa7906 --- /dev/null +++ b/src/Entity/Parameters/AssemblyParameter.php @@ -0,0 +1,65 @@ +. + */ + +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 . + */ + +namespace App\Entity\Parameters; + +use App\Entity\AssemblySystem\Assembly; +use App\Entity\Base\AbstractDBElement; +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 AssemblyParameter extends AbstractParameter +{ + final public const ALLOWED_ELEMENT_CLASS = Assembly::class; + + /** + * @var Assembly the element this para is associated with + */ + #[ORM\ManyToOne(targetEntity: Assembly::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; +} diff --git a/src/Entity/Parts/Part.php b/src/Entity/Parts/Part.php index 2f274a8af..689e7ce7f 100644 --- a/src/Entity/Parts/Part.php +++ b/src/Entity/Parts/Part.php @@ -22,6 +22,7 @@ namespace App\Entity\Parts; +use App\Entity\Parts\PartTraits\AssemblyTrait; use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface; use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter; use ApiPlatform\Doctrine\Orm\Filter\DateFilter; @@ -125,6 +126,7 @@ class Part extends AttachmentContainingDBElement use OrderTrait; use ParametersTrait; use ProjectTrait; + use AssemblyTrait; use AssociationTrait; use EDATrait; @@ -186,6 +188,7 @@ public function __construct() $this->orderdetails = new ArrayCollection(); $this->parameters = new ArrayCollection(); $this->project_bom_entries = new ArrayCollection(); + $this->assembly_bom_entries = new ArrayCollection(); $this->associated_parts_as_owner = new ArrayCollection(); $this->associated_parts_as_other = new ArrayCollection(); diff --git a/src/Entity/Parts/PartTraits/AssemblyTrait.php b/src/Entity/Parts/PartTraits/AssemblyTrait.php new file mode 100644 index 000000000..2d82c32f8 --- /dev/null +++ b/src/Entity/Parts/PartTraits/AssemblyTrait.php @@ -0,0 +1,45 @@ + $assembly_bom_entries + */ + #[ORM\OneToMany(mappedBy: 'part', targetEntity: AssemblyBOMEntry::class, cascade: ['remove'], orphanRemoval: true)] + protected Collection $assembly_bom_entries; + + /** + * Returns all AssemblyBOMEntry that use this part. + * + * @phpstan-return Collection + */ + public function getAssemblyBomEntries(): Collection + { + return $this->assembly_bom_entries; + } + + /** + * Get all assemblies which uses this part. + * + * @return Assembly[] all assemblies which uses this part as a one-dimensional array of Assembly objects + */ + public function getAssemblies(): array + { + $assemblies = []; + + foreach($this->assembly_bom_entries as $entry) { + $assemblies[] = $entry->getAssembly(); + } + + return $assemblies; + } +} diff --git a/src/Entity/ProjectSystem/ProjectBOMEntry.php b/src/Entity/ProjectSystem/ProjectBOMEntry.php index 2a7862ec5..fd613dc22 100644 --- a/src/Entity/ProjectSystem/ProjectBOMEntry.php +++ b/src/Entity/ProjectSystem/ProjectBOMEntry.php @@ -36,6 +36,7 @@ use ApiPlatform\Serializer\Filter\PropertyFilter; use App\ApiPlatform\Filter\LikeFilter; use App\Entity\Contracts\TimeStampableInterface; +use App\Repository\DBElementRepository; use App\Validator\UniqueValidatableInterface; use Doctrine\DBAL\Types\Types; use App\Entity\Base\AbstractDBElement; @@ -54,7 +55,7 @@ * The ProjectBOMEntry class represents an entry in a project's BOM. */ #[ORM\HasLifecycleCallbacks] -#[ORM\Entity] +#[ORM\Entity(repositoryClass: DBElementRepository::class)] #[ORM\Table('project_bom_entries')] #[ApiResource( operations: [ diff --git a/src/Form/AdminPages/AssemblyAdminForm.php b/src/Form/AdminPages/AssemblyAdminForm.php new file mode 100644 index 000000000..dd0a80381 --- /dev/null +++ b/src/Form/AdminPages/AssemblyAdminForm.php @@ -0,0 +1,82 @@ +. + */ +namespace App\Form\AdminPages; + +use App\Entity\Base\AbstractNamedDBElement; +use App\Form\AssemblySystem\AssemblyBOMEntryCollectionType; +use App\Form\Type\RichTextEditorType; +use App\Services\LogSystem\EventCommentNeededHelper; +use App\Settings\MiscSettings\AssemblySettings; +use Symfony\Bundle\SecurityBundle\Security; +use Symfony\Component\Form\Extension\Core\Type\ChoiceType; +use Symfony\Component\Form\Extension\Core\Type\TextType; +use Symfony\Component\Form\FormBuilderInterface; + +class AssemblyAdminForm extends BaseEntityAdminForm +{ + public function __construct( + protected Security $security, + protected EventCommentNeededHelper $eventCommentNeededHelper, + protected ?AssemblySettings $assemblySettings = null, + ) { + parent::__construct($security, $eventCommentNeededHelper, $assemblySettings); + } + + protected function additionalFormElements(FormBuilderInterface $builder, array $options, AbstractNamedDBElement $entity): void + { + $builder->add('description', RichTextEditorType::class, [ + 'required' => false, + 'label' => 'part.edit.description', + 'mode' => 'markdown-single_line', + 'empty_data' => '', + 'attr' => [ + 'placeholder' => 'part.edit.description.placeholder', + 'rows' => 2, + ], + ]); + + $builder->add('bom_entries', AssemblyBOMEntryCollectionType::class); + + $builder->add('status', ChoiceType::class, [ + 'attr' => [ + 'class' => 'form-select', + ], + 'label' => 'assembly.edit.status', + 'required' => false, + 'empty_data' => '', + 'choices' => [ + 'assembly.status.draft' => 'draft', + 'assembly.status.planning' => 'planning', + 'assembly.status.in_production' => 'in_production', + 'assembly.status.finished' => 'finished', + 'assembly.status.archived' => 'archived', + ], + ]); + + $builder->add('ipn', TextType::class, [ + 'required' => false, + 'empty_data' => null, + 'label' => 'assembly.edit.ipn', + ]); + } +} diff --git a/src/Form/AdminPages/BaseEntityAdminForm.php b/src/Form/AdminPages/BaseEntityAdminForm.php index 5a4ef5bce..35afbaa1a 100644 --- a/src/Form/AdminPages/BaseEntityAdminForm.php +++ b/src/Form/AdminPages/BaseEntityAdminForm.php @@ -22,10 +22,12 @@ namespace App\Form\AdminPages; +use App\Entity\AssemblySystem\Assembly; use App\Entity\PriceInformations\Currency; use App\Entity\ProjectSystem\Project; use App\Entity\UserSystem\Group; use App\Services\LogSystem\EventCommentType; +use App\Settings\MiscSettings\AssemblySettings; use Symfony\Bundle\SecurityBundle\Security; use App\Entity\Base\AbstractNamedDBElement; use App\Entity\Base\AbstractStructuralDBElement; @@ -47,8 +49,11 @@ class BaseEntityAdminForm extends AbstractType { - public function __construct(protected Security $security, protected EventCommentNeededHelper $eventCommentNeededHelper) - { + public function __construct( + protected Security $security, + protected EventCommentNeededHelper $eventCommentNeededHelper, + protected ?AssemblySettings $assemblySettings = null, + ) { } public function configureOptions(OptionsResolver $resolver): void @@ -69,6 +74,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void ->add('name', TextType::class, [ 'empty_data' => '', 'label' => 'name.label', + 'data' => $is_new && $entity instanceof Assembly && $this->assemblySettings !== null && $this->assemblySettings->useIpnPlaceholderInName ? '%%ipn%%' : $entity->getName(), 'attr' => [ 'placeholder' => 'part.name.placeholder', ], @@ -114,7 +120,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void ); } - if ($entity instanceof AbstractStructuralDBElement && !($entity instanceof Group || $entity instanceof Project || $entity instanceof Currency)) { + if ($entity instanceof AbstractStructuralDBElement && !($entity instanceof Group || $entity instanceof Project || $entity instanceof Assembly || $entity instanceof Currency)) { $builder->add('alternative_names', TextType::class, [ 'required' => false, 'label' => 'entity.edit.alternative_names.label', diff --git a/src/Form/AssemblySystem/AssemblyAddPartsType.php b/src/Form/AssemblySystem/AssemblyAddPartsType.php new file mode 100644 index 000000000..1fa671266 --- /dev/null +++ b/src/Form/AssemblySystem/AssemblyAddPartsType.php @@ -0,0 +1,91 @@ +. + */ +namespace App\Form\AssemblySystem; + +use App\Entity\AssemblySystem\Assembly; +use App\Entity\AssemblySystem\AssemblyBOMEntry; +use App\Form\Type\StructuralEntityType; +use App\Validator\Constraints\UniqueObjectCollection; +use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\Extension\Core\Type\SubmitType; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\FormEvent; +use Symfony\Component\Form\FormEvents; +use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\Validator\Constraints\NotNull; + +class AssemblyAddPartsType extends AbstractType +{ + public function buildForm(FormBuilderInterface $builder, array $options): void + { + $builder->add('assembly', StructuralEntityType::class, [ + 'class' => Assembly::class, + 'required' => true, + 'disabled' => $options['assembly'] instanceof Assembly, //If a assembly is given, disable the field + 'data' => $options['assembly'], + 'constraints' => [ + new NotNull() + ] + ]); + $builder->add('bom_entries', AssemblyBOMEntryCollectionType::class, [ + 'entry_options' => [ + 'constraints' => [ + new UniqueEntity(fields: ['part'], message: 'assembly.bom_entry.part_already_in_bom', + entityClass: AssemblyBOMEntry::class), + new UniqueEntity(fields: ['referencedAssembly'], message: 'assembly.bom_entry.assembly_already_in_bom', + entityClass: AssemblyBOMEntry::class), + new UniqueEntity(fields: ['name'], message: 'assembly.bom_entry.name_already_in_bom', + entityClass: AssemblyBOMEntry::class, ignoreNull: true), + ] + ], + 'constraints' => [ + new UniqueObjectCollection(message: 'assembly.bom_entry.part_already_in_bom', fields: ['part']), + new UniqueObjectCollection(message: 'assembly.bom_entry.assembly_already_in_bom', fields: ['referencedAssembly']), + new UniqueObjectCollection(message: 'assembly.bom_entry.name_already_in_bom', fields: ['name']), + ] + ]); + $builder->add('submit', SubmitType::class, ['label' => 'save']); + + //After submit set the assembly for all bom entries, so that it can be validated properly + $builder->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) { + $form = $event->getForm(); + /** @var Assembly $assembly */ + $assembly = $form->get('assembly')->getData(); + $bom_entries = $form->get('bom_entries')->getData(); + + foreach ($bom_entries as $bom_entry) { + $bom_entry->setAssembly($assembly); + } + }); + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'assembly' => null, + ]); + + $resolver->setAllowedTypes('assembly', ['null', Assembly::class]); + } +} diff --git a/src/Form/AssemblySystem/AssemblyBOMEntryCollectionType.php b/src/Form/AssemblySystem/AssemblyBOMEntryCollectionType.php new file mode 100644 index 000000000..04293f4e0 --- /dev/null +++ b/src/Form/AssemblySystem/AssemblyBOMEntryCollectionType.php @@ -0,0 +1,32 @@ +setDefaults([ + 'entry_type' => AssemblyBOMEntryType::class, + 'entry_options' => [ + 'label' => false, + ], + 'allow_add' => true, + 'allow_delete' => true, + 'by_reference' => false, + 'reindex_enable' => true, + 'label' => false, + ]); + } +} diff --git a/src/Form/AssemblySystem/AssemblyBOMEntryType.php b/src/Form/AssemblySystem/AssemblyBOMEntryType.php new file mode 100644 index 000000000..8b56dfeb0 --- /dev/null +++ b/src/Form/AssemblySystem/AssemblyBOMEntryType.php @@ -0,0 +1,98 @@ +addEventListener(FormEvents::PRE_SET_DATA, function (PreSetDataEvent $event) { + $form = $event->getForm(); + /** @var AssemblyBOMEntry $data */ + $data = $event->getData(); + + $form->add('quantity', SIUnitType::class, [ + 'label' => 'assembly.bom.quantity', + 'measurement_unit' => $data && $data->getPart() ? $data->getPart()->getPartUnit() : null, + ]); + }); + + $builder + ->add('part', PartSelectType::class, [ + 'required' => false, + ]) + ->add('referencedAssembly', AssemblySelectType::class, [ + 'label' => 'assembly.bom.referencedAssembly', + 'required' => false, + ]) + ->add('name', TextType::class, [ + 'label' => 'assembly.bom.name', + 'help' => 'assembly.bom.name.help', + 'required' => false, + ]) + ->add('designator', TextType::class, [ + 'label' => 'assembly.bom.designator', + 'help' => 'assembly.bom.designator.help', + 'empty_data' => '', + 'required' => false, + ]) + ->add('mountnames', TextType::class, [ + 'required' => false, + 'label' => 'assembly.bom.mountnames', + 'empty_data' => '', + 'attr' => [ + 'class' => 'tagsinput', + 'data-controller' => 'elements--tagsinput', + ], + ]) + ->add('comment', RichTextEditorType::class, [ + 'required' => false, + 'label' => 'assembly.bom.comment', + 'empty_data' => '', + 'mode' => 'markdown-single_line', + 'attr' => [ + 'rows' => 2, + ], + ]) + ->add('price', BigDecimalNumberType::class, [ + 'label' => false, + 'required' => false, + 'scale' => 5, + 'html5' => true, + 'attr' => [ + 'min' => 0, + 'step' => 'any', + ], + ]) + ->add('priceCurrency', CurrencyEntityType::class, [ + 'required' => false, + 'label' => false, + 'short' => true, + ] + ); + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => AssemblyBOMEntry::class, + ]); + } +} diff --git a/src/Form/Filters/AssemblyFilterType.php b/src/Form/Filters/AssemblyFilterType.php new file mode 100644 index 000000000..acfbb1a8e --- /dev/null +++ b/src/Form/Filters/AssemblyFilterType.php @@ -0,0 +1,114 @@ +. + */ +namespace App\Form\Filters; + +use App\DataTables\Filters\AssemblyFilter; +use App\Entity\Attachments\AttachmentType; +use App\Form\Filters\Constraints\DateTimeConstraintType; +use App\Form\Filters\Constraints\NumberConstraintType; +use App\Form\Filters\Constraints\StructuralEntityConstraintType; +use App\Form\Filters\Constraints\TextConstraintType; +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\Extension\Core\Type\ResetType; +use Symfony\Component\Form\Extension\Core\Type\SubmitType; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\OptionsResolver\OptionsResolver; + +class AssemblyFilterType extends AbstractType +{ + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'compound' => true, + 'data_class' => AssemblyFilter::class, + 'csrf_protection' => false, + ]); + } + + public function buildForm(FormBuilderInterface $builder, array $options): void + { + /* + * Common tab + */ + + $builder->add('name', TextConstraintType::class, [ + 'label' => 'assembly.filter.name', + ]); + + $builder->add('description', TextConstraintType::class, [ + 'label' => 'assembly.filter.description', + ]); + + $builder->add('comment', TextConstraintType::class, [ + 'label' => 'assembly.filter.comment' + ]); + + /* + * Advanced tab + */ + + $builder->add('dbId', NumberConstraintType::class, [ + 'label' => 'assembly.filter.dbId', + 'min' => 1, + 'step' => 1, + ]); + + $builder->add('ipn', TextConstraintType::class, [ + 'label' => 'assembly.filter.ipn', + ]); + + $builder->add('lastModified', DateTimeConstraintType::class, [ + 'label' => 'lastModified' + ]); + + $builder->add('addedDate', DateTimeConstraintType::class, [ + 'label' => 'createdAt' + ]); + + /** + * Attachments count + */ + $builder->add('attachmentsCount', NumberConstraintType::class, [ + 'label' => 'assembly.filter.attachments_count', + 'step' => 1, + 'min' => 0, + ]); + + $builder->add('attachmentType', StructuralEntityConstraintType::class, [ + 'label' => 'attachment.attachment_type', + 'entity_class' => AttachmentType::class + ]); + + $builder->add('attachmentName', TextConstraintType::class, [ + 'label' => 'assembly.filter.attachmentName', + ]); + + $builder->add('submit', SubmitType::class, [ + 'label' => 'filter.submit', + ]); + + $builder->add('discard', ResetType::class, [ + 'label' => 'filter.discard', + ]); + } +} diff --git a/src/Form/Filters/AttachmentFilterType.php b/src/Form/Filters/AttachmentFilterType.php index ff80bd384..a44588955 100644 --- a/src/Form/Filters/AttachmentFilterType.php +++ b/src/Form/Filters/AttachmentFilterType.php @@ -23,6 +23,7 @@ namespace App\Form\Filters; use App\DataTables\Filters\AttachmentFilter; +use App\Entity\Attachments\AssemblyAttachment; use App\Entity\Attachments\AttachmentType; use App\Entity\Attachments\AttachmentTypeAttachment; use App\Entity\Attachments\CategoryAttachment; @@ -80,6 +81,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'category.label' => CategoryAttachment::class, 'currency.label' => CurrencyAttachment::class, 'project.label' => ProjectAttachment::class, + 'assembly.label' => AssemblyAttachment::class, 'footprint.label' => FootprintAttachment::class, 'group.label' => GroupAttachment::class, 'label_profile.label' => LabelAttachment::class, diff --git a/src/Form/Filters/LogFilterType.php b/src/Form/Filters/LogFilterType.php index c973ad0fb..4fb5bc499 100644 --- a/src/Form/Filters/LogFilterType.php +++ b/src/Form/Filters/LogFilterType.php @@ -114,6 +114,8 @@ public function buildForm(FormBuilderInterface $builder, array $options): void LogTargetType::CATEGORY => 'category.label', LogTargetType::PROJECT => 'project.label', LogTargetType::BOM_ENTRY => 'project_bom_entry.label', + LogTargetType::ASSEMBLY => 'assembly.label', + LogTargetType::ASSEMBLY_BOM_ENTRY => 'assembly_bom_entry.label', LogTargetType::FOOTPRINT => 'footprint.label', LogTargetType::GROUP => 'group.label', LogTargetType::MANUFACTURER => 'manufacturer.label', diff --git a/src/Form/Type/AssemblySelectType.php b/src/Form/Type/AssemblySelectType.php new file mode 100644 index 000000000..282161b17 --- /dev/null +++ b/src/Form/Type/AssemblySelectType.php @@ -0,0 +1,122 @@ +addEventListener(FormEvents::PRE_SET_DATA, function (PreSetDataEvent $event) { + $form = $event->getForm(); + $config = $form->getConfig()->getOptions(); + $data = $event->getData() ?? []; + + $config['compound'] = false; + $config['choices'] = is_iterable($data) ? $data : [$data]; + $config['error_bubbling'] = true; + + $form->add('autocomplete', EntityType::class, $config); + }); + + //After form submit, we have to add the selected element as choice, otherwise the form will not accept this element + $builder->addEventListener(FormEvents::PRE_SUBMIT, function(FormEvent $event) { + $data = $event->getData(); + $form = $event->getForm(); + $options = $form->get('autocomplete')->getConfig()->getOptions(); + + + if (!isset($data['autocomplete']) || '' === $data['autocomplete'] || empty($data['autocomplete'])) { + $options['choices'] = []; + } else { + //Extract the ID from the submitted data + $id = $data['autocomplete']; + //Find the element in the database + $element = $this->em->find($options['class'], $id); + + //Add the element as choice + $options['choices'] = [$element]; + $options['error_bubbling'] = true; + $form->add('autocomplete', EntityType::class, $options); + } + }); + + $builder->setDataMapper($this); + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'class' => Assembly::class, + 'choice_label' => 'name', + 'compound' => true, + 'error_bubbling' => false, + ]); + + $resolver->setDefaults([ + 'attr' => [ + 'data-controller' => 'elements--assembly-select', + 'data-autocomplete' => $this->urlGenerator->generate('typeahead_assemblies', ['query' => '__QUERY__']), + 'autocomplete' => 'off', + ], + ]); + + $resolver->setDefaults([ + //Prefill the selected choice with the needed data, so the user can see it without an additional Ajax request + 'choice_attr' => ChoiceList::attr($this, function (?Assembly $assembly) { + if($assembly instanceof Assembly) { + //Determine the picture to show: + $preview_attachment = $this->previewGenerator->getTablePreviewAttachment($assembly); + if ($preview_attachment instanceof Attachment) { + $preview_url = $this->attachmentURLGenerator->getThumbnailURL($preview_attachment, + 'thumbnail_sm'); + } else { + $preview_url = ''; + } + } + + return $assembly instanceof Assembly ? [ + 'data-description' => $assembly->getDescription() ? mb_strimwidth($assembly->getDescription(), 0, 127, '...') : '', + 'data-category' => '', + 'data-footprint' => '', + 'data-image' => $preview_url, + ] : []; + }) + ]); + } + + public function mapDataToForms($data, \Traversable $forms): void + { + $form = current(iterator_to_array($forms, false)); + $form->setData($data); + } + + public function mapFormsToData(\Traversable $forms, &$data): void + { + $form = current(iterator_to_array($forms, false)); + $data = $form->getData(); + } + +} diff --git a/src/Form/Type/PartSelectType.php b/src/Form/Type/PartSelectType.php index 34b8fc7c4..8cdd6256c 100644 --- a/src/Form/Type/PartSelectType.php +++ b/src/Form/Type/PartSelectType.php @@ -50,7 +50,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void $options = $form->get('autocomplete')->getConfig()->getOptions(); - if (!isset($data['autocomplete']) || '' === $data['autocomplete']) { + if (!isset($data['autocomplete']) || '' === $data['autocomplete'] || empty($data['autocomplete'])) { $options['choices'] = []; } else { //Extract the ID from the submitted data diff --git a/src/Helpers/Assemblies/AssemblyPartAggregator.php b/src/Helpers/Assemblies/AssemblyPartAggregator.php new file mode 100644 index 000000000..46495935d --- /dev/null +++ b/src/Helpers/Assemblies/AssemblyPartAggregator.php @@ -0,0 +1,273 @@ +. + */ +namespace App\Helpers\Assemblies; + +use App\Entity\AssemblySystem\Assembly; +use App\Entity\AssemblySystem\AssemblyBOMEntry; +use App\Entity\Parts\Part; +use Dompdf\Dompdf; +use Dompdf\Options; +use Twig\Environment; + +class AssemblyPartAggregator +{ + public function __construct(private readonly Environment $twig) + { + } + + /** + * Aggregate the required parts and their total quantities for an assembly. + * + * @param Assembly $assembly The assembly to process. + * @param float $multiplier The quantity multiplier from the parent assembly. + * @return array Array of parts with their aggregated quantities, keyed by Part ID. + */ + public function getAggregatedParts(Assembly $assembly, float $multiplier): array + { + $aggregatedParts = []; + + // Start processing the assembly recursively + $this->processAssembly($assembly, $multiplier, $aggregatedParts); + + // Return the final aggregated list of parts + return $aggregatedParts; + } + + /** + * Recursive helper to process an assembly and all its BOM entries. + * + * @param Assembly $assembly The current assembly to process. + * @param float $multiplier The quantity multiplier from the parent assembly. + * @param array &$aggregatedParts The array to accumulate parts and their quantities. + */ + private function processAssembly(Assembly $assembly, float $multiplier, array &$aggregatedParts): void + { + /** @var AssemblyBOMEntry $bomEntry */ + foreach ($assembly->getBomEntries() as $bomEntry) { + // If the BOM entry refers to a part, add its quantity + if ($bomEntry->getPart() instanceof Part) { + $part = $bomEntry->getPart(); + + if (!isset($aggregatedParts[$part->getId()])) { + $aggregatedParts[$part->getId()] = [ + 'part' => $part, + 'assembly' => $assembly, + 'name' => $bomEntry->getName(), + 'designator' => $bomEntry->getDesignator(), + 'quantity' => $bomEntry->getQuantity(), + 'multiplier' => $multiplier, + ]; + } + } elseif ($bomEntry->getReferencedAssembly() instanceof Assembly) { + // If the BOM entry refers to another assembly, process it recursively + $this->processAssembly($bomEntry->getReferencedAssembly(), $bomEntry->getQuantity(), $aggregatedParts); + } else { + $aggregatedParts[] = [ + 'part' => null, + 'assembly' => $assembly, + 'name' => $bomEntry->getName(), + 'designator' => $bomEntry->getDesignator(), + 'quantity' => $bomEntry->getQuantity(), + 'multiplier' => $multiplier, + ]; + } + } + } + + /** + * Exports a hierarchical Bill of Materials (BOM) for assemblies and parts in a readable format, + * including the multiplier for each part and assembly. + * + * @param Assembly $assembly The root assembly to export. + * @param string $indentationSymbol The symbol used for indentation (e.g., ' '). + * @param int $initialDepth The starting depth for formatting (default: 0). + * @return string Human-readable hierarchical BOM list. + */ + public function exportReadableHierarchy(Assembly $assembly, string $indentationSymbol = ' ', int $initialDepth = 0): string + { + // Start building the hierarchy + $output = ''; + $this->processAssemblyHierarchy($assembly, $initialDepth, 1, $indentationSymbol, $output); + + return $output; + } + + public function exportReadableHierarchyForPdf(array $assemblyHierarchies): string + { + $html = $this->twig->render('assemblies/export_bom_pdf.html.twig', [ + 'assemblies' => $assemblyHierarchies, + ]); + + $options = new Options(); + $options->set('isHtml5ParserEnabled', true); + $options->set('isPhpEnabled', true); + + $dompdf = new Dompdf($options); + $dompdf->loadHtml($html); + $dompdf->setPaper('A4'); + $dompdf->render(); + + $canvas = $dompdf->getCanvas(); + $font = $dompdf->getFontMetrics()->getFont('Arial', 'normal'); + + return $dompdf->output(); + } + + /** + * Recursive method to process assemblies and their parts. + * + * @param Assembly $assembly The current assembly to process. + * @param int $depth The current depth in the hierarchy. + * @param float $parentMultiplier The multiplier inherited from the parent (default is 1 for root). + * @param string $indentationSymbol The symbol used for indentation. + * @param string &$output The cumulative output string. + */ + private function processAssemblyHierarchy(Assembly $assembly, int $depth, float $parentMultiplier, string $indentationSymbol, string &$output): void + { + // Add the current assembly to the output + if ($depth === 0) { + $output .= sprintf( + "%sAssembly: %s [IPN: %s]\n\n", + str_repeat($indentationSymbol, $depth), + $assembly->getName(), + $assembly->getIpn(), + ); + } else { + $output .= sprintf( + "%sAssembly: %s [IPN: %s, Multiplier: %.2f]\n\n", + str_repeat($indentationSymbol, $depth), + $assembly->getName(), + $assembly->getIpn(), + $parentMultiplier + ); + } + + // Gruppiere BOM-Einträge in Kategorien + $parts = []; + $referencedAssemblies = []; + $others = []; + + foreach ($assembly->getBomEntries() as $bomEntry) { + if ($bomEntry->getPart() instanceof Part) { + $parts[] = $bomEntry; + } elseif ($bomEntry->getReferencedAssembly() instanceof Assembly) { + $referencedAssemblies[] = $bomEntry; + } else { + $others[] = $bomEntry; + } + } + + if (!empty($parts)) { + // Process each BOM entry for the current assembly + foreach ($parts as $bomEntry) { + $effectiveQuantity = $bomEntry->getQuantity() * $parentMultiplier; + + $output .= sprintf( + "%sPart: %s [IPN: %s, MPNR: %s, Quantity: %.2f%s, EffectiveQuantity: %.2f]\n", + str_repeat($indentationSymbol, $depth + 1), + $bomEntry->getPart()?->getName(), + $bomEntry->getPart()?->getIpn() ?? '-', + $bomEntry->getPart()?->getManufacturerProductNumber() ?? '-', + $bomEntry->getQuantity(), + $parentMultiplier > 1 ? sprintf(", Multiplier: %.2f", $parentMultiplier) : '', + $effectiveQuantity, + ); + } + + $output .= "\n"; + } + + foreach ($referencedAssemblies as $bomEntry) { + // Add referenced assembly details + $referencedQuantity = $bomEntry->getQuantity() * $parentMultiplier; + + $output .= sprintf( + "%sReferenced Assembly: %s [IPN: %s, Quantity: %.2f%s, EffectiveQuantity: %.2f]\n", + str_repeat($indentationSymbol, $depth + 1), + $bomEntry->getReferencedAssembly()->getName(), + $bomEntry->getReferencedAssembly()->getIpn() ?? '-', + $bomEntry->getQuantity(), + $parentMultiplier > 1 ? sprintf(", Multiplier: %.2f", $parentMultiplier) : '', + $referencedQuantity, + ); + + // Recurse into the referenced assembly + $this->processAssemblyHierarchy( + $bomEntry->getReferencedAssembly(), + $depth + 2, // Increase depth for nested assemblies + $referencedQuantity, // Pass the calculated multiplier + $indentationSymbol, + $output + ); + } + + foreach ($others as $bomEntry) { + $output .= sprintf( + "%sOther: %s [Quantity: %.2f, Multiplier: %.2f]\n", + str_repeat($indentationSymbol, $depth + 1), + $bomEntry->getName(), + $bomEntry->getQuantity(), + $parentMultiplier, + ); + } + } + + public function processAssemblyHierarchyForPdf(Assembly $assembly, int $depth, float $quantity, float $parentMultiplier): array + { + $result = [ + 'name' => $assembly->getName(), + 'ipn' => $assembly->getIpn(), + 'quantity' => $quantity, + 'multiplier' => $depth === 0 ? null : $parentMultiplier, + 'parts' => [], + 'referencedAssemblies' => [], + 'others' => [], + ]; + + foreach ($assembly->getBomEntries() as $bomEntry) { + if ($bomEntry->getPart() instanceof Part) { + $result['parts'][] = [ + 'name' => $bomEntry->getPart()->getName(), + 'ipn' => $bomEntry->getPart()->getIpn(), + 'quantity' => $bomEntry->getQuantity(), + 'effectiveQuantity' => $bomEntry->getQuantity() * $parentMultiplier, + ]; + } elseif ($bomEntry->getReferencedAssembly() instanceof Assembly) { + $result['referencedAssemblies'][] = $this->processAssemblyHierarchyForPdf( + $bomEntry->getReferencedAssembly(), + $depth + 1, + $bomEntry->getQuantity(), + $parentMultiplier * $bomEntry->getQuantity() + ); + } else { + $result['others'][] = [ + 'name' => $bomEntry->getName(), + 'quantity' => $bomEntry->getQuantity(), + 'multiplier' => $parentMultiplier, + ]; + } + } + + return $result; + } +} diff --git a/src/Repository/AssemblyRepository.php b/src/Repository/AssemblyRepository.php new file mode 100644 index 000000000..eef366905 --- /dev/null +++ b/src/Repository/AssemblyRepository.php @@ -0,0 +1,69 @@ +. + */ + +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 . + */ + +namespace App\Repository; + +use App\Entity\AssemblySystem\Assembly; + +/** + * @template TEntityClass of Assembly + * @extends StructuralDBElementRepository + */ +class AssemblyRepository extends StructuralDBElementRepository +{ + /** + * @return Assembly[] + */ + public function autocompleteSearch(string $query, int $max_limits = 50): array + { + $qb = $this->createQueryBuilder('assembly'); + $qb->select('assembly') + ->where('ILIKE(assembly.name, :query) = TRUE') + ->orWhere('ILIKE(assembly.description, :query) = TRUE'); + + $qb->setParameter('query', '%'.$query.'%'); + + $qb->setMaxResults($max_limits); + $qb->orderBy('NATSORT(assembly.name)', 'ASC'); + + return $qb->getQuery()->getResult(); + } +} diff --git a/src/Repository/DBElementRepository.php b/src/Repository/DBElementRepository.php index 2437e8488..23ad296aa 100644 --- a/src/Repository/DBElementRepository.php +++ b/src/Repository/DBElementRepository.php @@ -154,4 +154,14 @@ protected function setField(AbstractDBElement $element, string $field, int $new_ $property->setAccessible(true); $property->setValue($element, $new_value); } + + protected function save(AbstractDBElement $entity, bool $flush = true): void + { + $manager = $this->getEntityManager(); + $manager->persist($entity); + + if ($flush) { + $manager->flush(); + } + } } diff --git a/src/Security/Voter/AttachmentVoter.php b/src/Security/Voter/AttachmentVoter.php index bd7ae4df8..766aaeac4 100644 --- a/src/Security/Voter/AttachmentVoter.php +++ b/src/Security/Voter/AttachmentVoter.php @@ -22,6 +22,7 @@ namespace App\Security\Voter; +use App\Entity\Attachments\AssemblyAttachment; use App\Services\UserSystem\VoterHelper; use Symfony\Bundle\SecurityBundle\Security; use App\Entity\Attachments\AttachmentContainingDBElement; @@ -89,6 +90,8 @@ protected function voteOnAttribute(string $attribute, $subject, TokenInterface $ $param = 'currencies'; } elseif (is_a($subject, ProjectAttachment::class, true)) { $param = 'projects'; + } elseif (is_a($subject, AssemblyAttachment::class, true)) { + $param = 'assemblies'; } elseif (is_a($subject, FootprintAttachment::class, true)) { $param = 'footprints'; } elseif (is_a($subject, GroupAttachment::class, true)) { diff --git a/src/Security/Voter/StructureVoter.php b/src/Security/Voter/StructureVoter.php index ad0299a79..8079757cd 100644 --- a/src/Security/Voter/StructureVoter.php +++ b/src/Security/Voter/StructureVoter.php @@ -22,6 +22,7 @@ namespace App\Security\Voter; +use App\Entity\AssemblySystem\Assembly; use App\Entity\Attachments\AttachmentType; use App\Entity\ProjectSystem\Project; use App\Entity\Parts\Category; @@ -47,6 +48,7 @@ final class StructureVoter extends Voter AttachmentType::class => 'attachment_types', Category::class => 'categories', Project::class => 'projects', + Assembly::class => 'assemblies', Footprint::class => 'footprints', Manufacturer::class => 'manufacturers', StorageLocation::class => 'storelocations', diff --git a/src/Services/Attachments/AssemblyPreviewGenerator.php b/src/Services/Attachments/AssemblyPreviewGenerator.php new file mode 100644 index 000000000..9ecbbd070 --- /dev/null +++ b/src/Services/Attachments/AssemblyPreviewGenerator.php @@ -0,0 +1,93 @@ +. + */ + +declare(strict_types=1); + +namespace App\Services\Attachments; + +use App\Entity\AssemblySystem\Assembly; +use App\Entity\Attachments\Attachment; + +class AssemblyPreviewGenerator +{ + public function __construct(protected AttachmentManager $attachmentHelper) + { + } + + /** + * Returns a list of attachments that can be used for previewing the assembly ordered by priority. + * + * @param Assembly $assembly the assembly for which the attachments should be determined + * + * @return (Attachment|null)[] + * + * @psalm-return list + */ + public function getPreviewAttachments(Assembly $assembly): array + { + $list = []; + + //Master attachment has top priority + $attachment = $assembly->getMasterPictureAttachment(); + if ($this->isAttachmentValidPicture($attachment)) { + $list[] = $attachment; + } + + //Then comes the other images of the assembly + foreach ($assembly->getAttachments() as $attachment) { + //Dont show the master attachment twice + if ($this->isAttachmentValidPicture($attachment) && $attachment !== $assembly->getMasterPictureAttachment()) { + $list[] = $attachment; + } + } + + return $list; + } + + /** + * Determines what attachment should be used for previewing a assembly (especially in assembly table). + * The returned attachment is guaranteed to be existing and be a picture. + * + * @param Assembly $assembly The assembly for which the attachment should be determined + */ + public function getTablePreviewAttachment(Assembly $assembly): ?Attachment + { + $attachment = $assembly->getMasterPictureAttachment(); + if ($this->isAttachmentValidPicture($attachment)) { + return $attachment; + } + + return null; + } + + /** + * Checks if a attachment is exising and a valid picture. + * + * @param Attachment|null $attachment the attachment that should be checked + * + * @return bool true if the attachment is valid + */ + protected function isAttachmentValidPicture(?Attachment $attachment): bool + { + return $attachment instanceof Attachment + && $attachment->isPicture() + && $this->attachmentHelper->isFileExisting($attachment); + } +} diff --git a/src/Services/Attachments/AttachmentSubmitHandler.php b/src/Services/Attachments/AttachmentSubmitHandler.php index 9fbc3fe39..4d0da57c5 100644 --- a/src/Services/Attachments/AttachmentSubmitHandler.php +++ b/src/Services/Attachments/AttachmentSubmitHandler.php @@ -22,6 +22,7 @@ namespace App\Services\Attachments; +use App\Entity\Attachments\AssemblyAttachment; use App\Entity\Attachments\Attachment; use App\Entity\Attachments\AttachmentContainingDBElement; use App\Entity\Attachments\AttachmentType; @@ -84,6 +85,7 @@ public function __construct( CategoryAttachment::class => 'category', CurrencyAttachment::class => 'currency', ProjectAttachment::class => 'project', + AssemblyAttachment::class => 'assembly', FootprintAttachment::class => 'footprint', GroupAttachment::class => 'group', ManufacturerAttachment::class => 'manufacturer', diff --git a/src/Services/ElementTypeNameGenerator.php b/src/Services/ElementTypeNameGenerator.php index 326707b77..130cc53dd 100644 --- a/src/Services/ElementTypeNameGenerator.php +++ b/src/Services/ElementTypeNameGenerator.php @@ -22,6 +22,8 @@ namespace App\Services; +use App\Entity\AssemblySystem\Assembly; +use App\Entity\AssemblySystem\AssemblyBOMEntry; use App\Entity\Attachments\Attachment; use App\Entity\Attachments\AttachmentContainingDBElement; use App\Entity\Attachments\AttachmentType; @@ -66,6 +68,8 @@ public function __construct(protected TranslatorInterface $translator, private r AttachmentType::class => $this->translator->trans('attachment_type.label'), Project::class => $this->translator->trans('project.label'), ProjectBOMEntry::class => $this->translator->trans('project_bom_entry.label'), + Assembly::class => $this->translator->trans('assembly.label'), + AssemblyBOMEntry::class => $this->translator->trans('assembly_bom_entry.label'), Footprint::class => $this->translator->trans('footprint.label'), Manufacturer::class => $this->translator->trans('manufacturer.label'), MeasurementUnit::class => $this->translator->trans('measurement_unit.label'), @@ -182,6 +186,8 @@ public function formatLabelHTMLForEntity(AbstractDBElement $entity, bool $includ $on = $entity->getOrderdetail()->getPart(); } elseif ($entity instanceof ProjectBOMEntry && $entity->getProject() instanceof Project) { $on = $entity->getProject(); + } elseif ($entity instanceof AssemblyBOMEntry && $entity->getAssembly() instanceof Assembly) { + $on = $entity->getAssembly(); } if (isset($on) && $on instanceof NamedElementInterface) { diff --git a/src/Services/EntityURLGenerator.php b/src/Services/EntityURLGenerator.php index 78db06f07..8e1704b46 100644 --- a/src/Services/EntityURLGenerator.php +++ b/src/Services/EntityURLGenerator.php @@ -22,6 +22,7 @@ namespace App\Services; +use App\Entity\AssemblySystem\Assembly; use App\Entity\Attachments\Attachment; use App\Entity\Attachments\AttachmentType; use App\Entity\Attachments\PartAttachment; @@ -98,6 +99,7 @@ public function timeTravelURL(AbstractDBElement $entity, \DateTimeInterface $dat AttachmentType::class => 'attachment_type_edit', Category::class => 'category_edit', Project::class => 'project_edit', + Assembly::class => 'assembly_edit', Supplier::class => 'supplier_edit', Manufacturer::class => 'manufacturer_edit', StorageLocation::class => 'store_location_edit', @@ -204,6 +206,7 @@ public function infoURL(AbstractDBElement $entity): string AttachmentType::class => 'attachment_type_edit', Category::class => 'category_edit', Project::class => 'project_info', + Assembly::class => 'assembly_info', Supplier::class => 'supplier_edit', Manufacturer::class => 'manufacturer_edit', StorageLocation::class => 'store_location_edit', @@ -234,6 +237,7 @@ public function editURL(AbstractDBElement $entity): string AttachmentType::class => 'attachment_type_edit', Category::class => 'category_edit', Project::class => 'project_edit', + Assembly::class => 'assembly_edit', Supplier::class => 'supplier_edit', Manufacturer::class => 'manufacturer_edit', StorageLocation::class => 'store_location_edit', @@ -265,6 +269,7 @@ public function createURL(AbstractDBElement|string $entity): string AttachmentType::class => 'attachment_type_new', Category::class => 'category_new', Project::class => 'project_new', + Assembly::class => 'assembly_new', Supplier::class => 'supplier_new', Manufacturer::class => 'manufacturer_new', StorageLocation::class => 'store_location_new', @@ -296,6 +301,7 @@ public function cloneURL(AbstractDBElement $entity): string AttachmentType::class => 'attachment_type_clone', Category::class => 'category_clone', Project::class => 'device_clone', + Assembly::class => 'assembly_clone', Supplier::class => 'supplier_clone', Manufacturer::class => 'manufacturer_clone', StorageLocation::class => 'store_location_clone', @@ -323,6 +329,7 @@ public function listPartsURL(AbstractDBElement $entity): string { $map = [ Project::class => 'project_info', + Assembly::class => 'assembly_info', Category::class => 'part_list_category', Footprint::class => 'part_list_footprint', @@ -341,6 +348,7 @@ public function deleteURL(AbstractDBElement $entity): string AttachmentType::class => 'attachment_type_delete', Category::class => 'category_delete', Project::class => 'project_delete', + Assembly::class => 'assembly_delete', Supplier::class => 'supplier_delete', Manufacturer::class => 'manufacturer_delete', StorageLocation::class => 'store_location_delete', diff --git a/src/Services/ImportExportSystem/BOMImporter.php b/src/Services/ImportExportSystem/BOMImporter.php index 862fa463f..fc0791eef 100644 --- a/src/Services/ImportExportSystem/BOMImporter.php +++ b/src/Services/ImportExportSystem/BOMImporter.php @@ -22,21 +22,37 @@ */ namespace App\Services\ImportExportSystem; +use App\Entity\AssemblySystem\Assembly; +use App\Entity\AssemblySystem\AssemblyBOMEntry; +use App\Entity\Parts\Category; +use App\Entity\Parts\Manufacturer; use App\Entity\Parts\Part; use App\Entity\ProjectSystem\Project; use App\Entity\ProjectSystem\ProjectBOMEntry; +use App\Repository\DBElementRepository; +use App\Repository\PartRepository; +use App\Repository\Parts\CategoryRepository; +use App\Repository\Parts\ManufacturerRepository; use Doctrine\ORM\EntityManagerInterface; use InvalidArgumentException; use League\Csv\Reader; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\File\File; +use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Contracts\Translation\TranslatorInterface; +use UnexpectedValueException; +use Symfony\Component\Validator\ConstraintViolation; /** * @see \App\Tests\Services\ImportExportSystem\BOMImporterTest */ class BOMImporter { + private const IMPORT_TYPE_JSON = 'json'; + private const IMPORT_TYPE_CSV = 'csv'; + private const IMPORT_TYPE_KICAD_PCB = 'kicad_pcbnew'; + private const IMPORT_TYPE_KICAD_SCHEMATIC = 'kicad_schematic'; private const MAP_KICAD_PCB_FIELDS = [ 0 => 'Id', @@ -47,17 +63,35 @@ class BOMImporter 5 => 'Supplier and ref', ]; + private readonly PartRepository $partRepository; + + private readonly ManufacturerRepository $manufacturerRepository; + + private readonly CategoryRepository $categoryRepository; + + private readonly DBElementRepository $projectBomEntryRepository; + + private readonly DBElementRepository $assemblyBomEntryRepository; + + private string $jsonRoot = ''; + public function __construct( private readonly EntityManagerInterface $entityManager, private readonly LoggerInterface $logger, - private readonly BOMValidationService $validationService + private readonly BOMValidationService $validationService, + private readonly TranslatorInterface $translator ) { + $this->partRepository = $this->entityManager->getRepository(Part::class); + $this->manufacturerRepository = $this->entityManager->getRepository(Manufacturer::class); + $this->categoryRepository = $this->entityManager->getRepository(Category::class); + $this->projectBomEntryRepository = $this->entityManager->getRepository(ProjectBOMEntry::class); + $this->assemblyBomEntryRepository = $this->entityManager->getRepository(AssemblyBOMEntry::class); } protected function configureOptions(OptionsResolver $resolver): OptionsResolver { $resolver->setRequired('type'); - $resolver->setAllowedValues('type', ['kicad_pcbnew', 'kicad_schematic']); + $resolver->setAllowedValues('type', [self::IMPORT_TYPE_KICAD_PCB, self::IMPORT_TYPE_KICAD_SCHEMATIC, self::IMPORT_TYPE_JSON, self::IMPORT_TYPE_CSV]); // For flexible schematic import with field mapping $resolver->setDefined(['field_mapping', 'field_priorities', 'delimiter']); @@ -73,27 +107,118 @@ protected function configureOptions(OptionsResolver $resolver): OptionsResolver /** * Converts the given file into an array of BOM entries using the given options and save them into the given project. * The changes are not saved into the database yet. - * @return ProjectBOMEntry[] */ - public function importFileIntoProject(File $file, Project $project, array $options): array + public function importFileIntoProject(UploadedFile $file, Project $project, array $options): ImporterResult { - $bom_entries = $this->fileToBOMEntries($file, $options); + $importerResult = $this->fileToImporterResult($project, $file, $options); - //Assign the bom_entries to the project - foreach ($bom_entries as $bom_entry) { - $project->addBomEntry($bom_entry); + if ($importerResult->getViolations()->count() === 0) { + //Assign the bom_entries to the project + foreach ($importerResult->getBomEntries() as $bomEntry) { + $project->addBomEntry($bomEntry); + } } - return $bom_entries; + return $importerResult; + } + + /** + * Imports a file into an Assembly object and processes its contents. + * + * This method converts the provided file into an ImporterResult object that contains BOM entries and potential + * validation violations. If no violations are found, the BOM entries extracted from the file are added to the + * provided Assembly object. + * + * @param UploadedFile $file The file to be imported and processed. + * @param Assembly $assembly The target Assembly object to which the BOM entries are added. + * @param array $options Options or configurations related to the import process. + * + * @return ImporterResult An object containing the result of the import process, including BOM entries and any violations. + */ + public function importFileIntoAssembly(UploadedFile $file, Assembly $assembly, array $options): ImporterResult + { + $importerResult = $this->fileToImporterResult($assembly, $file, $options); + + if ($importerResult->getViolations()->count() === 0) { + //Assign the bom_entries to the assembly + foreach ($importerResult->getBomEntries() as $bomEntry) { + $assembly->addBomEntry($bomEntry); + } + } + + return $importerResult; } /** - * Converts the given file into an array of BOM entries using the given options. - * @return ProjectBOMEntry[] + * Converts the content of a file into an array of BOM (Bill of Materials) entries. + * + * This method processes the content of the provided file and delegates the conversion + * to a helper method that generates BOM entries based on the provided import object and options. + * + * @param Project|Assembly $importObject The object determining the context of the BOM entries (either a Project or Assembly). + * @param File $file The file whose content will be converted into BOM entries. + * @param array $options Additional options or configurations to be applied during the conversion process. + * + * @return array An array of BOM entries created from the file content. */ - public function fileToBOMEntries(File $file, array $options): array + public function fileToBOMEntries(Project|Assembly $importObject, File $file, array $options): array { - return $this->stringToBOMEntries($file->getContent(), $options); + return $this->stringToBOMEntries($importObject, $file->getContent(), $options); + } + + + /** + * Handles the conversion of an uploaded file into an ImporterResult for a given project or assembly. + * + * This method processes the uploaded file by validating its file extension based on the provided import type + * options and then proceeds to convert the file content into an ImporterResult. If the file extension is + * invalid or unsupported, the result will contain a corresponding violation. + * + * @param Project|Assembly $importObject The context of the import operation (either a Project or Assembly). + * @param UploadedFile $file The uploaded file to be processed. + * @param array $options An array of options, expected to include an 'type' key to determine valid file types. + * + * @return ImporterResult An object containing the results of the import process, including any detected violations. + */ + public function fileToImporterResult(Project|Assembly $importObject, UploadedFile $file, array $options): ImporterResult + { + $result = new ImporterResult(); + + //Available file endings depending on the import type + $validExtensions = match ($options['type']) { + self::IMPORT_TYPE_KICAD_PCB => ['kicad_pcb'], + self::IMPORT_TYPE_JSON => ['json'], + self::IMPORT_TYPE_CSV => ['csv'], + default => [], + }; + + //Get the file extension of the uploaded file + $fileExtension = pathinfo($file->getClientOriginalName(), PATHINFO_EXTENSION); + + //Check whether the file extension is valid + if ($validExtensions === []) { + $result->addViolation($this->buildJsonViolation( + 'validator.bom_importer.invalid_import_type', + 'import.type' + )); + + return $result; + } else if (!in_array(strtolower($fileExtension), $validExtensions, true)) { + $result->addViolation($this->buildJsonViolation( + 'validator.bom_importer.invalid_file_extension', + 'file.extension', + $fileExtension, + [ + '%extension%' => $fileExtension, + '%importType%' => $this->translator->trans($importObject instanceof Project ? 'project.bom_import.type.'.$options['type'] : 'assembly.bom_import.type.'.$options['type']), + '%allowedExtensions%' => implode(', ', $validExtensions), + ] + )); + + return $result; + } + + return $this->stringToImporterResult($importObject, $file->getContent(), $options); } /** @@ -115,31 +240,76 @@ public function validateBOMData(string $data, array $options): array /** * Import string data into an array of BOM entries, which are not yet assigned to a project. - * @param string $data The data to import - * @param array $options An array of options - * @return ProjectBOMEntry[] An array of imported entries + * + * @param Project|Assembly $importObject The object determining the context of the BOM entry (either a Project or Assembly). + * @param string $data The data to import + * @param array $options An array of options + * + * @return ProjectBOMEntry[]|AssemblyBOMEntry[] An array of imported entries */ - public function stringToBOMEntries(string $data, array $options): array + public function stringToBOMEntries(Project|Assembly $importObject, string $data, array $options): array { $resolver = new OptionsResolver(); $resolver = $this->configureOptions($resolver); $options = $resolver->resolve($options); return match ($options['type']) { - 'kicad_pcbnew' => $this->parseKiCADPCB($data), - 'kicad_schematic' => $this->parseKiCADSchematic($data, $options), - default => throw new InvalidArgumentException('Invalid import type!'), + self::IMPORT_TYPE_KICAD_PCB => $this->parseKiCADPCB($data, $importObject)->getBomEntries(), + self::IMPORT_TYPE_KICAD_SCHEMATIC => $this->parseKiCADSchematic($data, $options), + default => throw new InvalidArgumentException($this->translator->trans('validator.bom_importer.invalid_import_type', [], 'validators')), + }; + } + + /** + * Import string data into an array of BOM entries, which are not yet assigned to a project. + * + * @param Project|Assembly $importObject The object determining the context of the BOM entry (either a Project or Assembly). + * @param string $data The data to import + * @param array $options An array of options + * + * @return ImporterResult An result of imported entries or a violation list + */ + public function stringToImporterResult(Project|Assembly $importObject, string $data, array $options): ImporterResult + { + $resolver = new OptionsResolver(); + $resolver = $this->configureOptions($resolver); + $options = $resolver->resolve($options); + + $defaultImporterResult = new ImporterResult(); + $defaultImporterResult->addViolation($this->buildJsonViolation( + 'validator.bom_importer.invalid_import_type', + 'import.type' + )); + + return match ($options['type']) { + self::IMPORT_TYPE_KICAD_PCB => $this->parseKiCADPCB($data, $importObject), + self::IMPORT_TYPE_JSON => $this->parseJson($importObject, $data), + self::IMPORT_TYPE_CSV => $this->parseCsv($importObject, $data), + default => $defaultImporterResult, }; } - private function parseKiCADPCB(string $data): array + /** + * Parses a KiCAD PCB file and imports its BOM (Bill of Materials) entries into the given Project or Assembly context. + * + * This method processes a semicolon-delimited CSV data string, normalizes column names, + * validates the required fields, and creates BOM entries for each record in the data. + * The BOM entries are added to the provided Project or Assembly, depending on the context. + * + * @param string $data The semicolon- or comma-delimited CSV data to be parsed. + * @param Project|Assembly $importObject The object determining the context of the BOM entry (either a Project or Assembly). + * @return ImporterResult The result of the import process, containing the created BOM entries. + * + * @throws UnexpectedValueException If required fields are missing in the provided data. + */ + private function parseKiCADPCB(string $data, Project|Assembly $importObject): ImporterResult { + $result = new ImporterResult(); + $csv = Reader::createFromString($data); $csv->setDelimiter(';'); $csv->setHeaderOffset(0); - $bom_entries = []; - foreach ($csv->getRecords() as $offset => $entry) { //Translate the german field names to english $entry = $this->normalizeColumnNames($entry); @@ -158,16 +328,21 @@ private function parseKiCADPCB(string $data): array throw new \UnexpectedValueException('Quantity missing at line ' . ($offset + 1) . '!'); } - $bom_entry = new ProjectBOMEntry(); - $bom_entry->setName($entry['Designation'] . ' (' . $entry['Package'] . ')'); - $bom_entry->setMountnames($entry['Designator'] ?? ''); + $bom_entry = $importObject instanceof Project ? new ProjectBOMEntry() : new AssemblyBOMEntry(); + if ($bom_entry instanceof ProjectBOMEntry) { + $bom_entry->setName($entry['Designation'] . ' (' . $entry['Package'] . ')'); + } else { + $bom_entry->setName($entry['Designation']); + } + + $bom_entry->setMountnames($entry['Designator']); $bom_entry->setComment($entry['Supplier and ref'] ?? ''); $bom_entry->setQuantity((float) ($entry['Quantity'] ?? 1)); - $bom_entries[] = $bom_entry; + $result->addBomEntry($bom_entry); } - return $bom_entries; + return $result; } /** @@ -227,6 +402,545 @@ private function validateKiCADSchematicData(string $data, array $options): array return $this->validationService->validateBOMEntries($mapped_entries, $options); } + /** + * Parses the given JSON data into an ImporterResult while validating and transforming entries according to the + * specified options and object type. If violations are encountered during parsing, they are added to the result. + * + * The structure of each entry in the JSON data is validated to ensure that required fields (e.g., quantity, and name) + * are present, and optional composite fields, like `part` and its sub-properties, meet specific criteria. Various + * conditions are checked, including whether the provided values are the correct types, and if relationships (like + * matching parts or manufacturers) are resolved successfully. + * + * Violations are added for: + * - Missing or invalid `quantity` values. + * - Non-string `name` values. + * - Invalid structure or missing sub-properties in `part`. + * - Incorrect or unresolved references to parts and their information, such as `id`, `name`, `manufacturer_product_number` + * (mpnr), `internal_part_number` (ipn), or `description`. + * - Inconsistent or absent manufacturer information. + * + * If a match for a part or manufacturer cannot be resolved, a violation is added alongside an indication of the + * imported value and any partially matched information. Warnings for no exact matches are also added for parts + * using specific identifying properties like name, manufacturer product number, or internal part numbers. + * + * Additional validations include: + * - Checking for empty or invalid descriptions. + * - Ensuring manufacturers, if specified, have valid `name` or `id` values. + * + * @param Project|Assembly $importObject The object determining the context of the BOM entry (either a Project or Assembly). + * @param string $data JSON encoded string containing BOM entries data. + * + * @return ImporterResult The result containing parsed data and any violations encountered during the parsing process. + */ + private function parseJson(Project|Assembly $importObject, string $data): ImporterResult + { + $result = new ImporterResult(); + $this->jsonRoot = 'JSON Import for '.($importObject instanceof Project ? 'Project' : 'Assembly'); + + $data = json_decode($data, true); + + foreach ($data as $key => $entry) { + if (!isset($entry['quantity'])) { + $result->addViolation($this->buildJsonViolation( + 'validator.bom_importer.json_csv.quantity.required', + "entry[$key].quantity" + )); + } + + if (isset($entry['quantity']) && (!is_float($entry['quantity']) || $entry['quantity'] <= 0)) { + $result->addViolation($this->buildJsonViolation( + 'validator.bom_importer.json_csv.quantity.float', + "entry[$key].quantity", + $entry['quantity'] + )); + } + + if (isset($entry['name']) && !is_string($entry['name'])) { + $result->addViolation($this->buildJsonViolation( + 'validator.bom_importer.json_csv.parameter.string.notEmpty', + "entry[$key].name", + $entry['name'] + )); + } + + if (isset($entry['part'])) { + $this->processPart($importObject, $entry, $result, $key, self::IMPORT_TYPE_JSON); + } else { + $bomEntry = $this->getOrCreateBomEntry($importObject, $entry['name'] ?? null); + $bomEntry->setQuantity((float) $entry['quantity']); + + $result->addBomEntry($bomEntry); + } + } + + return $result; + } + + + /** + * Parses a CSV string and processes its rows into hierarchical data structures, + * performing validations and converting data based on the provided headers. + * Handles potential violations and manages the creation of BOM entries based on the given type. + * + * @param Project|Assembly $importObject The object determining the context of the BOM entry (either a Project or Assembly). + * @param string $csvData The raw CSV data to parse, with rows separated by newlines. + * + * @return ImporterResult Returns an ImporterResult instance containing BOM entries and any validation violations encountered. + */ + function parseCsv(Project|Assembly $importObject, string $csvData): ImporterResult + { + $result = new ImporterResult(); + $rows = explode("\r\n", trim($csvData)); + $headers = str_getcsv(array_shift($rows)); + + if (count($headers) === 1 && isset($headers[0])) { + //If only one column was recognized, try fallback with semicolon as a separator + $headers = str_getcsv($headers[0], ';'); + } + + foreach ($rows as $key => $row) { + $entry = []; + $values = str_getcsv($row); + + if (count($values) === 1 || count($values) !== count($headers)) { + //If only one column was recognized, try fallback with semicolon as a separator + $values = str_getcsv($row, ';'); + } + + foreach ($headers as $index => $column) { + //Change the column names in small letters + $column = strtolower($column); + + //Convert column name into hierarchy + $path = explode('_', $column); + /** @var array $temp */ + $temp = &$entry; + + /** @var lowercase-string $step */ + foreach ($path as $step) { + if (!isset($temp[$step])) { + $temp[$step] = []; + } + + $temp = &$temp[$step]; + } + + //If there is no value, skip + if (isset($values[$index]) && $values[$index] !== '') { + //Check whether the value is numerical + if (is_numeric($values[$index]) && !in_array($column, ['name','description','manufacturer','designator'], true)) { + //Convert to integer or float + $temp = (str_contains($values[$index], '.')) + ? floatval($values[$index]) + : intval($values[$index]); + } else { + //Leave other data types untouched + $temp = $values[$index]; + } + } + } + + $entry = $this->removeEmptyProperties($entry); + + if (!isset($entry['quantity'])) { + $result->addViolation($this->buildJsonViolation( + 'validator.bom_importer.csv.quantity.required', + "row[$key].quantity" + )); + } + + if (isset($entry['quantity']) && (!is_numeric($entry['quantity']) || $entry['quantity'] <= 0)) { + $result->addViolation($this->buildJsonViolation( + 'validator.bom_importer.csv.quantity.float', + "row[$key].quantity", + $entry['quantity'] + )); + } + + if (isset($entry['name']) && !is_string($entry['name'])) { + $result->addViolation($this->buildJsonViolation( + 'validator.bom_importer.json_csv.parameter.string.notEmpty', + "row[$key].name", + $entry['name'] + )); + } + + if (isset($entry['id']) && is_numeric($entry['id'])) { + //Use id column as a fallback for the expected part_id column + $entry['part']['id'] = (int) $entry['id']; + } + + if (isset($entry['part'])) { + $this->processPart($importObject, $entry, $result, $key, self::IMPORT_TYPE_CSV); + } else { + $bomEntry = $this->getOrCreateBomEntry($importObject, $entry['name'] ?? null); + + if (isset($entry['designator'])) { + $bomEntry->setMountnames(trim($entry['designator']) === '' ? '' : trim($entry['designator'])); + } + + $bomEntry->setQuantity((float) $entry['quantity']); + + $result->addBomEntry($bomEntry); + } + } + + return $result; + } + + /** + * Processes an individual part entry in the import data. + * + * This method validates the structure and content of the provided part entry and uses the findings + * to identify corresponding objects in the database. The result is recorded, and violations are + * logged if issues or discrepancies exist in the validation or database matching process. + * + * @param Project|Assembly $importObject The object determining the context of the BOM entry (either a Project or Assembly). + * @param array $entry The array representation of the part entry. + * @param ImporterResult $result The result object used for recording validation violations. + * @param int $key The index of the entry in the data array. + * @param string $importType The type of import being performed. + * + * @return void + */ + private function processPart(Project|Assembly $importObject, array $entry, ImporterResult $result, int $key, string $importType): void + { + $prefix = $importType === self::IMPORT_TYPE_JSON ? 'entry' : 'row'; + + if (!is_array($entry['part'])) { + $result->addViolation($this->buildJsonViolation( + 'validator.bom_importer.json_csv.parameter.array', + $prefix."[$key].part", + $entry['part'] + )); + } + + $partIdValid = isset($entry['part']['id']) && is_int($entry['part']['id']) && $entry['part']['id'] > 0; + $partMpnrValid = isset($entry['part']['mpnr']) && is_string($entry['part']['mpnr']) && trim($entry['part']['mpnr']) !== ''; + $partIpnValid = isset($entry['part']['ipn']) && is_string($entry['part']['ipn']) && trim($entry['part']['ipn']) !== ''; + $partNameValid = isset($entry['part']['name']) && is_string($entry['part']['name']) && trim($entry['part']['name']) !== ''; + + if (!$partIdValid && !$partNameValid && !$partMpnrValid && !$partIpnValid) { + $result->addViolation($this->buildJsonViolation( + 'validator.bom_importer.json_csv.parameter.subproperties', + $prefix."[$key].part", + $entry['part'], + ['%propertyString%' => '"id", "name", "mpnr", or "ipn"'] + )); + } + + $part = $partIdValid ? $this->partRepository->findOneBy(['id' => $entry['part']['id']]) : null; + $part = $part ?? ($partMpnrValid ? $this->partRepository->findOneBy(['manufacturer_product_number' => trim($entry['part']['mpnr'])]) : null); + $part = $part ?? ($partIpnValid ? $this->partRepository->findOneBy(['ipn' => trim($entry['part']['ipn'])]) : null); + $part = $part ?? ($partNameValid ? $this->partRepository->findOneBy(['name' => trim($entry['part']['name'])]) : null); + + if ($part === null) { + $value = sprintf('part.id: %s, part.mpnr: %s, part.ipn: %s, part.name: %s', + isset($entry['part']['id']) ? '' . $entry['part']['id'] . '' : '-', + isset($entry['part']['mpnr']) ? '' . $entry['part']['mpnr'] . '' : '-', + isset($entry['part']['ipn']) ? '' . $entry['part']['ipn'] . '' : '-', + isset($entry['part']['name']) ? '' . $entry['part']['name'] . '' : '-', + ); + + $result->addViolation($this->buildJsonViolation( + 'validator.bom_importer.json_csv.parameter.notFoundFor', + $prefix."[$key].part", + $entry['part'], + ['%value%' => $value] + )); + } + + if ($partNameValid && $part !== null && isset($entry['part']['name']) && $part->getName() !== trim($entry['part']['name'])) { + $result->addViolation($this->buildJsonViolation( + 'validator.bom_importer.json_csv.parameter.noExactMatch', + $prefix."[$key].part.name", + $entry['part']['name'], + [ + '%importValue%' => '' . $entry['part']['name'] . '', + '%foundId%' => $part->getID(), + '%foundValue%' => '' . $part->getName() . '' + ] + )); + } + + if ($partMpnrValid && $part !== null && isset($entry['part']['mpnr']) && $part->getManufacturerProductNumber() !== trim($entry['part']['mpnr'])) { + $result->addViolation($this->buildJsonViolation( + 'validator.bom_importer.json_csv.parameter.noExactMatch', + $prefix."[$key].part.mpnr", + $entry['part']['mpnr'], + [ + '%importValue%' => '' . $entry['part']['mpnr'] . '', + '%foundId%' => $part->getID(), + '%foundValue%' => '' . $part->getManufacturerProductNumber() . '' + ] + )); + } + + if ($partIpnValid && $part !== null && isset($entry['part']['ipn']) && $part->getIpn() !== trim($entry['part']['ipn'])) { + $result->addViolation($this->buildJsonViolation( + 'validator.bom_importer.json_csv.parameter.noExactMatch', + $prefix."[$key].part.ipn", + $entry['part']['ipn'], + [ + '%importValue%' => '' . $entry['part']['ipn'] . '', + '%foundId%' => $part->getID(), + '%foundValue%' => '' . $part->getIpn() . '' + ] + )); + } + + if (isset($entry['part']['description'])) { + if (!is_string($entry['part']['description']) || trim($entry['part']['description']) === '') { + $result->addViolation($this->buildJsonViolation( + 'validator.bom_importer.json_csv.parameter.string.notEmpty', + 'entry[$key].part.description', + $entry['part']['description'] + )); + } + } + + $partDescription = $entry['part']['description'] ?? ''; + + $manufacturerIdValid = false; + $manufacturerNameValid = false; + if (array_key_exists('manufacturer', $entry['part'])) { + if (!is_array($entry['part']['manufacturer'])) { + $result->addViolation($this->buildJsonViolation( + 'validator.bom_importer.json_csv.parameter.array', + 'entry[$key].part.manufacturer', + $entry['part']['manufacturer']) + ); + } + + $manufacturerIdValid = isset($entry['part']['manufacturer']['id']) && is_int($entry['part']['manufacturer']['id']) && $entry['part']['manufacturer']['id'] > 0; + $manufacturerNameValid = isset($entry['part']['manufacturer']['name']) && is_string($entry['part']['manufacturer']['name']) && trim($entry['part']['manufacturer']['name']) !== ''; + + if (!$manufacturerIdValid && !$manufacturerNameValid) { + $result->addViolation($this->buildJsonViolation( + 'validator.bom_importer.json_csv.parameter.manufacturerOrCategoryWithSubProperties', + $prefix."[$key].part.manufacturer", + $entry['part']['manufacturer'], + )); + } + } + + $manufacturer = $manufacturerIdValid ? $this->manufacturerRepository->findOneBy(['id' => $entry['part']['manufacturer']['id']]) : null; + $manufacturer = $manufacturer ?? ($manufacturerNameValid ? $this->manufacturerRepository->findOneBy(['name' => trim($entry['part']['manufacturer']['name'])]) : null); + + if (($manufacturerIdValid || $manufacturerNameValid) && $manufacturer === null) { + $value = sprintf( + 'manufacturer.id: %s, manufacturer.name: %s', + isset($entry['part']['manufacturer']['id']) && $entry['part']['manufacturer']['id'] != null ? '' . $entry['part']['manufacturer']['id'] . '' : '-', + isset($entry['part']['manufacturer']['name']) && $entry['part']['manufacturer']['name'] != null ? '' . $entry['part']['manufacturer']['name'] . '' : '-' + ); + + $result->addViolation($this->buildJsonViolation( + 'validator.bom_importer.json_csv.parameter.notFoundFor', + $prefix."[$key].part.manufacturer", + $entry['part']['manufacturer'], + ['%value%' => $value] + )); + } + + if ($manufacturerNameValid && $manufacturer !== null && isset($entry['part']['manufacturer']['name']) && $manufacturer->getName() !== trim($entry['part']['manufacturer']['name'])) { + $result->addViolation($this->buildJsonViolation( + 'validator.bom_importer.json_csv.parameter.noExactMatch', + $prefix."[$key].part.manufacturer.name", + $entry['part']['manufacturer']['name'], + [ + '%importValue%' => '' . $entry['part']['manufacturer']['name'] . '', + '%foundId%' => $manufacturer->getID(), + '%foundValue%' => '' . $manufacturer->getName() . '' + ] + )); + } + + $categoryIdValid = false; + $categoryNameValid = false; + if (array_key_exists('category', $entry['part'])) { + if (!is_array($entry['part']['category'])) { + $result->addViolation($this->buildJsonViolation( + 'validator.bom_importer.json_csv.parameter.array', + 'entry[$key].part.category', + $entry['part']['category']) + ); + } + + $categoryIdValid = isset($entry['part']['category']['id']) && is_int($entry['part']['category']['id']) && $entry['part']['category']['id'] > 0; + $categoryNameValid = isset($entry['part']['category']['name']) && is_string($entry['part']['category']['name']) && trim($entry['part']['category']['name']) !== ''; + + if (!$categoryIdValid && !$categoryNameValid) { + $result->addViolation($this->buildJsonViolation( + 'validator.bom_importer.json_csv.parameter.manufacturerOrCategoryWithSubProperties', + $prefix."[$key].part.category", + $entry['part']['category'] + )); + } + } + + $category = $categoryIdValid ? $this->categoryRepository->findOneBy(['id' => $entry['part']['category']['id']]) : null; + $category = $category ?? ($categoryNameValid ? $this->categoryRepository->findOneBy(['name' => trim($entry['part']['category']['name'])]) : null); + + if (($categoryIdValid || $categoryNameValid)) { + $value = sprintf( + 'category.id: %s, category.name: %s', + isset($entry['part']['category']['id']) && $entry['part']['category']['id'] != null ? '' . $entry['part']['category']['id'] . '' : '-', + isset($entry['part']['category']['name']) && $entry['part']['category']['name'] != null ? '' . $entry['part']['category']['name'] . '' : '-' + ); + + $result->addViolation($this->buildJsonViolation( + 'validator.bom_importer.json_csv.parameter.notFoundFor', + $prefix."[$key].part.category", + $entry['part']['category'], + ['%value%' => $value] + )); + } + + if ($categoryNameValid && $category !== null && isset($entry['part']['category']['name']) && $category->getName() !== trim($entry['part']['category']['name'])) { + $result->addViolation($this->buildJsonViolation( + 'validator.bom_importer.json_csv.parameter.noExactMatch', + $prefix."[$key].part.category.name", + $entry['part']['category']['name'], + [ + '%importValue%' => '' . $entry['part']['category']['name'] . '', + '%foundId%' => $category->getID(), + '%foundValue%' => '' . $category->getName() . '' + ] + )); + } + + if ($result->getViolations()->count() > 0) { + return; + } + + if ($partDescription !== '') { + //When updating the associated parts to a assembly, take over the description of the part. + $part->setDescription($partDescription); + } + + /** @var Manufacturer|null $manufacturer */ + if ($manufacturer !== null && $manufacturer->getID() !== $part->getManufacturer()->getID()) { + //When updating the associated parts, take over to a assembly of the manufacturer of the part. + $part->setManufacturer($manufacturer); + } + + /** @var Category|null $category */ + if ($category !== null && $category->getID() !== $part->getCategory()->getID()) { + //When updating the associated parts to a assembly, take over the category of the part. + $part->setCategory($category); + } + + if ($importObject instanceof Assembly) { + $bomEntry = $this->assemblyBomEntryRepository->findOneBy(['assembly' => $importObject, 'part' => $part]); + + if ($bomEntry === null) { + if (isset($entry['name']) && $entry['name'] !== '') { + $bomEntry = $this->assemblyBomEntryRepository->findOneBy(['assembly' => $importObject, 'name' => $entry['name']]); + } + + if ($bomEntry === null) { + $bomEntry = new AssemblyBOMEntry(); + } + } + } else { + $bomEntry = $this->projectBomEntryRepository->findOneBy(['project' => $importObject, 'part' => $part]); + + if ($bomEntry === null) { + if (isset($entry['name']) && $entry['name'] !== '') { + $bomEntry = $this->projectBomEntryRepository->findOneBy(['project' => $importObject, 'name' => $entry['name']]); + } + + if ($bomEntry === null) { + $bomEntry = new ProjectBOMEntry(); + } + } + } + + $bomEntry->setQuantity((float) $entry['quantity']); + + if (isset($entry['name'])) { + $givenName = trim($entry['name']) === '' ? null : trim ($entry['name']); + + if ($givenName !== null && $part !== null && $part->getName() !== $givenName) { + //Apply different names for parts list entry + $bomEntry->setName(trim($entry['name']) === '' ? null : trim ($entry['name'])); + } + } else { + $bomEntry->setName(null); + } + + if (isset($entry['designator'])) { + if ($bomEntry instanceof ProjectBOMEntry) { + $bomEntry->setMountnames(trim($entry['designator']) === '' ? '' : trim($entry['designator'])); + } elseif ($bomEntry instanceof AssemblyBOMEntry) { + $bomEntry->setDesignator(trim($entry['designator']) === '' ? '' : trim($entry['designator'])); + } + } + + $bomEntry->setPart($part); + + $result->addBomEntry($bomEntry); + } + + private function removeEmptyProperties(array $data): array + { + foreach ($data as $key => &$value) { + //Recursive check when the value is an array + if (is_array($value)) { + $value = $this->removeEmptyProperties($value); + + //Remove the array when it is empty after cleaning + if (empty($value)) { + unset($data[$key]); + } + } elseif ($value === null || $value === '') { + //Remove values that are explicitly zero or empty + unset($data[$key]); + } + } + + return $data; + } + + /** + * Retrieves an existing BOM (Bill of Materials) entry by name or creates a new one if not found. + * + * Depending on whether the provided import object is a Project or Assembly, this method attempts to locate + * a corresponding BOM entry in the appropriate repository. If no entry is located, a new BOM entry object + * is instantiated according to the type of the import object. + * + * @param Project|Assembly $importObject The object determining the context of the BOM entry (either a Project or Assembly). + * @param string|null $name The name of the BOM entry to search for or assign to a new entry. + * + * @return ProjectBOMEntry|AssemblyBOMEntry An existing or newly created BOM entry. + */ + private function getOrCreateBomEntry(Project|Assembly $importObject, ?string $name): ProjectBOMEntry|AssemblyBOMEntry + { + $bomEntry = null; + + //Check whether there is a name + if (!empty($name)) { + if ($importObject instanceof Project) { + $bomEntry = $this->projectBomEntryRepository->findOneBy(['name' => $name]); + } else { + $bomEntry = $this->assemblyBomEntryRepository->findOneBy(['name' => $name]); + } + } + + //If no bom entry was found, a new object create + if ($bomEntry === null) { + if ($importObject instanceof Project) { + $bomEntry = new ProjectBOMEntry(); + } else { + $bomEntry = new AssemblyBOMEntry(); + } + } + + $bomEntry->setName($name); + + return $bomEntry; + } + /** * This function uses the order of the fields in the CSV files to make them locale independent. * @param array $entry @@ -243,13 +957,28 @@ private function normalizeColumnNames(array $entry): array } //@phpstan-ignore-next-line We want to keep this check just to be safe when something changes - $new_index = self::MAP_KICAD_PCB_FIELDS[$index] ?? throw new \UnexpectedValueException('Invalid field index!'); + $new_index = self::MAP_KICAD_PCB_FIELDS[$index] ?? throw new UnexpectedValueException('Invalid field index!'); $out[$new_index] = $field; } return $out; } + + /** + * Builds a JSON-based constraint violation. + * + * This method creates a `ConstraintViolation` object that represents a validation error. + * The violation includes a message, property path, invalid value, and other contextual information. + * Translations for the violation message can be applied through the translator service. + * + * @param string $message The translation key for the validation message. + * @param string $propertyPath The property path where the violation occurred. + * @param mixed|null $invalidValue The value that caused the violation (optional). + * @param array $parameters Additional parameters for message placeholders (default is an empty array). + * + * @return ConstraintViolation The created constraint violation object. + */ /** * Parse KiCad schematic BOM with flexible field mapping */ @@ -727,4 +1456,30 @@ public function detectFields(string $data, ?string $delimiter = null): array return array_values($headers); } + + /** + * Builds a JSON-based constraint violation. + * + * This method creates a `ConstraintViolation` object that represents a validation error. + * The violation includes a message, property path, invalid value, and other contextual information. + * Translations for the violation message can be applied through the translator service. + * + * @param string $message The translation key for the validation message. + * @param string $propertyPath The property path where the violation occurred. + * @param mixed|null $invalidValue The value that caused the violation (optional). + * @param array $parameters Additional parameters for message placeholders (default is an empty array). + * + * @return ConstraintViolation The created constraint violation object. + */ + private function buildJsonViolation(string $message, string $propertyPath, mixed $invalidValue = null, array $parameters = []): ConstraintViolation + { + return new ConstraintViolation( + message: $this->translator->trans($message, $parameters, 'validators'), + messageTemplate: $message, + parameters: $parameters, + root: $this->jsonRoot, + propertyPath: $propertyPath, + invalidValue: $invalidValue + ); + } } diff --git a/src/Services/ImportExportSystem/EntityExporter.php b/src/Services/ImportExportSystem/EntityExporter.php index 70feb8e67..028a537e7 100644 --- a/src/Services/ImportExportSystem/EntityExporter.php +++ b/src/Services/ImportExportSystem/EntityExporter.php @@ -22,8 +22,22 @@ namespace App\Services\ImportExportSystem; +use App\Entity\AssemblySystem\Assembly; +use App\Entity\AssemblySystem\AssemblyBOMEntry; +use App\Entity\Attachments\AttachmentType; use App\Entity\Base\AbstractNamedDBElement; use App\Entity\Base\AbstractStructuralDBElement; +use App\Entity\LabelSystem\LabelProfile; +use App\Entity\Parts\Category; +use App\Entity\Parts\Footprint; +use App\Entity\Parts\Manufacturer; +use App\Entity\Parts\MeasurementUnit; +use App\Entity\Parts\StorageLocation; +use App\Entity\Parts\Supplier; +use App\Entity\PriceInformations\Currency; +use App\Entity\ProjectSystem\Project; +use App\Entity\ProjectSystem\ProjectBOMEntry; +use App\Helpers\Assemblies\AssemblyPartAggregator; use App\Helpers\FilenameSanatizer; use App\Serializer\APIPlatform\SkippableItemNormalizer; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -48,8 +62,10 @@ */ class EntityExporter { - public function __construct(protected SerializerInterface $serializer) - { + public function __construct( + protected SerializerInterface $serializer, + protected AssemblyPartAggregator $partAggregator, private readonly AssemblyPartAggregator $assemblyPartAggregator, + ) { } protected function configureOptions(OptionsResolver $resolver): void @@ -65,6 +81,10 @@ protected function configureOptions(OptionsResolver $resolver): void $resolver->setDefault('include_children', false); $resolver->setAllowedTypes('include_children', 'bool'); + + $resolver->setDefault('readableSelect', null); + $resolver->setAllowedValues('readableSelect', [null, 'readable', 'readable_bom']); + } /** @@ -222,15 +242,67 @@ public function exportEntityFromRequest(AbstractNamedDBElement|array $entities, $entities = [$entities]; } - //Do the serialization with the given options - $serialized_data = $this->exportEntities($entities, $options); + if ($request->get('readableSelect', false) === 'readable') { + // Map entity classes to export functions + $entityExportMap = [ + AttachmentType::class => fn($entities) => $this->exportReadable($entities, AttachmentType::class), + Category::class => fn($entities) => $this->exportReadable($entities, Category::class), + Project::class => fn($entities) => $this->exportReadable($entities, Project::class), + Assembly::class => fn($entities) => $this->exportReadable($entities, Assembly::class), + Supplier::class => fn($entities) => $this->exportReadable($entities, Supplier::class), + Manufacturer::class => fn($entities) => $this->exportReadable($entities, Manufacturer::class), + StorageLocation::class => fn($entities) => $this->exportReadable($entities, StorageLocation::class), + Footprint::class => fn($entities) => $this->exportReadable($entities, Footprint::class), + Currency::class => fn($entities) => $this->exportReadable($entities, Currency::class), + MeasurementUnit::class => fn($entities) => $this->exportReadable($entities, MeasurementUnit::class), + LabelProfile::class => fn($entities) => $this->exportReadable($entities, LabelProfile::class, false), + ]; + + // Determine the type of the entity + $type = null; + foreach ($entities as $entity) { + $entityClass = get_class($entity); + if (isset($entityExportMap[$entityClass])) { + $type = $entityClass; + break; + } + } + + // Generate the response + $response = isset($entityExportMap[$type]) + ? new Response($entityExportMap[$type]($entities)) + : new Response(''); + + $options['format'] = 'csv'; + $options['level'] = 'readable'; + } elseif ($request->get('readableSelect', false) === 'readable_bom') { + $hierarchies = []; + + foreach ($entities as $entity) { + if (!$entity instanceof Assembly) { + throw new InvalidArgumentException('Only assemblies can be exported in readable BOM format'); + } + + $hierarchies[] = $this->assemblyPartAggregator->processAssemblyHierarchyForPdf($entity, 0, 1, 1); + } + + $pdfContent = $this->assemblyPartAggregator->exportReadableHierarchyForPdf($hierarchies); + + $response = new Response($pdfContent); + + $options['format'] = 'pdf'; + $options['level'] = 'readable_bom'; + } else { + //Do the serialization with the given options + $serialized_data = $this->exportEntities($entities, $options); - $response = new Response($serialized_data); + $response = new Response($serialized_data); - //Resolve the format - $optionsResolver = new OptionsResolver(); - $this->configureOptions($optionsResolver); - $options = $optionsResolver->resolve($options); + //Resolve the format + $optionsResolver = new OptionsResolver(); + $this->configureOptions($optionsResolver); + $options = $optionsResolver->resolve($options); + } //Determine the content type for the response @@ -241,6 +313,7 @@ public function exportEntityFromRequest(AbstractNamedDBElement|array $entities, 'json' => 'application/json', 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'xls' => 'application/vnd.ms-excel', + 'pdf' => 'application/pdf', default => 'text/plain', }; $response->headers->set('Content-Type', $content_type); @@ -277,4 +350,311 @@ public function exportEntityFromRequest(AbstractNamedDBElement|array $entities, return $response; } + + /** + * Exports data for multiple entity types in a readable CSV format. + * + * @param array $entities The entities to export. + * @param string $type The type of entities ('category', 'project', 'assembly', 'attachmentType', 'supplier'). + * @return string The generated CSV content as a string. + */ + public function exportReadable(array $entities, string $type, bool $isHierarchical = true): string + { + //Define headers and entity-specific processing logic + $defaultProcessEntity = fn($entity, $depth) => [ + 'Id' => $entity->getId(), + 'ParentId' => $entity->getParent()?->getId() ?? '', + 'NameHierarchical' => str_repeat('--', $depth) . ' ' . $entity->getName(), + 'Name' => $entity->getName(), + 'FullName' => $this->getFullName($entity), + ]; + + $config = [ + AttachmentType::class => [ + 'header' => ['Id', 'ParentId', 'NameHierarchical', 'Name', 'FullName'], + 'processEntity' => $defaultProcessEntity, + ], + Category::class => [ + 'header' => ['Id', 'ParentId', 'NameHierarchical', 'Name', 'FullName'], + 'processEntity' => $defaultProcessEntity, + ], + Project::class => [ + 'header' => [ + 'Id', 'ParentId', 'Type', 'ProjectNameHierarchical', 'ProjectName', 'ProjectFullName', + + //BOM relevant attributes + 'Quantity', 'PartId', 'PartName', 'Ipn', 'Manufacturer', 'Mpn', 'Name', 'Mountnames', + 'Description', + ], + 'processEntity' => fn($entity, $depth) => [ + 'Id' => $entity->getId(), + 'ParentId' => $entity->getParent()?->getId() ?? '', + 'Type' => 'project', + 'ProjectNameHierarchical' => str_repeat('--', $depth) . ' ' . $entity->getName(), + 'ProjectName' => $entity->getName(), + 'ProjectFullName' => $this->getFullName($entity), + + //BOM relevant attributes + 'Quantity' => '-', + 'PartId' => '-', + 'PartName' => '-', + 'Ipn' => '-', + 'Manufacturer' => '-', + 'Mpn' => '-', + 'Name' => '-', + 'Mountnames' => '-', + 'Description' => '-', + ], + 'processBomEntries' => fn($entity, $depth) => array_map(fn(ProjectBOMEntry $bomEntry) => [ + 'Id' => $entity->getId(), + 'ParentId' => '', + 'Type' => 'project_bom_entry', + 'ProjectNameHierarchical' => str_repeat('--', $depth) . '> ' . $entity->getName(), + 'ProjectName' => $entity->getName(), + 'ProjectFullName' => $this->getFullName($entity), + + //BOM relevant attributes + 'Quantity' => $bomEntry->getQuantity(), + 'PartId' => $bomEntry->getPart()?->getId() ?? '', + 'PartName' => $bomEntry->getPart()?->getName() ?? '', + 'Ipn' => $bomEntry->getPart()?->getIpn() ?? '', + 'Manufacturer' => $bomEntry->getPart()?->getManufacturer()?->getName() ?? '', + 'Mpn' => $bomEntry->getPart()?->getManufacturerProductNumber() ?? '', + 'Name' => $bomEntry->getPart()?->getName() ?? '', + 'Mountnames' => $bomEntry->getMountnames(), + 'Description' => $bomEntry->getPart()?->getDescription() ?? '', + ], $entity->getBomEntries()->toArray()), + ], + Assembly::class => [ + 'header' => [ + 'Id', 'ParentId', 'Type', 'AssemblyIpn', 'AssemblyNameHierarchical', 'AssemblyName', + 'AssemblyFullName', + + //BOM relevant attributes + 'Quantity', 'PartId', 'PartName', 'Ipn', 'Manufacturer', 'Mpn', 'Name', 'Designator', + 'Description', 'ReferencedAssemblyId', 'ReferencedAssemblyIpn', + 'ReferencedAssemblyFullName', + ], + 'processEntity' => fn($entity, $depth) => [ + 'Id' => $entity->getId(), + 'ParentId' => $entity->getParent()?->getId() ?? '', + 'Type' => 'assembly', + 'AssemblyIpn' => $entity->getIpn(), + 'AssemblyNameHierarchical' => str_repeat('--', $depth) . ' ' . $entity->getName(), + 'AssemblyName' => $entity->getName(), + 'AssemblyFullName' => $this->getFullName($entity), + + //BOM relevant attributes + 'Quantity' => '-', + 'PartId' => '-', + 'PartName' => '-', + 'Ipn' => '-', + 'Manufacturer' => '-', + 'Mpn' => '-', + 'Name' => '-', + 'Designator' => '-', + 'Description' => '-', + 'ReferencedAssemblyId' => '-', + 'ReferencedAssemblyIpn' => '-', + 'ReferencedAssemblyFullName' => '-', + ], + 'processBomEntries' => fn($entity, $depth) => $this->processBomEntriesWithAggregatedParts($entity, $depth), + ], + Supplier::class => [ + 'header' => ['Id', 'ParentId', 'NameHierarchical', 'Name', 'FullName'], + 'processEntity' => $defaultProcessEntity, + ], + Manufacturer::class => [ + 'header' => ['Id', 'ParentId', 'NameHierarchical', 'Name', 'FullName'], + 'processEntity' => $defaultProcessEntity, + ], + StorageLocation::class => [ + 'header' => ['Id', 'ParentId', 'NameHierarchical', 'Name', 'FullName'], + 'processEntity' => $defaultProcessEntity, + ], + Footprint::class => [ + 'header' => ['Id', 'ParentId', 'NameHierarchical', 'Name', 'FullName'], + 'processEntity' => $defaultProcessEntity, + ], + Currency::class => [ + 'header' => ['Id', 'ParentId', 'NameHierarchical', 'Name', 'FullName'], + 'processEntity' => $defaultProcessEntity, + ], + MeasurementUnit::class => [ + 'header' => ['Id', 'ParentId', 'NameHierarchical', 'Name', 'FullName'], + 'processEntity' => $defaultProcessEntity, + ], + LabelProfile::class => [ + 'header' => ['Id', 'SupportedElement', 'Name'], + 'processEntity' => fn(LabelProfile $entity, $depth) => [ + 'Id' => $entity->getId(), + 'SupportedElement' => $entity->getOptions()->getSupportedElement()->name, + 'Name' => $entity->getName(), + ], + ], + ]; + + //Get configuration for the entity type + $entityConfig = $config[$type] ?? null; + + if (!$entityConfig) { + return ''; + } + + //Initialize CSV data with the header + $csvData = []; + $csvData[] = $entityConfig['header']; + + $relevantEntities = $entities; + + if ($isHierarchical) { + //Filter root entities (those without parents) + $relevantEntities = array_filter($entities, fn($entity) => $entity->getParent() === null); + + if (count($relevantEntities) === 0 && count($entities) > 0) { + //If no root entities are found, then we need to add all entities + + $relevantEntities = $entities; + } + } + + //Sort root entities alphabetically by `name` + usort($relevantEntities, fn($a, $b) => strnatcasecmp($a->getName(), $b->getName())); + + //Recursive function to process an entity and its children + $processEntity = function ($entity, &$csvData, $depth = 0) use (&$processEntity, $entityConfig, $isHierarchical) { + //Add main entity data to CSV + $csvData[] = $entityConfig['processEntity']($entity, $depth); + + //Process BOM entries if applicable + if (isset($entityConfig['processBomEntries'])) { + $bomRows = $entityConfig['processBomEntries']($entity, $depth); + foreach ($bomRows as $bomRow) { + $csvData[] = $bomRow; + } + } + + if ($isHierarchical) { + //Retrieve children, sort alphabetically, then process them + $children = $entity->getChildren()->toArray(); + usort($children, fn($a, $b) => strnatcasecmp($a->getName(), $b->getName())); + foreach ($children as $childEntity) { + $processEntity($childEntity, $csvData, $depth + 1); + } + } + }; + + //Start processing with root entities + foreach ($relevantEntities as $rootEntity) { + $processEntity($rootEntity, $csvData); + } + + //Generate CSV string + $output = ''; + foreach ($csvData as $line) { + $output .= implode(';', $line) . "\n"; // Use a semicolon as the delimiter + } + + return $output; + } + + /** + * Process BOM entries and include aggregated parts as "complete_part_list". + * + * @param Assembly $assembly The assembly being processed. + * @param int $depth The current depth in the hierarchy. + * @return array Processed BOM entries and aggregated parts rows. + */ + private function processBomEntriesWithAggregatedParts(Assembly $assembly, int $depth): array + { + $rows = []; + + /** @var AssemblyBOMEntry $bomEntry */ + foreach ($assembly->getBomEntries() as $bomEntry) { + // Add the BOM entry itself + $rows[] = [ + 'Id' => $assembly->getId(), + 'ParentId' => '', + 'Type' => 'assembly_bom_entry', + 'AssemblyIpn' => $assembly->getIpn(), + 'AssemblyNameHierarchical' => str_repeat('--', $depth) . '> ' . $assembly->getName(), + 'AssemblyName' => $assembly->getName(), + 'AssemblyFullName' => $this->getFullName($assembly), + + //BOM relevant attributes + 'Quantity' => $bomEntry->getQuantity(), + 'PartId' => $bomEntry->getPart()?->getId() ?? '-', + 'PartName' => $bomEntry->getPart()?->getName() ?? '-', + 'Ipn' => $bomEntry->getPart()?->getIpn() ?? '-', + 'Manufacturer' => $bomEntry->getPart()?->getManufacturer()?->getName() ?? '-', + 'Mpn' => $bomEntry->getPart()?->getManufacturerProductNumber() ?? '-', + 'Name' => $bomEntry->getName() ?? '-', + 'Designator' => $bomEntry->getDesignator(), + 'Description' => $bomEntry->getPart()?->getDescription() ?? '-', + 'ReferencedAssemblyId' => $bomEntry->getReferencedAssembly()?->getId() ?? '-', + 'ReferencedAssemblyIpn' => $bomEntry->getReferencedAssembly()?->getIpn() ?? '-', + 'ReferencedAssemblyFullName' => $this->getFullName($bomEntry->getReferencedAssembly() ?? null), + ]; + + // If a referenced assembly exists, add aggregated parts + if ($bomEntry->getReferencedAssembly() instanceof Assembly) { + $referencedAssembly = $bomEntry->getReferencedAssembly(); + + // Get aggregated parts for the referenced assembly + $aggregatedParts = $this->assemblyPartAggregator->getAggregatedParts($referencedAssembly, $bomEntry->getQuantity());; + + foreach ($aggregatedParts as $partData) { + $partAssembly = $partData['assembly'] ?? null; + + $rows[] = [ + 'Id' => $assembly->getId(), + 'ParentId' => '', + 'Type' => 'subassembly_part_list', + 'AssemblyIpn' => $partAssembly ? $partAssembly->getIpn() : '', + 'AssemblyNameHierarchical' => '', + 'AssemblyName' => $partAssembly ? $partAssembly->getName() : '', + 'AssemblyFullName' => $this->getFullName($partAssembly), + + //BOM relevant attributes + 'Quantity' => $partData['quantity'], + 'PartId' => $partData['part']?->getId(), + 'PartName' => $partData['part']?->getName(), + 'Ipn' => $partData['part']?->getIpn(), + 'Manufacturer' => $partData['part']?->getManufacturer()?->getName(), + 'Mpn' => $partData['part']?->getManufacturerProductNumber(), + 'Name' => $partData['name'] ?? '', + 'Designator' => $partData['designator'], + 'Description' => $partData['part']?->getDescription(), + 'ReferencedAssemblyId' => '-', + 'ReferencedAssemblyIpn' => '-', + 'ReferencedAssemblyFullName' => '-', + ]; + } + } + } + + return $rows; + } + + /** + * Constructs the full hierarchical name of an object by traversing + * through its parent objects and concatenating their names using + * a specified separator. + * + * @param AttachmentType|Category|Project|Assembly|Supplier|Manufacturer|StorageLocation|Footprint|Currency|MeasurementUnit|LabelProfile|null $object The object whose full name is to be constructed. If null, the result will be an empty string. + * @param string $separator The string used to separate the names of the objects in the full hierarchy. + * + * @return string The full hierarchical name constructed by concatenating the names of the object and its parents. + */ + private function getFullName(AttachmentType|Category|Project|Assembly|Supplier|Manufacturer|StorageLocation|Footprint|Currency|MeasurementUnit|LabelProfile|null $object, string $separator = '->'): string + { + $fullNameParts = []; + + while ($object !== null) { + array_unshift($fullNameParts, $object->getName()); + $object = $object->getParent(); + } + + return implode($separator, $fullNameParts); + } } diff --git a/src/Services/ImportExportSystem/ImporterResult.php b/src/Services/ImportExportSystem/ImporterResult.php new file mode 100644 index 000000000..4e289d133 --- /dev/null +++ b/src/Services/ImportExportSystem/ImporterResult.php @@ -0,0 +1,60 @@ +bomEntries = $bomEntries; + $this->violations = new ConstraintViolationList(); + } + + /** + * Fügt einen neuen BOM-Eintrag hinzu. + */ + public function addBomEntry(object $bomEntry): void + { + $this->bomEntries[] = $bomEntry; + } + + /** + * Gibt alle BOM-Einträge zurück. + */ + public function getBomEntries(): array + { + return $this->bomEntries; + } + + /** + * Gibt die Liste der Violation zurück. + */ + public function getViolations(): ConstraintViolationList + { + return $this->violations; + } + + /** + * Fügt eine neue `ConstraintViolation` zur Liste hinzu. + */ + public function addViolation(ConstraintViolation $violation): void + { + $this->violations->add($violation); + } + + /** + * Prüft, ob die Liste der Violationen leer ist. + */ + public function hasViolations(): bool + { + return count($this->violations) > 0; + } +} \ No newline at end of file diff --git a/src/Services/Trees/ToolsTreeBuilder.php b/src/Services/Trees/ToolsTreeBuilder.php index 036797f61..f16431b31 100644 --- a/src/Services/Trees/ToolsTreeBuilder.php +++ b/src/Services/Trees/ToolsTreeBuilder.php @@ -22,6 +22,7 @@ namespace App\Services\Trees; +use App\Entity\AssemblySystem\Assembly; use App\Entity\Attachments\AttachmentType; use App\Entity\LabelSystem\LabelProfile; use App\Entity\Parts\Category; @@ -175,6 +176,12 @@ protected function getEditNodes(): array $this->urlGenerator->generate('project_new') ))->setIcon('fa-fw fa-treeview fa-solid fa-archive'); } + if ($this->security->isGranted('read', new Assembly())) { + $nodes[] = (new TreeViewNode( + $this->translator->trans('tree.tools.edit.assemblies'), + $this->urlGenerator->generate('assembly_new') + ))->setIcon('fa-fw fa-treeview fa-solid fa-list'); + } if ($this->security->isGranted('read', new Supplier())) { $nodes[] = (new TreeViewNode( $this->translator->trans('tree.tools.edit.suppliers'), diff --git a/src/Services/Trees/TreeViewGenerator.php b/src/Services/Trees/TreeViewGenerator.php index 73ffa5baf..3a0979028 100644 --- a/src/Services/Trees/TreeViewGenerator.php +++ b/src/Services/Trees/TreeViewGenerator.php @@ -22,6 +22,7 @@ namespace App\Services\Trees; +use App\Entity\AssemblySystem\Assembly; use App\Entity\Base\AbstractDBElement; use App\Entity\Base\AbstractNamedDBElement; use App\Entity\Base\AbstractStructuralDBElement; @@ -154,6 +155,10 @@ private function getTreeViewUncached( $href_type = 'list_parts'; } + if ($mode === 'assemblies') { + $href_type = 'list_parts'; + } + $generic = $this->getGenericTree($class, $parent); $treeIterator = new TreeViewNodeIterator($generic); $recursiveIterator = new RecursiveIteratorIterator($treeIterator, RecursiveIteratorIterator::SELF_FIRST); @@ -183,6 +188,15 @@ private function getTreeViewUncached( $root_node->setExpanded($this->rootNodeExpandedByDefault); $root_node->setIcon($this->entityClassToRootNodeIcon($class)); + $generic = [$root_node]; + } elseif ($mode === 'assemblies' && $this->rootNodeEnabled) { + //We show the root node as a link to the list of all assemblies + $show_all_parts_url = $this->router->generate('assemblies_list'); + + $root_node = new TreeViewNode($this->entityClassToRootNodeString($class), $show_all_parts_url, $generic); + $root_node->setExpanded($this->rootNodeExpandedByDefault); + $root_node->setIcon($this->entityClassToRootNodeIcon($class)); + $generic = [$root_node]; } @@ -219,6 +233,7 @@ protected function entityClassToRootNodeString(string $class): string Manufacturer::class => $this->translator->trans('manufacturer.labelp'), Supplier::class => $this->translator->trans('supplier.labelp'), Project::class => $this->translator->trans('project.labelp'), + Assembly::class => $this->translator->trans('assembly.labelp'), default => $this->translator->trans('tree.root_node.text'), }; } @@ -233,6 +248,7 @@ protected function entityClassToRootNodeIcon(string $class): ?string Manufacturer::class => $icon.'fa-industry', Supplier::class => $icon.'fa-truck', Project::class => $icon.'fa-archive', + Assembly::class => $icon.'fa-list', default => null, }; } diff --git a/src/Services/UserSystem/PermissionPresetsHelper.php b/src/Services/UserSystem/PermissionPresetsHelper.php index 554da8b32..295877a67 100644 --- a/src/Services/UserSystem/PermissionPresetsHelper.php +++ b/src/Services/UserSystem/PermissionPresetsHelper.php @@ -104,6 +104,7 @@ private function admin(HasPermissionsInterface $perm_holder): void $this->permissionResolver->setAllOperationsOfPermission($perm_holder, 'measurement_units', PermissionData::ALLOW); $this->permissionResolver->setAllOperationsOfPermission($perm_holder, 'suppliers', PermissionData::ALLOW); $this->permissionResolver->setAllOperationsOfPermission($perm_holder, 'projects', PermissionData::ALLOW); + $this->permissionResolver->setAllOperationsOfPermission($perm_holder, 'assemblies', PermissionData::ALLOW); //Allow to change system settings $this->permissionResolver->setPermission($perm_holder, 'config', 'change_system_settings', PermissionData::ALLOW); @@ -133,6 +134,7 @@ private function editor(HasPermissionsInterface $permHolder): HasPermissionsInte $this->permissionResolver->setAllOperationsOfPermissionExcept($permHolder, 'measurement_units', PermissionData::ALLOW, ['import']); $this->permissionResolver->setAllOperationsOfPermissionExcept($permHolder, 'suppliers', PermissionData::ALLOW, ['import']); $this->permissionResolver->setAllOperationsOfPermissionExcept($permHolder, 'projects', PermissionData::ALLOW, ['import']); + $this->permissionResolver->setAllOperationsOfPermissionExcept($permHolder, 'assemblies', PermissionData::ALLOW, ['import']); //Attachments permissions $this->permissionResolver->setPermission($permHolder, 'attachments', 'show_private', PermissionData::ALLOW); @@ -180,6 +182,9 @@ private function readOnly(HasPermissionsInterface $perm_holder): HasPermissionsI //Set projects permissions $this->permissionResolver->setPermission($perm_holder, 'projects', 'read', PermissionData::ALLOW); + //Set assemblies permissions + $this->permissionResolver->setPermission($perm_holder, 'assemblies', 'read', PermissionData::ALLOW); + return $perm_holder; } diff --git a/src/Settings/BehaviorSettings/AssemblyBomTableColumns.php b/src/Settings/BehaviorSettings/AssemblyBomTableColumns.php new file mode 100644 index 000000000..2833a3dfc --- /dev/null +++ b/src/Settings/BehaviorSettings/AssemblyBomTableColumns.php @@ -0,0 +1,54 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Settings\BehaviorSettings; + +use Symfony\Contracts\Translation\TranslatableInterface; +use Symfony\Contracts\Translation\TranslatorInterface; + +enum AssemblyBomTableColumns : string implements TranslatableInterface +{ + case NAME = "name"; + case ID = "id"; + case QUANTITY = "quantity"; + case IPN = "ipn"; + case DESCRIPTION = "description"; + case CATEGORY = "category"; + case MANUFACTURER = "manufacturer"; + case DESIGNATOR = "designator"; + case MOUNTNAMES = "mountnames"; + case STORAGE_LOCATION = "storage_location"; + case AMOUNT = "amount"; + case ADDED_DATE = "addedDate"; + case LAST_MODIFIED = "lastModified"; + case EDIT = "edit"; + + public function trans(TranslatorInterface $translator, ?string $locale = null): string + { + $key = match($this) { + default => 'assembly.bom.table.' . $this->value, + }; + + return $translator->trans($key, locale: $locale); + } +} diff --git a/src/Settings/BehaviorSettings/AssemblyTableColumns.php b/src/Settings/BehaviorSettings/AssemblyTableColumns.php new file mode 100644 index 000000000..02c315b49 --- /dev/null +++ b/src/Settings/BehaviorSettings/AssemblyTableColumns.php @@ -0,0 +1,49 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Settings\BehaviorSettings; + +use Symfony\Contracts\Translation\TranslatableInterface; +use Symfony\Contracts\Translation\TranslatorInterface; + +enum AssemblyTableColumns : string implements TranslatableInterface +{ + + case NAME = "name"; + case ID = "id"; + case IPN = "ipn"; + case DESCRIPTION = "description"; + case REFERENCED_ASSEMBLIES = "referencedAssemblies"; + case ADDED_DATE = "addedDate"; + case LAST_MODIFIED = "lastModified"; + case EDIT = "edit"; + + public function trans(TranslatorInterface $translator, ?string $locale = null): string + { + $key = match($this) { + default => 'assembly.table.' . $this->value, + }; + + return $translator->trans($key, locale: $locale); + } +} diff --git a/src/Settings/BehaviorSettings/TableSettings.php b/src/Settings/BehaviorSettings/TableSettings.php index b69648769..c49b25f48 100644 --- a/src/Settings/BehaviorSettings/TableSettings.php +++ b/src/Settings/BehaviorSettings/TableSettings.php @@ -70,6 +70,37 @@ class TableSettings PartTableColumns::CATEGORY, PartTableColumns::FOOTPRINT, PartTableColumns::MANUFACTURER, PartTableColumns::LOCATION, PartTableColumns::AMOUNT]; + /** @var AssemblyTableColumns[] */ + #[SettingsParameter(ArrayType::class, + label: new TM("settings.behavior.table.assemblies_default_columns"), + description: new TM("settings.behavior.table.assemblies_default_columns.help"), + options: ['type' => EnumType::class, 'options' => ['class' => AssemblyTableColumns::class]], + formType: \Symfony\Component\Form\Extension\Core\Type\EnumType::class, + formOptions: ['class' => AssemblyTableColumns::class, 'multiple' => true, 'ordered' => true], + envVar: "TABLE_ASSEMBLIES_DEFAULT_COLUMNS", envVarMode: EnvVarMode::OVERWRITE, envVarMapper: [self::class, 'mapAssembliesDefaultColumnsEnv'] + )] + #[Assert\NotBlank()] + #[Assert\Unique()] + #[Assert\All([new Assert\Type(AssemblyTableColumns::class)])] + public array $assembliesDefaultColumns = [AssemblyTableColumns::ID, AssemblyTableColumns::IPN, AssemblyTableColumns::NAME, + AssemblyTableColumns::DESCRIPTION, AssemblyTableColumns::REFERENCED_ASSEMBLIES, AssemblyTableColumns::EDIT]; + + /** @var AssemblyBomTableColumns[] */ + #[SettingsParameter(ArrayType::class, + label: new TM("settings.behavior.table.assemblies_bom_default_columns"), + description: new TM("settings.behavior.table.assemblies_bom_default_columns.help"), + options: ['type' => EnumType::class, 'options' => ['class' => AssemblyBomTableColumns::class]], + formType: \Symfony\Component\Form\Extension\Core\Type\EnumType::class, + formOptions: ['class' => AssemblyBomTableColumns::class, 'multiple' => true, 'ordered' => true], + envVar: "TABLE_ASSEMBLIES_BOM_DEFAULT_COLUMNS", envVarMode: EnvVarMode::OVERWRITE, envVarMapper: [self::class, 'mapAssemblyBomsDefaultColumnsEnv'] + )] + #[Assert\NotBlank()] + #[Assert\Unique()] + #[Assert\All([new Assert\Type(AssemblyBomTableColumns::class)])] + + public array $assembliesBomDefaultColumns = [AssemblyBomTableColumns::QUANTITY, AssemblyBomTableColumns::ID, + AssemblyBomTableColumns::IPN, AssemblyBomTableColumns::NAME, AssemblyBomTableColumns::DESCRIPTION]; + #[SettingsParameter(label: new TM("settings.behavior.table.preview_image_min_width"), formOptions: ['attr' => ['min' => 1, 'max' => 100]], envVar: "int:TABLE_IMAGE_PREVIEW_MIN_SIZE", envVarMode: EnvVarMode::OVERWRITE @@ -101,4 +132,36 @@ public static function mapPartsDefaultColumnsEnv(string $columns): array return $ret; } + public static function mapAssembliesDefaultColumnsEnv(string $columns): array + { + $exploded = explode(',', $columns); + $ret = []; + foreach ($exploded as $column) { + $enum = AssemblyTableColumns::tryFrom($column); + if (!$enum) { + throw new \InvalidArgumentException("Invalid column '$column' in TABLE_ASSEMBLIES_DEFAULT_COLUMNS"); + } + + $ret[] = $enum; + } + + return $ret; + } + + public static function mapAssemblyBomsDefaultColumnsEnv(string $columns): array + { + $exploded = explode(',', $columns); + $ret = []; + foreach ($exploded as $column) { + $enum = AssemblyBomTableColumns::tryFrom($column); + if (!$enum) { + throw new \InvalidArgumentException("Invalid column '$column' in TABLE_ASSEMBLIES_BOM_DEFAULT_COLUMNS"); + } + + $ret[] = $enum; + } + + return $ret; + } + } diff --git a/src/Settings/MiscSettings/AssemblySettings.php b/src/Settings/MiscSettings/AssemblySettings.php new file mode 100644 index 000000000..82fb26b66 --- /dev/null +++ b/src/Settings/MiscSettings/AssemblySettings.php @@ -0,0 +1,45 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Settings\MiscSettings; + +use App\Settings\SettingsIcon; +use Jbtronics\SettingsBundle\Metadata\EnvVarMode; +use Jbtronics\SettingsBundle\Settings\Settings; +use Jbtronics\SettingsBundle\Settings\SettingsParameter; +use Jbtronics\SettingsBundle\Settings\SettingsTrait; +use Symfony\Component\Translation\TranslatableMessage as TM; + +#[Settings(label: new TM("settings.misc.assembly"))] +#[SettingsIcon("fa-list")] +class AssemblySettings +{ + use SettingsTrait; + + #[SettingsParameter( + label: new TM("settings.misc.assembly.useIpnPlaceholderInName"), + envVar: "bool:CREATE_ASSEMBLY_USE_IPN_PLACEHOLDER_IN_NAME", envVarMode: EnvVarMode::OVERWRITE, + )] + public bool $useIpnPlaceholderInName = true; +} diff --git a/src/Settings/MiscSettings/MiscSettings.php b/src/Settings/MiscSettings/MiscSettings.php index 1c304d4a0..876a04004 100644 --- a/src/Settings/MiscSettings/MiscSettings.php +++ b/src/Settings/MiscSettings/MiscSettings.php @@ -35,4 +35,7 @@ class MiscSettings #[EmbeddedSettings] public ?ExchangeRateSettings $exchangeRate = null; + + #[EmbeddedSettings] + public ?AssemblySettings $assembly = null; } diff --git a/src/Twig/EntityExtension.php b/src/Twig/EntityExtension.php index 762ebb094..086b21c5a 100644 --- a/src/Twig/EntityExtension.php +++ b/src/Twig/EntityExtension.php @@ -22,6 +22,7 @@ */ namespace App\Twig; +use App\Entity\AssemblySystem\Assembly; use App\Entity\Attachments\Attachment; use App\Entity\Base\AbstractDBElement; use App\Entity\ProjectSystem\Project; @@ -108,6 +109,7 @@ public function getEntityType(object $entity): ?string Manufacturer::class => 'manufacturer', Category::class => 'category', Project::class => 'device', + Assembly::class => 'assembly', Attachment::class => 'attachment', Supplier::class => 'supplier', User::class => 'user', diff --git a/src/Validator/Constraints/AssemblySystem/AssemblyCycle.php b/src/Validator/Constraints/AssemblySystem/AssemblyCycle.php new file mode 100644 index 000000000..9d79b879c --- /dev/null +++ b/src/Validator/Constraints/AssemblySystem/AssemblyCycle.php @@ -0,0 +1,39 @@ +. + */ +namespace App\Validator\Constraints\AssemblySystem; + +use Symfony\Component\Validator\Constraint; + +/** + * This constraint checks that there is no cycle in bom configuration of the assembly + */ +#[\Attribute(\Attribute::TARGET_PROPERTY)] +class AssemblyCycle extends Constraint +{ + public string $message = 'assembly.bom_entry.assembly_cycle'; + + public function validatedBy(): string + { + return AssemblyCycleValidator::class; + } +} \ No newline at end of file diff --git a/src/Validator/Constraints/AssemblySystem/AssemblyCycleValidator.php b/src/Validator/Constraints/AssemblySystem/AssemblyCycleValidator.php new file mode 100644 index 000000000..c8fd18d3b --- /dev/null +++ b/src/Validator/Constraints/AssemblySystem/AssemblyCycleValidator.php @@ -0,0 +1,169 @@ +. + */ +namespace App\Validator\Constraints\AssemblySystem; + +use App\Entity\AssemblySystem\Assembly; +use Symfony\Component\Form\Form; +use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\ConstraintValidator; +use Symfony\Component\Validator\Exception\UnexpectedTypeException; +use Symfony\Component\Validator\Violation\ConstraintViolationBuilder; +use ReflectionClass; + +/** + * Validator class to check for cycles in assemblies based on BOM entries. + * + * This validator ensures that the structure of assemblies does not contain circular dependencies + * by validating each entry in the Bill of Materials (BOM) of the given assembly. Additionally, + * it can handle form-submitted BOM entries to include these in the validation process. + */ +class AssemblyCycleValidator extends ConstraintValidator +{ + public function validate($value, Constraint $constraint): void + { + if (!$constraint instanceof AssemblyCycle) { + throw new UnexpectedTypeException($constraint, AssemblyCycle::class); + } + + if (!$value instanceof Assembly) { + return; + } + + $availableViolations = $this->context->getViolations(); + if (count($availableViolations) > 0) { + //already violations given, currently no more needed to check + + return; + } + + $bomEntries = []; + + if ($this->context->getRoot() instanceof Form && $this->context->getRoot()->has('bom_entries')) { + $bomEntries = $this->context->getRoot()->get('bom_entries')->getData(); + $bomEntries = is_array($bomEntries) ? $bomEntries : iterator_to_array($bomEntries); + } elseif ($this->context->getRoot() instanceof Assembly) { + $bomEntries = $value->getBomEntries()->toArray(); + } + + $relevantEntries = []; + + foreach ($bomEntries as $bomEntry) { + if ($bomEntry->getReferencedAssembly() !== null) { + $relevantEntries[$bomEntry->getId()] = $bomEntry; + } + } + + $visitedAssemblies = []; + foreach ($relevantEntries as $bomEntry) { + if ($this->hasCycle($bomEntry->getReferencedAssembly(), $value, $visitedAssemblies)) { + $this->addViolation($value, $constraint); + } + } + } + + /** + * Determines if there is a cyclic dependency in the assembly hierarchy. + * + * This method checks if a cycle exists in the hierarchy of referenced assemblies starting + * from a given assembly. It traverses through the Bill of Materials (BOM) entries of each + * assembly recursively and keeps track of visited assemblies to detect cycles. + * + * @param Assembly|null $currentAssembly The current assembly being checked for cycles. + * @param Assembly $originalAssembly The original assembly from where the cycle detection started. + * @param Assembly[] $visitedAssemblies A list of assemblies that have been visited during the current traversal. + * + * @return bool True if a cycle is detected, false otherwise. + */ + private function hasCycle(?Assembly $currentAssembly, Assembly $originalAssembly, array $visitedAssemblies = []): bool + { + //No referenced assembly → no cycle + if ($currentAssembly === null) { + return false; + } + + //If the assembly has already been visited, there is a cycle + if (in_array($currentAssembly->getId(), array_map(fn($a) => $a->getId(), $visitedAssemblies), true)) { + return true; + } + + //Add the current assembly to the visited + $visitedAssemblies[] = $currentAssembly; + + //Go through the bom entries of the current assembly + foreach ($currentAssembly->getBomEntries() as $bomEntry) { + $referencedAssembly = $bomEntry->getReferencedAssembly(); + + if ($referencedAssembly !== null && $this->hasCycle($referencedAssembly, $originalAssembly, $visitedAssemblies)) { + return true; + } + } + + //Remove the current assembly from the list of visit (recursion completed) + array_pop($visitedAssemblies); + + return false; + } + + /** + * Adds a violation to the current context if it hasn’t already been added. + * + * This method checks whether a violation with the same property path as the current violation + * already exists in the context. If such a violation is found, the current violation is not added again. + * The process involves reflection to access private or protected properties of violation objects. + * + * @param mixed $value The value that triggered the violation. + * @param AssemblyCycle $constraint The constraint containing the validation details. + * + */ + private function addViolation(mixed $value, AssemblyCycle $constraint): void + { + /** @var ConstraintViolationBuilder $buildViolation */ + $buildViolation = $this->context->buildViolation($constraint->message) + ->setParameter('%name%', $value->getName()); + + $alreadyAdded = false; + + try { + $reflectionClass = new ReflectionClass($buildViolation); + $property = $reflectionClass->getProperty('propertyPath'); + $propertyPath = $property->getValue($buildViolation); + + $availableViolations = $this->context->getViolations(); + + foreach ($availableViolations as $tmpViolation) { + $tmpReflectionClass = new ReflectionClass($tmpViolation); + $tmpProperty = $tmpReflectionClass->getProperty('propertyPath'); + $tmpPropertyPath = $tmpProperty->getValue($tmpViolation); + + if ($tmpPropertyPath === $propertyPath) { + $alreadyAdded = true; + } + } + } catch (\ReflectionException) { + } + + if (!$alreadyAdded) { + $buildViolation->addViolation(); + } + } +} diff --git a/src/Validator/Constraints/AssemblySystem/AssemblyInvalidBomEntry.php b/src/Validator/Constraints/AssemblySystem/AssemblyInvalidBomEntry.php new file mode 100644 index 000000000..73234c86e --- /dev/null +++ b/src/Validator/Constraints/AssemblySystem/AssemblyInvalidBomEntry.php @@ -0,0 +1,21 @@ +context->getViolations(); + if (count($availableViolations) > 0) { + //already violations given, currently no more needed to check + + return; + } + + $bomEntries = []; + + if ($this->context->getRoot() instanceof Form && $this->context->getRoot()->has('bom_entries')) { + $bomEntries = $this->context->getRoot()->get('bom_entries')->getData(); + $bomEntries = is_array($bomEntries) ? $bomEntries : iterator_to_array($bomEntries); + } elseif ($this->context->getRoot() instanceof Assembly) { + $bomEntries = $value->getBomEntries()->toArray(); + } + + $relevantEntries = []; + + foreach ($bomEntries as $bomEntry) { + if ($bomEntry->getReferencedAssembly() !== null) { + $relevantEntries[$bomEntry->getId()] = $bomEntry; + } + } + + foreach ($relevantEntries as $bomEntry) { + $referencedAssembly = $bomEntry->getReferencedAssembly(); + + if ($bomEntry->getAssembly()->getParent()?->getId() === $referencedAssembly->getParent()?->getId()) { + //Save on the same assembly level + continue; + } elseif ($this->isInvalidBomEntry($referencedAssembly, $bomEntry->getAssembly())) { + $this->addViolation($value, $constraint); + } + } + } + + /** + * Determines whether a Bill of Materials (BOM) entry is invalid based on the relationship + * between the current assembly and the parent assembly. + * + * @param Assembly|null $currentAssembly The current assembly being analyzed. Null indicates no assembly is referenced. + * @param Assembly $parentAssembly The parent assembly to check against the current assembly. + * + * @return bool Returns + */ + private function isInvalidBomEntry(?Assembly $currentAssembly, Assembly $parentAssembly): bool + { + //No assembly referenced -> no problems + if ($currentAssembly === null) { + return false; + } + + //Check: is the current assembly a descendant of the parent assembly? + if ($currentAssembly->isChildOf($parentAssembly)) { + return true; + } + + //Recursive check: Analyze the current assembly list + foreach ($currentAssembly->getBomEntries() as $bomEntry) { + $referencedAssembly = $bomEntry->getReferencedAssembly(); + + if ($this->isInvalidBomEntry($referencedAssembly, $parentAssembly)) { + return true; + } + } + + return false; + + } + + /** + * Adds a violation to the current context if it hasn’t already been added. + * + * This method checks whether a violation with the same property path as the current violation + * already exists in the context. If such a violation is found, the current violation is not added again. + * The process involves reflection to access private or protected properties of violation objects. + * + * @param mixed $value The value that triggered the violation. + * @param AssemblyInvalidBomEntry $constraint The constraint containing the validation details. + * + */ + private function addViolation($value, AssemblyInvalidBomEntry $constraint): void + { + /** @var ConstraintViolationBuilder $buildViolation */ + $buildViolation = $this->context->buildViolation($constraint->message) + ->setParameter('%name%', $value->getName()); + + $alreadyAdded = false; + + try { + $reflectionClass = new ReflectionClass($buildViolation); + $property = $reflectionClass->getProperty('propertyPath'); + $propertyPath = $property->getValue($buildViolation); + + $availableViolations = $this->context->getViolations(); + + foreach ($availableViolations as $tmpViolation) { + $tmpReflectionClass = new ReflectionClass($tmpViolation); + $tmpProperty = $tmpReflectionClass->getProperty('propertyPath'); + $tmpPropertyPath = $tmpProperty->getValue($tmpViolation); + + if ($tmpPropertyPath === $propertyPath) { + $alreadyAdded = true; + } + } + } catch (\ReflectionException) { + } + + if (!$alreadyAdded) { + $buildViolation->addViolation(); + } + } +} diff --git a/src/Validator/Constraints/AssemblySystem/UniqueReferencedAssembly.php b/src/Validator/Constraints/AssemblySystem/UniqueReferencedAssembly.php new file mode 100644 index 000000000..55a31440a --- /dev/null +++ b/src/Validator/Constraints/AssemblySystem/UniqueReferencedAssembly.php @@ -0,0 +1,34 @@ +. + */ +namespace App\Validator\Constraints\AssemblySystem; + +use Symfony\Component\Validator\Constraint; + +/** + * This constraint checks that the given UniqueReferencedAssembly is valid. + */ +#[\Attribute(\Attribute::TARGET_PROPERTY)] +class UniqueReferencedAssembly extends Constraint +{ + public string $message = 'assembly.bom_entry.assembly_already_in_bom'; +} \ No newline at end of file diff --git a/src/Validator/Constraints/AssemblySystem/UniqueReferencedAssemblyValidator.php b/src/Validator/Constraints/AssemblySystem/UniqueReferencedAssemblyValidator.php new file mode 100644 index 000000000..0b3eb3952 --- /dev/null +++ b/src/Validator/Constraints/AssemblySystem/UniqueReferencedAssemblyValidator.php @@ -0,0 +1,50 @@ +. + */ +namespace App\Validator\Constraints\AssemblySystem; + +use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\ConstraintValidator; + +class UniqueReferencedAssemblyValidator extends ConstraintValidator +{ + public function validate($value, Constraint $constraint) + { + $assemblies = []; + + foreach ($value as $entry) { + $referencedAssemblyId = $entry->getReferencedAssembly()?->getId(); + if ($referencedAssemblyId === null) { + continue; + } + + if (isset($assemblies[$referencedAssemblyId])) { + /** @var UniqueReferencedAssembly $constraint */ + $this->context->buildViolation($constraint->message) + ->atPath('referencedAssembly') + ->addViolation(); + return; + } + $assemblies[$referencedAssemblyId] = true; + } + } +} diff --git a/templates/admin/_export_form.html.twig b/templates/admin/_export_form.html.twig index 07b00d43c..b02d4a8e8 100644 --- a/templates/admin/_export_form.html.twig +++ b/templates/admin/_export_form.html.twig @@ -1,6 +1,6 @@ -
+ -
+
@@ -23,7 +23,7 @@
-
+
@@ -34,9 +34,32 @@
+ {% if path is defined and 'assembly' in path %} +
+ +
+ +
+
+ {% else %} +
+ +
+ + +
+
+ {% endif %} +
- \ No newline at end of file + diff --git a/templates/admin/assembly_admin.html.twig b/templates/admin/assembly_admin.html.twig new file mode 100644 index 000000000..b6bf6d09b --- /dev/null +++ b/templates/admin/assembly_admin.html.twig @@ -0,0 +1,48 @@ +{% extends "admin/base_admin.html.twig" %} + +{# @var entity App\Entity\AssemblySystem\Assembly #} + +{% block card_title %} + {% trans %}assembly.caption{% endtrans %} +{% endblock %} + +{% block edit_title %} + {% trans %}assembly.edit{% endtrans %}: {{ entity.name }} +{% endblock %} + +{% block new_title %} + {% trans %}assembly.new{% endtrans %} +{% endblock %} + +{% block additional_pills %} + +{% endblock %} + +{% block quick_links %} +
+
+ +
+
+{% endblock %} + +{% block additional_controls %} + {{ form_row(form.description) }} + {{ form_row(form.status) }} + {{ form_row(form.ipn) }} +{% endblock %} + +{% block additional_panes %} +
+ {% form_theme form.bom_entries with ['form/collection_types_layout_assembly.html.twig'] %} + {{ form_errors(form.bom_entries) }} + {{ form_widget(form.bom_entries) }} + {% if entity.id %} + + + {% trans %}assembly.edit.bom.import_bom{% endtrans %} + + {% endif %} +
+{% endblock %} diff --git a/templates/assemblies/add_parts.html.twig b/templates/assemblies/add_parts.html.twig new file mode 100644 index 000000000..d8d8e657f --- /dev/null +++ b/templates/assemblies/add_parts.html.twig @@ -0,0 +1,22 @@ +{% extends "main_card.html.twig" %} + +{% block title %}{% trans %}assembly.add_parts_to_assembly{% endtrans %}{% endblock %} + +{% block card_title %} + + {% trans %}assembly.add_parts_to_assembly{% endtrans %}{% if assembly %}: {{ assembly.name }}{% endif %} +{% endblock %} + +{% block card_content %} + + {{ form_start(form) }} + + {{ form_row(form.assembly) }} + {% form_theme form.bom_entries with ['form/collection_types_layout_assembly.html.twig'] %} + {{ form_widget(form.bom_entries) }} + + {{ form_row(form.submit) }} + + {{ form_end(form) }} + +{% endblock %} \ No newline at end of file diff --git a/templates/assemblies/export_bom_pdf.html.twig b/templates/assemblies/export_bom_pdf.html.twig new file mode 100644 index 000000000..15bf5d883 --- /dev/null +++ b/templates/assemblies/export_bom_pdf.html.twig @@ -0,0 +1,103 @@ + + + + Assembly Hierarchy + + + + + +

Table of Contents

+ + + + + + + + + + + {% for assembly in assemblies %} + + + + + + + {% endfor %} + +
#Assembly NameIPNSection
{{ loop.index }}Assembly: {{ assembly.name }}{% if assembly.ipn != '' %}{{ assembly.ipn }}{% else %}-{% endif %}{{ loop.index + 1 }}
+
+ + +{% for assembly in assemblies %} +
Assembly: {{ assembly.name }}
+ + + + + + + + + + + + {% for part in assembly.parts %} + + + + + + + + {% endfor %} + {% for other in assembly.others %} + + + + + + + + {% endfor %} + {% for referencedAssembly in assembly.referencedAssemblies %} + + + + + + + + {% endfor %} + +
NameIPNQuantityMultiplierEffective Quantity
{{ part.name }}{{ part.ipn }}{{ part.quantity }}{% if assembly.multiplier %}{{ assembly.multiplier }}{% else %}-{% endif %}{{ part.effectiveQuantity }}
{{ other.name }}{{ other.ipn }}{{ other.quantity }}{{ other.multiplier }}{{ other.effectiveQuantity }}
{{ referencedAssembly.name }}{{ referencedAssembly.ipn }}{{ referencedAssembly.quantity }}{{ referencedAssembly.quantity }}
+ + {% for refAssembly in assembly.referencedAssemblies %} + {% include 'assemblies/export_bom_referenced_assembly_pdf.html.twig' with {'assembly': refAssembly} only %} + {% endfor %} + + {% if not loop.last %} +
+ {% endif %} + + +{% endfor %} + + diff --git a/templates/assemblies/export_bom_referenced_assembly_pdf.html.twig b/templates/assemblies/export_bom_referenced_assembly_pdf.html.twig new file mode 100644 index 000000000..b5a1324d9 --- /dev/null +++ b/templates/assemblies/export_bom_referenced_assembly_pdf.html.twig @@ -0,0 +1,55 @@ +
+
Referenced Assembly: {{ assembly.name }} [IPN: {% if assembly.ipn != '' %}{{ assembly.ipn }}{% else %}-{% endif %}, quantity: {{ assembly.quantity }}]
+ + + + + + + + + + + + + + {% for part in assembly.parts %} + + + + + + + + + {% endfor %} + + {% for other in assembly.others %} + + + + + + + + + {% endfor %} + + {% for referencedAssembly in assembly.referencedAssemblies %} + + + + + + + + + {% endfor %} + +
TypeNameIPNQuantityMultiplierEffective Quantity
Part{{ part.name }}{{ part.ipn }}{{ part.quantity }}{% if assembly.multiplier %}{{ assembly.multiplier }}{% else %}-{% endif %}{{ part.effectiveQuantity }}
Other{{ other.name }}-{{ other.quantity }}{{ other.multiplier }}-
Referenced assembly{{ referencedAssembly.name }}-{{ referencedAssembly.quantity }}{{ referencedAssembly.multiplier }}
+ + + {% for refAssembly in assembly.referencedAssemblies %} + {% include 'assemblies/export_bom_referenced_assembly_pdf.html.twig' with {'assembly': refAssembly} only %} + {% endfor %} +
diff --git a/templates/assemblies/import_bom.html.twig b/templates/assemblies/import_bom.html.twig new file mode 100644 index 000000000..bfbecf8d4 --- /dev/null +++ b/templates/assemblies/import_bom.html.twig @@ -0,0 +1,114 @@ +{% extends "main_card.html.twig" %} + +{% block title %}{% trans %}assembly.import_bom{% endtrans %}{% endblock %} + +{% block before_card %} + {% if validationErrors or importerErrors %} +
+

{% trans %}parts.import.errors.title{% endtrans %}

+
    + {% if validationErrors %} + {% for violation in validationErrors %} +
  • + {{ violation.propertyPath }}: + {{ violation.message|trans(violation.parameters, 'validators') }} +
  • + {% endfor %} + {% endif %} + + {% if importerErrors %} + {% for violation in importerErrors %} +
  • + {{ violation.propertyPath }}: + {{ violation.message|trans(violation.parameters, 'validators')|raw }} +
  • + {% endfor %} + {% endif %} +
+
+ {% endif %} +{% endblock %} + +{% block card_title %} + + {% trans %}assembly.import_bom{% endtrans %}{% if assembly %}: {{ assembly.name }}{% endif %} +{% endblock %} + +{% block card_content %} + {{ form(form) }} +{% endblock %} + +{% block additional_content %} +
+
+
+
+ {% trans %}assembly.import_bom.template.header.json{% endtrans %} +
+
+
{{ jsonTemplate|json_encode(constant('JSON_PRETTY_PRINT') b-or constant('JSON_UNESCAPED_UNICODE')) }}
+ + {{ 'assembly.bom_import.template.json.table'|trans|raw }} +
+
+
+
+
+
+ {% trans %}assembly.import_bom.template.header.csv{% endtrans %} +
+
+ {{ 'assembly.bom_import.template.csv.exptected_columns'|trans }} + +
quantity;name;part_id;part_mpnr;part_ipn;part_name;part_description;part_manufacturer_id;part_manufacturer_name;part_category_id;part_category_name
+ +
    +
  • quantity
  • +
  • name
  • +
  • part_id
  • +
  • part_mpnr
  • +
  • part_ipn
  • +
  • part_name
  • +
  • part_description
  • +
  • part_manufacturer_id
  • +
  • part_manufacturer_name
  • +
  • part_category_id
  • +
  • part_category_name
  • +
+ + {{ 'assembly.bom_import.template.csv.table'|trans|raw }} +
+
+
+
+
+
+ {% trans %}assembly.import_bom.template.header.kicad_pcbnew{% endtrans %} +
+
+ {{ 'assembly.bom_import.template.kicad_pcbnew.exptected_columns'|trans }} +
Id;Designator;Package;Quantity;Designation;Supplier and ref
+ +
    +
  • Id
  • +
  • Designator
  • +
  • Package
  • +
  • Quantity
  • +
  • Designation
  • +
  • Supplier and ref
  • +
  • Note
  • +
  • Footprint
  • +
  • Value
  • +
  • Footprint
  • +
+ + {{ 'assembly.bom_import.template.kicad_pcbnew.exptected_columns.note'|trans|raw }} + + {{ 'assembly.bom_import.template.kicad_pcbnew.table'|trans|raw }} + + {{ 'assembly.bom_import.template.json.table'|trans|raw }} +
+
+
+
+{% endblock %} diff --git a/templates/assemblies/info/_attachments_info.html.twig b/templates/assemblies/info/_attachments_info.html.twig new file mode 100644 index 000000000..747426c3a --- /dev/null +++ b/templates/assemblies/info/_attachments_info.html.twig @@ -0,0 +1,91 @@ +{% import "helper.twig" as helper %} + + + + + + + + + + + + + + + + + {% for attachment in assembly.attachments %} + + + + + + + + + + {% endfor %} + + + +
{% trans %}attachment.name{% endtrans %}{% trans %}attachment.attachment_type{% endtrans %}{% trans %}attachment.file_name{% endtrans %}{% trans %}attachment.file_size{% endtrans %}
+ {% import "components/attachments.macro.html.twig" as attachments %} + {{ attachments.attachment_icon(attachment, attachment_manager) }} + {{ attachment.name }}{{ attachment.attachmentType.fullPath }} + {% if attachment.hasInternal() %} + {{ attachment.filename }} + {% endif %} + + {% if not attachment.hasInternal() %} + + {% trans %}attachment.external_only{% endtrans %} + + {% elseif attachment_manager.internalFileExisting(attachment) %} + + {{ attachment_manager.humanFileSize(attachment) }} + + {% else %} + + {% trans %}attachment.file_not_found{% endtrans %} + + {% endif %} + {% if attachment.secure %} +
+ {% trans %}attachment.secure{% endtrans %} + + {% endif %} + {% if attachment == assembly.masterPictureAttachment %} +
+ + {% trans %}attachment.preview{% endtrans %} + + {% endif %} +
+ + + + + + + + + + +
+ + +
+
\ No newline at end of file diff --git a/templates/assemblies/info/_info.html.twig b/templates/assemblies/info/_info.html.twig new file mode 100644 index 000000000..97da3f708 --- /dev/null +++ b/templates/assemblies/info/_info.html.twig @@ -0,0 +1,72 @@ +{% import "helper.twig" as helper %} + +
+
+
+
+ {% if assembly.masterPictureAttachment %} + + + + {% else %} + Part main image + {% endif %} +
+
+

{{ assembly.name }} + {# You need edit permission to use the edit button #} + {% if is_granted('edit', assembly) %} + + {% endif %} +

+
{{ assembly.description|format_markdown(true) }}
+
+
+
+ + +
{# Sidebar panel with infos about last creation date, etc. #} +
+ + {{ helper.date_user_combination(assembly, true) }} + +
+ + {{ helper.date_user_combination(assembly, false) }} + +
+ +
+
+ {{ helper.assemblies_status_to_badge(assembly.status) }} +
+
+
+
+ + + {{ assembly.bomEntries | length }} + {% trans %}assembly.info.bom_entries_count{% endtrans %} + +
+
+ {% if assembly.children is not empty %} +
+
+ + + {{ assembly.children | length }} + {% trans %}assembly.info.sub_assemblies_count{% endtrans %} + +
+
+ {% endif %} +
+ + {% if assembly.comment is not empty %} +

+

{% trans %}comment.label{% endtrans %}:
+ {{ assembly.comment|format_markdown }} +

+ {% endif %} +
diff --git a/templates/assemblies/info/_info_card.html.twig b/templates/assemblies/info/_info_card.html.twig new file mode 100644 index 000000000..2d0c535b2 --- /dev/null +++ b/templates/assemblies/info/_info_card.html.twig @@ -0,0 +1,118 @@ +{% import "helper.twig" as helper %} +{% import "label_system/dropdown_macro.html.twig" as dropdown %} + +{{ helper.breadcrumb_entity_link(assembly) }} + +
+
+
+ +
+
+
+ {% if assembly.description is not empty %} + {{ assembly.description|format_markdown }} + {% endif %} +
+ +
+
+
+
+
+
+ + {{ assembly.name }} +
+
+ + + {% if assembly.parent %} + {{ assembly.parent.fullPath }} + {% else %} + - + {% endif %} + +
+
+
+ {% block quick_links %}{% endblock %} + + + {% trans %}entity.edit.btn{% endtrans %} + +
+ + {{ assembly.lastModified | format_datetime("short") }} + +
+ + {{ assembly.addedDate | format_datetime("short") }} + +
+
+
+
+
+
+
+ + {{ assembly.children | length }} +
+
+ + {{ assembly.bomEntries | length }} +
+
+
+ + {% if assembly.attachments is not empty %} +
+ {% include "parts/info/_attachments_info.html.twig" with {"part": assembly} %} +
+ {% endif %} + + {% if assembly.comment is not empty %} +
+
+ {{ assembly.comment|format_markdown }} +
+
+ {% endif %} +
+
+
+
+
+
+
\ No newline at end of file diff --git a/templates/assemblies/info/_part.html.twig b/templates/assemblies/info/_part.html.twig new file mode 100644 index 000000000..1fa8b90ed --- /dev/null +++ b/templates/assemblies/info/_part.html.twig @@ -0,0 +1,5 @@ +{% import "components/datatables.macro.html.twig" as datatables %} + +
+ +{{ datatables.datatable(datatable, 'elements/datatables/datatables', 'assemblies') }} \ No newline at end of file diff --git a/templates/assemblies/info/_subassemblies.html.twig b/templates/assemblies/info/_subassemblies.html.twig new file mode 100644 index 000000000..243e7d332 --- /dev/null +++ b/templates/assemblies/info/_subassemblies.html.twig @@ -0,0 +1,28 @@ + + + + + + + + + + + {% for assembly in assembly.children %} + + + + + + + {% endfor %} + +
{% trans %}name.label{% endtrans %}{% trans %}description.label{% endtrans %}# {% trans %}assembly.info.bom_entries_count{% endtrans %}# {% trans %}assembly.info.sub_assemblies_count{% endtrans %}
{# Name #} + {{ assembly.name }} + {# Description #} + {{ assembly.description | format_markdown }} + + {{ assembly.bomEntries | length }} + + {{ assembly.children | length }} +
diff --git a/templates/assemblies/info/info.html.twig b/templates/assemblies/info/info.html.twig new file mode 100644 index 000000000..2cb3636f8 --- /dev/null +++ b/templates/assemblies/info/info.html.twig @@ -0,0 +1,135 @@ +{% extends "main_card.html.twig" %} +{% import "helper.twig" as helper %} + +{% block title %} + {% trans %}assembly.info.title{% endtrans %}: {{ assembly.name }} +{% endblock %} + +{% block before_card %} + +{% endblock %} + +{% block content %} + {{ helper.breadcrumb_entity_link(assembly) }} + {{ parent() }} +{% endblock %} + +{% block card_title %} + {% if assembly.masterPictureAttachment is not null and attachment_manager.isFileExisting(assembly.masterPictureAttachment) %} + + {% else %} + {{ helper.entity_icon(assembly, "me-1") }} + {% endif %} + {% trans %}assembly.info.title{% endtrans %}: {{ assembly.name }} +{% endblock %} + +{% block card_content %} + +
+
+ {% include "assemblies/info/_info.html.twig" %} +
+ {% if assembly.children is not empty %} +
+ {% include "assemblies/info/_subassemblies.html.twig" %} +
+ {% endif %} +
+ {% include "assemblies/info/_part.html.twig" %} +
+
+ {% include "assemblies/info/_attachments_info.html.twig" with {"assembly": assembly} %} +
+
+ {% for name, parameters in assembly.groupedParameters %} + {% if name is not empty %}
{{ name }}
{% endif %} + {{ helper.parameters_table(assembly.parameters) }} + {% endfor %} +
+
+ +{% endblock %} diff --git a/templates/assemblies/lists/_action_bar.html.twig b/templates/assemblies/lists/_action_bar.html.twig new file mode 100644 index 000000000..37289812a --- /dev/null +++ b/templates/assemblies/lists/_action_bar.html.twig @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/templates/assemblies/lists/_filter.html.twig b/templates/assemblies/lists/_filter.html.twig new file mode 100644 index 000000000..11be7bc24 --- /dev/null +++ b/templates/assemblies/lists/_filter.html.twig @@ -0,0 +1,62 @@ +
+
+ +
+
+
+ + + {{ form_start(filterForm, {"attr": {"data-controller": "helpers--form-cleanup", "data-action": "helpers--form-cleanup#submit"}}) }} + +
+
+ {{ form_row(filterForm.name) }} + {{ form_row(filterForm.description) }} + {{ form_row(filterForm.comment) }} +
+ +
+ {{ form_row(filterForm.dbId) }} + {{ form_row(filterForm.ipn) }} + {{ form_row(filterForm.lastModified) }} + {{ form_row(filterForm.addedDate) }} +
+ +
+ {{ form_row(filterForm.attachmentsCount) }} + {{ form_row(filterForm.attachmentType) }} + {{ form_row(filterForm.attachmentName) }} +
+
+ + {{ form_row(filterForm.submit) }} + {{ form_row(filterForm.discard) }} + +
+
+ +
+
+ + {# Retain the query parameters of the search form if it is existing #} + {% if searchFilter is defined %} + {% for property, value in searchFilter|to_array %} + + {% endfor %} + + {% endif %} + + {{ form_end(filterForm) }} +
+
+
\ No newline at end of file diff --git a/templates/assemblies/lists/all_list.html.twig b/templates/assemblies/lists/all_list.html.twig new file mode 100644 index 000000000..70d75ad40 --- /dev/null +++ b/templates/assemblies/lists/all_list.html.twig @@ -0,0 +1,30 @@ +{% extends "base.html.twig" %} + +{% block title %} + {% trans %}assembly_list.all.title{% endtrans %} +{% endblock %} + +{% block content %} + +
+
+
+ +
+
+
+ +
+
+
+ + {% include "assemblies/lists/_filter.html.twig" %} +
+ + {% include "assemblies/lists/_action_bar.html.twig" with {'url_options': {}} %} + {% include "assemblies/lists/data.html.twig" %} + +{% endblock %} diff --git a/templates/assemblies/lists/data.html.twig b/templates/assemblies/lists/data.html.twig new file mode 100644 index 000000000..69e13e4f5 --- /dev/null +++ b/templates/assemblies/lists/data.html.twig @@ -0,0 +1,3 @@ +{% import "components/datatables.macro.html.twig" as datatables %} + +{{ datatables.partsDatatableWithForm(datatable) }} diff --git a/templates/components/tree_macros.html.twig b/templates/components/tree_macros.html.twig index 366d42fe8..2e55147a1 100644 --- a/templates/components/tree_macros.html.twig +++ b/templates/components/tree_macros.html.twig @@ -7,6 +7,7 @@ ['manufacturers', path('tree_manufacturer_root'), 'manufacturer.labelp', is_granted('@manufacturers.read') and is_granted('@parts.read')], ['suppliers', path('tree_supplier_root'), 'supplier.labelp', is_granted('@suppliers.read') and is_granted('@parts.read')], ['projects', path('tree_device_root'), 'project.labelp', is_granted('@projects.read')], + ['assembly', path('tree_assembly_root'), 'assembly.labelp', is_granted('@assemblies.read')], ['tools', path('tree_tools'), 'tools.label', true], ] %} diff --git a/templates/form/collection_types_layout_assembly.html.twig b/templates/form/collection_types_layout_assembly.html.twig new file mode 100644 index 000000000..1bd79bb5f --- /dev/null +++ b/templates/form/collection_types_layout_assembly.html.twig @@ -0,0 +1,74 @@ +{% block assembly_bom_entry_collection_widget %} + {% import 'components/collection_type.macro.html.twig' as collection %} +
+ + + + {# expand button #} + + + + {# Remove button #} + + + + + {% for entry in form %} + {{ form_widget(entry) }} + {% endfor %} + +
{% trans %}assembly.bom.quantity{% endtrans %}{% trans %}assembly.bom.partOrAssembly{% endtrans %}{% trans %}assembly.bom.identifiers{% endtrans %}
+ + +
+ +{% endblock %} + +{% block assembly_bom_entry_widget %} + {% set target_id = 'expand_row-' ~ form.vars.name %} + + {% import 'components/collection_type.macro.html.twig' as collection %} + + + + + + {{ form_widget(form.quantity) }} + {{ form_errors(form.quantity) }} + + + {{ form_row(form.part) }} + {{ form_errors(form.part) }} +
+ {{ form_widget(form.referencedAssembly) }} + {{ form_errors(form.referencedAssembly) }} + + + {{ form_row(form.name) }} + {{ form_errors(form.name) }} +
+ {{ form_row(form.designator) }} + {{ form_errors(form.designator) }} + + + + {{ form_errors(form) }} + + + + + +
+ {{ form_row(form.comment) }} +
+ + +{% endblock %} diff --git a/templates/helper.twig b/templates/helper.twig index bd1d2aa7a..3ddb4f7fa 100644 --- a/templates/helper.twig +++ b/templates/helper.twig @@ -76,6 +76,21 @@ {% endif %} {% endmacro %} +{% macro assemblies_status_to_badge(status, class="badge") %} + {% if status is not empty %} + {% set color = " bg-secondary" %} + + {% if status == "in_production" %} + {% set color = " bg-success" %} + {% endif %} + + + + {{ ("assembly.status." ~ status) | trans }} + + {% endif %} +{% endmacro %} + {% macro structural_entity_link(entity, link_type = "list_parts") %} {# @var entity \App\Entity\Base\StructuralDBElement #} {% if entity %} @@ -101,6 +116,7 @@ "category": ["fa-solid fa-tags", "category.label"], "currency": ["fa-solid fa-coins", "currency.label"], "device": ["fa-solid fa-archive", "project.label"], + "assembly": ["fa-solid fa-list", "assembly.label"], "footprint": ["fa-solid fa-microchip", "footprint.label"], "group": ["fa-solid fa-users", "group.label"], "label_profile": ["fa-solid fa-qrcode", "label_profile.label"], diff --git a/templates/parts/info/_assemblies.html.twig b/templates/parts/info/_assemblies.html.twig new file mode 100644 index 000000000..d4996c592 --- /dev/null +++ b/templates/parts/info/_assemblies.html.twig @@ -0,0 +1,31 @@ +{% import "components/attachments.macro.html.twig" as attachments %} +{% import "helper.twig" as helper %} + + + + + + + + + + + + + {% for bom_entry in part.assemblyBomEntries %} + {# @var bom_entry App\Entity\Assembly\AssemblyBOMEntry #} + + + {# Name #} + {# Description #} + + + {% endfor %} + +
{% trans %}entity.info.name{% endtrans %}{% trans %}description.label{% endtrans %}{% trans %}assembly.bom.quantity{% endtrans %}
{% if bom_entry.assembly.masterPictureAttachment is not null %}{{ attachments.attachment_icon(bom_entry.assembly.masterPictureAttachment, attachment_manager) }}{% endif %}{{ bom_entry.assembly.name }}{{ bom_entry.assembly.description|format_markdown }}{{ bom_entry.quantity | format_amount(part.partUnit) }}
+ + + + {% trans %}part.info.add_part_to_assembly{% endtrans %} + \ No newline at end of file diff --git a/templates/parts/info/show_part_info.html.twig b/templates/parts/info/show_part_info.html.twig index 96b5e2091..cd7b4ce7a 100644 --- a/templates/parts/info/show_part_info.html.twig +++ b/templates/parts/info/show_part_info.html.twig @@ -109,15 +109,20 @@ {% trans %}vendor.partinfo.history{% endtrans %} - {% if part.projectBomEntries is not empty %} - - {% endif %} + +
+
+ {% include "parts/info/_assemblies.html.twig" %} +
+
{% include "parts/info/_history.html.twig" %}
diff --git a/templates/projects/import_bom.html.twig b/templates/projects/import_bom.html.twig index 0e7f17875..3f9059120 100644 --- a/templates/projects/import_bom.html.twig +++ b/templates/projects/import_bom.html.twig @@ -3,29 +3,107 @@ {% block title %}{% trans %}project.import_bom{% endtrans %}{% endblock %} {% block before_card %} - {% if errors %} + {% if validationErrors or importerErrors %}

{% trans %}parts.import.errors.title{% endtrans %}

    - {% for violation in errors %} -
  • - {{ violation.propertyPath }}: - {{ violation.message|trans(violation.parameters, 'validators') }} -
  • - {% endfor %} + {% if validationErrors %} + {% for violation in validationErrors %} +
  • + {{ violation.propertyPath }}: + {{ violation.message|trans(violation.parameters, 'validators') }} +
  • + {% endfor %} + {% endif %} + + {% if importerErrors %} + {% for violation in importerErrors %} +
  • + {{ violation.propertyPath }}: + {{ violation.message|trans(violation.parameters, 'validators')|raw }} +
  • + {% endfor %} + {% endif %}
{% endif %} {% endblock %} - {% block card_title %} {% trans %}project.import_bom{% endtrans %}{% if project %}: {{ project.name }}{% endif %} {% endblock %} {% block card_content %} - {{ form(form) }} +{% endblock %} + +{% block additional_content %} +
+
+
+
+ {% trans %}project.import_bom.template.header.json{% endtrans %} +
+
+
{{ jsonTemplate|json_encode(constant('JSON_PRETTY_PRINT') b-or constant('JSON_UNESCAPED_UNICODE')) }}
+ + {{ 'project.bom_import.template.json.table'|trans|raw }} +
+
+
+
+
+
+ {% trans %}project.import_bom.template.header.csv{% endtrans %} +
+
+ {{ 'project.bom_import.template.csv.exptected_columns'|trans }} +
quantity;name;part_id;part_mpnr;part_ipn;part_name;part_manufacturer_id;part_manufacturer_name
+ +
    +
  • quantity
  • +
  • name
  • +
  • part_id
  • +
  • part_mpnr
  • +
  • part_ipn
  • +
  • part_name
  • +
  • part_manufacturer_id
  • +
  • part_manufacturer_name
  • +
+ + {{ 'project.bom_import.template.csv.table'|trans|raw }} +
+
+
+
+
+
+ {% trans %}project.import_bom.template.header.kicad_pcbnew{% endtrans %} +
+
+ {{ 'project.bom_import.template.kicad_pcbnew.exptected_columns'|trans }} +
Id;Designator;Package;Quantity;Designation;Supplier and ref
+ +
    +
  • Id
  • +
  • Designator
  • +
  • Package
  • +
  • Quantity
  • +
  • Designation
  • +
  • Supplier and ref
  • +
  • Note
  • +
  • Footprint
  • +
  • Value
  • +
  • Footprint
  • +
+ + {{ 'project.bom_import.template.kicad_pcbnew.exptected_columns.note'|trans|raw }} + + {{ 'project.bom_import.template.kicad_pcbnew.table'|trans|raw }} +
+
+
+
{% endblock %} \ No newline at end of file diff --git a/tests/API/Endpoints/AssembliesEndpointTest.php b/tests/API/Endpoints/AssembliesEndpointTest.php new file mode 100644 index 000000000..80045dc64 --- /dev/null +++ b/tests/API/Endpoints/AssembliesEndpointTest.php @@ -0,0 +1,76 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Tests\API\Endpoints; + +use App\Tests\API\Endpoints\CrudEndpointTestCase; + +class AssembliesEndpointTest extends CrudEndpointTestCase +{ + + protected function getBasePath(): string + { + return '/api/assemblies'; + } + + public function testGetCollection(): void + { + $this->_testGetCollection(); + self::assertJsonContains([ + 'hydra:totalItems' => 7, + ]); + } + + public function testGetChildrenCollection(): void + { + $this->_testGetChildrenCollection(1); + } + + public function testGetItem(): void + { + $this->_testGetItem(1); + $this->_testGetItem(2); + $this->_testGetItem(3); + } + + public function testCreateItem(): void + { + $this->_testPostItem([ + 'name' => 'Test API', + 'parent' => '/api/assemblies/1', + ]); + } + + public function testUpdateItem(): void + { + $this->_testPatchItem(5, [ + 'name' => 'Updated', + 'parent' => '/api/assemblies/2', + ]); + } + + public function testDeleteItem(): void + { + $this->_testDeleteItem(7); + } +} diff --git a/tests/API/Endpoints/AssemblyBOMEntriesEndpointTest.php b/tests/API/Endpoints/AssemblyBOMEntriesEndpointTest.php new file mode 100644 index 000000000..a44e14d65 --- /dev/null +++ b/tests/API/Endpoints/AssemblyBOMEntriesEndpointTest.php @@ -0,0 +1,44 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Tests\API\Endpoints; + +class AssemblyBOMEntriesEndpointTest extends CrudEndpointTestCase +{ + + protected function getBasePath(): string + { + return '/api/assembly_bom_entries'; + } + + public function testGetCollection(): void + { + $this->_testGetCollection(); + } + + public function testGetBomFromAssembly(): void + { + $response = self::createAuthenticatedClient()->request('GET', '/api/assemblies/1/bom'); + self::assertResponseIsSuccessful(); + } +} diff --git a/tests/ApplicationAvailabilityFunctionalTest.php b/tests/ApplicationAvailabilityFunctionalTest.php index d5bced499..bc8f9ab8f 100644 --- a/tests/ApplicationAvailabilityFunctionalTest.php +++ b/tests/ApplicationAvailabilityFunctionalTest.php @@ -142,6 +142,12 @@ public static function urlProvider(): ?Generator yield ['/project/1/build?n=1']; yield ['/project/1/import_bom']; + //Assemblies + yield ['/assembly/1/info']; + yield ['/assembly/1/add_parts']; + yield ['/assembly/1/add_parts?parts=1,2']; + yield ['/assembly/1/import_bom']; + //Test info provider system yield ['/tools/info_providers/providers']; //List all providers yield ['/tools/info_providers/search']; //Search page diff --git a/tests/Controller/AdminPages/AssemblyController.php b/tests/Controller/AdminPages/AssemblyController.php new file mode 100644 index 000000000..ad2118f38 --- /dev/null +++ b/tests/Controller/AdminPages/AssemblyController.php @@ -0,0 +1,35 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Tests\Controller\AdminPages; + +use App\Entity\AssemblySystem\Assembly; +use PHPUnit\Framework\Attributes\Group; + +#[Group('slow')] +#[Group('DB')] +class AssemblyController extends AbstractAdminController +{ + protected static string $base_path = '/en/assembly'; + protected static string $entity_class = Assembly::class; +} diff --git a/tests/Entity/Attachments/AttachmentTest.php b/tests/Entity/Attachments/AttachmentTest.php index 00a68d7d4..699648eb7 100644 --- a/tests/Entity/Attachments/AttachmentTest.php +++ b/tests/Entity/Attachments/AttachmentTest.php @@ -24,6 +24,8 @@ use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Depends; +use App\Entity\AssemblySystem\Assembly; +use App\Entity\Attachments\AssemblyAttachment; use App\Entity\Attachments\Attachment; use App\Entity\Attachments\AttachmentType; use App\Entity\Attachments\AttachmentTypeAttachment; @@ -81,6 +83,7 @@ public static function subClassesDataProvider(): \Iterator yield [CategoryAttachment::class, Category::class]; yield [CurrencyAttachment::class, Currency::class]; yield [ProjectAttachment::class, Project::class]; + yield [AssemblyAttachment::class, Assembly::class]; yield [FootprintAttachment::class, Footprint::class]; yield [GroupAttachment::class, Group::class]; yield [ManufacturerAttachment::class, Manufacturer::class]; diff --git a/tests/Services/ImportExportSystem/BOMImporterTest.php b/tests/Services/ImportExportSystem/BOMImporterTest.php index 52c633d01..dd9f5bd86 100644 --- a/tests/Services/ImportExportSystem/BOMImporterTest.php +++ b/tests/Services/ImportExportSystem/BOMImporterTest.php @@ -29,7 +29,7 @@ use App\Services\ImportExportSystem\BOMImporter; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; -use Symfony\Component\HttpFoundation\File\File; +use Symfony\Component\HttpFoundation\File\UploadedFile; class BOMImporterTest extends WebTestCase { @@ -62,15 +62,17 @@ public function testImportFileIntoProject(): void 4;"C6";"CP_Radial_D6.3mm_P2.50mm";1;"47uF";;; CSV; - $file = $this->createMock(File::class); + $file = $this->createMock(UploadedFile::class); $file->method('getContent')->willReturn($input); + $file->method('getClientOriginalName')->willReturn('import.kicad_pcb'); + $file->method('getClientOriginalExtension')->willReturn('kicad_pcb'); $project = new Project(); $this->assertCount(0, $project->getBOMEntries()); - $bom_entries = $this->service->importFileIntoProject($file, $project, ['type' => 'kicad_pcbnew']); - $this->assertContainsOnlyInstancesOf(ProjectBOMEntry::class, $bom_entries); - $this->assertCount(4, $bom_entries); + $importerResult = $this->service->importFileIntoProject($file, $project, ['type' => 'kicad_pcbnew']); + $this->assertContainsOnlyInstancesOf(ProjectBOMEntry::class, $importerResult->getBomEntries()); + $this->assertCount(4, $importerResult->getBomEntries()); //Check that the BOM entries are added to the project $this->assertCount(4, $project->getBOMEntries()); @@ -87,7 +89,8 @@ public function testStringToBOMEntriesKiCADPCB(): void 4;"C6";"CP_Radial_D6.3mm_P2.50mm";1;"47uF";;; CSV; - $bom = $this->service->stringToBOMEntries($input, ['type' => 'kicad_pcbnew']); + $project = new Project(); + $bom = $this->service->stringToBOMEntries($project, $input, ['type' => 'kicad_pcbnew']); $this->assertContainsOnlyInstancesOf(ProjectBOMEntry::class, $bom); $this->assertCount(4, $bom); @@ -106,7 +109,8 @@ public function testStringToBOMEntriesKiCADPCB(): void 4;"C6";"CP_Radial_D6.3mm_P2.50mm";1;"47uF";;; CSV; - $bom = $this->service->stringToBOMEntries($input, ['type' => 'kicad_pcbnew']); + $project = new Project(); + $bom = $this->service->stringToBOMEntries($project, $input, ['type' => 'kicad_pcbnew']); $this->assertContainsOnlyInstancesOf(ProjectBOMEntry::class, $bom); $this->assertCount(4, $bom); @@ -126,7 +130,8 @@ public function testStringToBOMEntriesKiCADPCBError(): void $this->expectException(\UnexpectedValueException::class); - $this->service->stringToBOMEntries($input, ['type' => 'kicad_pcbnew']); + $project = new Project(); + $this->service->stringToBOMEntries($project, $input, ['type' => 'kicad_pcbnew']); } public function testDetectFields(): void @@ -370,7 +375,8 @@ public function testStringToBOMEntriesKiCADSchematic(): void 'Mouser SPN' => 'Mouser SPN' ]; - $bom_entries = $this->service->stringToBOMEntries($input, [ + $project = new Project(); + $bom_entries = $this->service->stringToBOMEntries($project, $input, [ 'type' => 'kicad_schematic', 'field_mapping' => $field_mapping, 'delimiter' => ',' @@ -413,7 +419,8 @@ public function testStringToBOMEntriesKiCADSchematicWithPriority(): void 'MPN2' => 2 ]; - $bom_entries = $this->service->stringToBOMEntries($input, [ + $project = new Project(); + $bom_entries = $this->service->stringToBOMEntries($project, $input, [ 'type' => 'kicad_schematic', 'field_mapping' => $field_mapping, 'field_priorities' => $field_priorities, @@ -451,7 +458,8 @@ public function testStringToBOMEntriesKiCADSchematicWithPartDBID(): void 'Quantity' => 'Quantity' ]; - $bom_entries = $this->service->stringToBOMEntries($input, [ + $project = new Project(); + $bom_entries = $this->service->stringToBOMEntries($project, $input, [ 'type' => 'kicad_schematic', 'field_mapping' => $field_mapping, 'delimiter' => ',' @@ -483,7 +491,8 @@ public function testStringToBOMEntriesKiCADSchematicWithInvalidPartDBID(): void 'Quantity' => 'Quantity' ]; - $bom_entries = $this->service->stringToBOMEntries($input, [ + $project = new Project(); + $bom_entries = $this->service->stringToBOMEntries($project, $input, [ 'type' => 'kicad_schematic', 'field_mapping' => $field_mapping, 'delimiter' => ',' @@ -512,7 +521,8 @@ public function testStringToBOMEntriesKiCADSchematicMergeDuplicates(): void 'Quantity' => 'Quantity' ]; - $bom_entries = $this->service->stringToBOMEntries($input, [ + $project = new Project(); + $bom_entries = $this->service->stringToBOMEntries($project, $input, [ 'type' => 'kicad_schematic', 'field_mapping' => $field_mapping, 'delimiter' => ',' @@ -541,7 +551,8 @@ public function testStringToBOMEntriesKiCADSchematicMissingRequired(): void $this->expectException(\UnexpectedValueException::class); $this->expectExceptionMessage('Required field "Designator" is missing or empty'); - $this->service->stringToBOMEntries($input, [ + $project = new Project(); + $this->service->stringToBOMEntries($project, $input, [ 'type' => 'kicad_schematic', 'field_mapping' => $field_mapping, 'delimiter' => ',' @@ -564,7 +575,8 @@ public function testStringToBOMEntriesKiCADSchematicQuantityMismatch(): void $this->expectException(\UnexpectedValueException::class); $this->expectExceptionMessage('Mismatch between quantity and component references'); - $this->service->stringToBOMEntries($input, [ + $project = new Project(); + $this->service->stringToBOMEntries($project, $input, [ 'type' => 'kicad_schematic', 'field_mapping' => $field_mapping, 'delimiter' => ',' @@ -585,7 +597,8 @@ public function testStringToBOMEntriesKiCADSchematicWithBOM(): void 'Quantity' => 'Quantity' ]; - $bom_entries = $this->service->stringToBOMEntries($input, [ + $project = new Project(); + $bom_entries = $this->service->stringToBOMEntries($project, $input, [ 'type' => 'kicad_schematic', 'field_mapping' => $field_mapping, 'delimiter' => ',' diff --git a/tests/Twig/EntityExtensionTest.php b/tests/Twig/EntityExtensionTest.php index 3adb9ad27..9780739c2 100644 --- a/tests/Twig/EntityExtensionTest.php +++ b/tests/Twig/EntityExtensionTest.php @@ -22,6 +22,7 @@ */ namespace App\Tests\Twig; +use App\Entity\AssemblySystem\Assembly; use App\Entity\Attachments\PartAttachment; use App\Entity\ProjectSystem\Project; use App\Entity\LabelSystem\LabelProfile; @@ -60,6 +61,7 @@ public function testGetEntityType(): void $this->assertSame('manufacturer', $this->service->getEntityType(new Manufacturer())); $this->assertSame('category', $this->service->getEntityType(new Category())); $this->assertSame('device', $this->service->getEntityType(new Project())); + $this->assertSame('assembly', $this->service->getEntityType(new Assembly())); $this->assertSame('attachment', $this->service->getEntityType(new PartAttachment())); $this->assertSame('supplier', $this->service->getEntityType(new Supplier())); $this->assertSame('user', $this->service->getEntityType(new User())); diff --git a/translations/messages.cs.xlf b/translations/messages.cs.xlf index 1f234450e..2f8c48fe9 100644 --- a/translations/messages.cs.xlf +++ b/translations/messages.cs.xlf @@ -351,6 +351,24 @@ Exportovat všechny prvky + + + export.readable.label + Čitelný export + + + + + export.readable + CSV + + + + + export.readable_bom + PDF + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:185 @@ -4741,7 +4759,7 @@ Pokud jste to provedli nesprávně nebo pokud počítač již není důvěryhodn Název - + Part-DB1\src\DataTables\PartsDataTable.php:178 Part-DB1\src\DataTables\PartsDataTable.php:126 @@ -9864,6 +9882,48 @@ Element 3 Archivováno + + + assembly.edit.status + Stav sestavy + + + + + assembly.edit.ipn + Interní číslo dílu (IPN) + + + + + assembly.status.draft + Návrh + + + + + assembly.status.planning + Plánování + + + + + assembly.status.in_production + Ve výrobě + + + + + assembly.status.finished + Dokončeno + + + + + assembly.status.archived + Archivováno + + part.new_build_part.error.build_part_already_exists @@ -10212,7 +10272,7 @@ Element 3 Cílový inventář - + project.builds.number_of_builds Množství sestavy @@ -11010,6 +11070,18 @@ Element 3 Typ + + + project.bom_import.type.json + JSON + + + + + project.bom_import.type.csv + CSV + + project.bom_import.type.kicad_pcbnew @@ -11028,6 +11100,319 @@ Element 3 Výběrem této možnosti odstraníte všechny existující položky BOM v projektu a přepíšete je importovaným souborem BOM! + + + project.import_bom.template.header.json + Šablona importu JSON + + + + + project.import_bom.template.header.csv + Šablona importu CSV + + + + + project.import_bom.template.header.kicad_pcbnew + Šablona importu CSV (KiCAD Pcbnew BOM) + + + + + project.bom_import.template.entry.name + Název komponenty v projektu + + + + + project.bom_import.template.entry.part.mpnr + Jedinečné číslo produktu u výrobce + + + + + project.bom_import.template.entry.part.ipn + Jedinečné IPN součásti + + + + + project.bom_import.template.entry.part.name + Jedinečný název součásti + + + + + project.bom_import.template.entry.part.manufacturer.name + Jedinečný název výrobce + + + + + project.bom_import.template.json.table + + + + + Pole + Podmínka + Datový typ + Popis + + + + + quantity + Povinné + Desetinné číslo (Float) + Musí být zadáno a obsahovat desetinnou hodnotu (Float), která je větší než 0.0. + + + name + Volitelné + Řetězec (String) + Pokud je přítomen, musí být neprázdný řetězec. Název položky v kusovníku. + + + part + Volitelné + Objekt/Array + + Pokud je potřeba přiřadit součástku, musí to být objekt/pole a musí být vyplněno alespoň jedno z následujících polí: +
    +
  • part.id
  • +
  • part.mpnr
  • +
  • part.ipn
  • +
  • part.name
  • +
+ + + + part.id + Volitelné + Celé číslo (Integer) + Celé číslo (Integer) > 0. Odpovídá internímu číselnému ID součástky v Part-DB. + + + part.mpnr + Volitelné + Řetězec (String) + Neprázdný řetězec, pokud není uvedeno part.id, part.ipn nebo part.name. + + + part.ipn + Volitelné + Řetězec (String) + Neprázdný řetězec, pokud není uvedeno part.id, part.mpnr nebo part.name. + + + part.name + Volitelné + Řetězec (String) + Neprázdný řetězec, pokud není uvedeno part.id, part.mpnr nebo part.ipn. + + + part.manufacturer + Volitelné + Objekt/Array + + Pokud má být upraven výrobce součástky nebo pokud má být součástka nalezena jednoznačně na základě part.mpnr, musí to být objekt/pole a musí být vyplněno alespoň jedno z následujících polí: +
    +
  • manufacturer.id
  • +
  • manufacturer.name
  • +
+ + + + manufacturer.id + Volitelné + Celé číslo (Integer) + Celé číslo (Integer) > 0. Odpovídá internímu číselnému ID výrobce. + + + manufacturer.name + Volitelné + Řetězec (String) + Neprázdný řetězec, pokud není uvedeno manufacturer.id. + + + + ]]> +
+
+
+ + + project.bom_import.template.csv.exptected_columns + Možné sloupce: + + + + + project.bom_import.template.csv.table + + + + + Sloupec + Podmínka + Datový typ + Popis + + + + + quantity + Povinné + Desetinné číslo (Float) + Musí být uvedeno a obsahovat hodnotu desetinného čísla (Float) větší než 0.0. + + + name + Optional + String + Název položky v kusovníku. + + + Sloupce začínající part_ + + Pokud má být přiřazena součástka, musí být uveden a vyplněn alespoň jeden z následujících sloupců: +
    +
  • part_id
  • +
  • part_mpnr
  • +
  • part_ipn
  • +
  • part_name
  • +
+ + + + part_id + Volitelné + Celé číslo (Integer) + Celé číslo (Integer) > 0. Odpovídá internímu číselnému ID součástky v Part-DB. + + + part_mpnr + Volitelné + Řetězec (String) + Musí být uvedeno, pokud nejsou vyplněny sloupce part_id, part_ipn nebo part_name. + + + part_ipn + Volitelné + Řetězec (String) + Musí být uvedeno, pokud nejsou vyplněny sloupce part_id, part_mpnr nebo part_name. + + + part_name + Volitelné + Řetězec (String) + Musí být uvedeno, pokud nejsou vyplněny sloupce part_id, part_mpnr nebo part_ipn. + + + Sloupce začínající part_manufacturer_ + + Pokud má být upraven výrobce dílu nebo má být díl jednoznačně identifikován podle hodnoty part_mpnr, musí být uveden a vyplněn alespoň jeden z následujících sloupců: +
    +
  • part_manufacturer_id
  • +
  • part_manufacturer_name
  • +
+ + + + part_manufacturer_id + Volitelné + Celé číslo (Integer) + Celé číslo (Integer) > 0. Odpovídá internímu číselnému ID výrobce. + + + part_manufacturer_name + Volitelné + Řetězec (String) + Musí být uvedeno, pokud není vyplněn sloupec part_manufacturer_id. + + + + ]]> +
+
+
+ + + project.bom_import.template.kicad_pcbnew.exptected_columns + Očekávané sloupce: + + + + + project.bom_import.template.kicad_pcbnew.exptected_columns.note + + Poznámka: Nedochází k přiřazení ke konkrétním součástkám ze správy kategorií.

+ ]]> +
+
+
+ + + project.bom_import.template.kicad_pcbnew.table + + + + + Pole + Podmínka + Datový typ + Popis + + + + + Id + Volitelné + Celé číslo (Integer) + Volný údaj. Jedinečné identifikační číslo pro každou součástku. + + + Designator + Volitelné + Řetězec (String) + Volný údaj. Jedinečný referenční označovač součástky na desce plošných spojů, např. „R1“ pro odpor 1.
Je převzat do osazovacího názvu záznamu součástky. + + + Package + Volitelné + Řetězec (String) + Volný údaj. Pouzdro nebo tvar součástky, např. „0805“ pro SMD odpory.
Pro záznam součástky není převzato. + + + Quantity + Povinné pole + Celé číslo (Integer) + Počet identických komponent, které jsou potřebné k vytvoření instance.
Je převzat jako počet položky komponenty. + + + Designation + Povinné pole + Řetězec (String) + Popis nebo funkce součástky, např. hodnota odporu „10kΩ“ nebo kapacita kondenzátoru „100nF“.
Je převzato do názvu záznamu součástky. + + + Supplier and ref + Volitelné + Řetězec (String) + Volný údaj. Může obsahovat např. distribuční specifickou hodnotu.
Je převzato jako poznámka ke záznamu součástky. + + + + ]]> +
+
+
project.bom_import.flash.invalid_file @@ -12765,6 +13150,30 @@ Vezměte prosím na vědomí, že se nemůžete vydávat za uživatele se zakáz Sloupce, které se mají ve výchozím nastavení zobrazovat v částečných tabulkách. Pořadí položek lze změnit pomocí funkce drag & drop. + + + settings.behavior.table.assemblies_default_columns + Výchozí sloupce pro tabulky sestav + + + + + settings.behavior.table.assemblies_default_columns.help + Sloupce, které by měly být zobrazeny ve výchozím nastavení v tabulkách sestav. Pořadí prvků lze změnit přetažením. + + + + + settings.behavior.table.assemblies_bom_default_columns + Výchozí sloupce pro kusovníky sestav + + + + + settings.behavior.table.assemblies_bom_default_columns.help + Sloupce, které by měly být zobrazeny ve výchozím nastavení v kusovnících sestav. Pořadí prvků lze změnit přetažením. + + settings.ips.oemsecrets @@ -12975,6 +13384,18 @@ Vezměte prosím na vědomí, že se nemůžete vydávat za uživatele se zakáz Pokud potřebujete směnné kurzy mezi měnami mimo eurozónu, můžete zde zadat API klíč z fixer.io. + + + settings.misc.assembly + Sestavy + + + + + settings.misc.assembly.useIpnPlaceholderInName + Použít zástupný symbol %%ipn%% v názvu sestavy. Zástupný symbol bude při ukládání nahrazen vstupem IPN. + + settings.behavior.part_info @@ -13035,6 +13456,725 @@ Vezměte prosím na vědomí, že se nemůžete vydávat za uživatele se zakáz Z bezpečnostních důvodů redigováno + + + part.table.name.value.for_part + %value% (Součást) + + + + + part.table.name.value.for_assembly + %value% (Sestava) + + + + + part.table.name.value.for_project + %value% (Projekt) + + + + + assembly.label + Sestava + + + + + assembly.caption + Sestava + + + + + perm.assemblies + Sestavy + + + + + assembly_bom_entry.label + Součásti + + + + + assembly.labelp + Sestavy + + + + + assembly.referencedAssembly.labelp + Odkazované sestavy + + + + + assembly.edit + Upravit sestavu + + + + + assembly.new + Nová sestava + + + + + assembly.edit.bom.import_bom + Importovat součásti + + + + + log.database_updated.failed + __log.database_updated.failed + + + + + log.database_updated.old_version + __log.database_updated.old_version + + + + + log.database_updated.new_version + __log.database_updated.new_version + + + + + tree.tools.edit.assemblies + Sestavy + + + + + assembly.bom_import.flash.success + %count% součástí úspěšně importováno do sestavy. + + + + + assembly.bom_import.flash.invalid_entries + Chyba ověření! Zkontrolujte svůj importovaný soubor! + + + + + assembly.bom_import.flash.invalid_file + Soubor nelze importovat. Zkontrolujte, zda jste vybrali správný typ souboru. Chybová zpráva: %message% + + + + + assembly.bom.quantity + Množství + + + + + assembly.bom.mountnames + Názvy osazení + + + + + assembly.bom.designator + Referenční označení + + + + + assembly.bom.designator.help + Volná referenční označení (designator) + + + + + assembly.bom.instockAmount + Stav na skladě + + + + + assembly.info.title + Info o sestavě + + + + + assembly.info.info.label + Informace + + + + + assembly.info.sub_assemblies.label + Podskupina + + + + + assembly.info.builds.label + Sestavení + + + + + assembly.info.bom_add_parts + Přidat součásti + + + + + assembly.info.bom_entries_count + Součásti + + + + + assembly.info.sub_assemblies_count + Podskupiny + + + + + assembly.bom.delete.confirm + Opravdu chcete tuto položku smazat? + + + + + assembly.add_parts_to_assembly + Přidat součásti do sestavy + + + + + part.info.add_part_to_assembly + Přidat tuto součástku do sestavy + + + + + assembly.bom.project + Projekt + + + + + assembly.bom.referencedAssembly + Sestava + + + + + assembly.bom.name + Název + + + + + assembly.bom.name.help + Člověkem čitelný název položky kusovníku + + + + + assembly.bom.comment + Poznámky + + + + + assembly.import_bom + Importovat součásti do sestavy + + + + + assembly.bom.partOrAssembly + Součást nebo sestava + + + + + assembly.bom.identifiers + Identifikátory + + + + + assembly.bom.add_entry + Přidat položku + + + + + assembly.bom.price + Cena + + + + + assembly.bom_import.type + Typ + + + + + assembly.bom_import.type.json + JSON pro sestavu + + + + + assembly.bom_import.type.csv + CSV pro sestavu + + + + + assembly.bom_import.type.kicad_pcbnew + CSV (KiCAD Pcbnew BOM) + + + + + assembly.bom_import.type.kicad_schematic + KiCAD Schématický editor BOM (CSV soubor) + + + + + assembly.bom_import.clear_existing_bom + Smazat existující položky před importem + + + + + assembly.bom_import.clear_existing_bom.help + Pokud je tato možnost vybrána, budou všechny již existující součásti sestavy smazány a nahrazeny importovanými daty součástí. + + + + + assembly.import_bom.template.header.json + Šablona importu JSON pro sestavu + + + + + assembly.import_bom.template.header.csv + Importní šablona CSV pro sestavu + + + + + assembly.import_bom.template.header.kicad_pcbnew + Šablona importu CSV (KiCAD Pcbnew BOM) pro sestavu + + + + + assembly.bom_import.template.entry.name + Název součásti v sestavě + + + + + assembly.bom_import.template.entry.part.mpnr + Unikátní číslo produktu u výrobce + + + + + assembly.bom_import.template.entry.part.ipn + Unikátní IPN součásti + + + + + assembly.bom_import.template.entry.part.name + Unikátní název součásti + + + + + assembly.bom_import.template.entry.part.manufacturer.name + Unikátní jméno výrobce + + + + + assembly.bom_import.template.entry.part.category.name + Unikátní název kategorie + + + + + assembly.bom_import.template.json.table + + + + + Pole + Podmínka + Datový typ + Popis + + + + + quantity + Povinné pole + Číslo s plovoucí desetinnou čárkou (Float) + Musí být vyplněno a obsahovat číselnou hodnotu (Float) větší než 0.0. + + + name + Volitelné + Řetězec + Pokud je uvedeno, musí být neprázdný text. Název položky ve skupině. + + + part + Volitelné + Objekt/Array + + Pokud má být přiřazena součástka, musí být objektem/arrayem a alespoň jedno z následujících polí musí být vyplněno: +
    +
  • part.id
  • +
  • part.mpnr
  • +
  • part.ipn
  • +
  • part.name
  • +
+ + + + part.id + Volitelné + Celé číslo (Integer) + Celé číslo > 0. Odpovídá internímu číselnému ID součástky v databázi. + + + part.mpnr + Volitelné + Řetězec + Neprázdný text, pokud není vyplněno part.id, part.ipn ani part.name. + + + part.ipn + Volitelné + Řetězec + Neprázdný text, pokud není vyplněno part.id, part.mpnr ani part.name. + + + part.name + Volitelné + Řetězec + Neprázdný text, pokud není vyplněno part.id, part.mpnr ani part.ipn. + + + part.description + Volitelné + Řetězec nebo null + Pokud je uvedeno, musí být neprázdný řetězec nebo null. Přepíše stávající hodnotu v součástce. + + + part.manufacturer + Volitelné + Objekt/Array + + Pokud má být výrobce součástky upraven nebo má být součástka jednoznačně identifikována pomocí hodnoty part.mpnr, musí být objektem/arrayem a alespoň jedno z následujících polí musí být vyplněno: +
    +
  • manufacturer.id
  • +
  • manufacturer.name
  • +
+ + + + manufacturer.id + Volitelné + Celé číslo (Integer) + Celé číslo > 0. Odpovídá internímu číselnému ID výrobce. + + + manufacturer.name + Volitelné + Řetězec + Neprázdný text, pokud není uveden manufacturer.id. + + + part.category + Volitelné + Objekt/Array + + Pokud má být kategorie součástky upravena, musí být objektem/arrayem a alespoň jedno z následujících polí musí být vyplněno: +
    +
  • category.id
  • +
  • category.name
  • +
+ + + + category.id + Volitelné + Celé číslo (Integer) + Celé číslo > 0. Odpovídá internímu číselnému ID kategorie součástky. + + + category.name + Volitelné + Řetězec + Neprázdný text, pokud není uvedeno category.id. + + + + ]]> +
+
+
+ + + assembly.bom_import.template.csv.exptected_columns + Možné sloupce: + + + + + assembly.bom_import.template.csv.table + + + + + Sloupec + Podmínka + Datový typ + Popis + + + + + quantity + Povinné pole + Číslo s plovoucí desetinnou čárkou (Float) + Musí být vyplněno a obsahovat číselnou hodnotu (Float) větší než 0.0. + + + name + Volitelné + Řetězec + Název položky ve skupině. + + + Sloupce začínající part_ + + Pokud má být přiřazena součástka, jeden z následujících sloupců musí být uveden a vyplněn: +
    +
  • part_id
  • +
  • part_mpnr
  • +
  • part_ipn
  • +
  • part_name
  • +
+ + + + part_id + Volitelné + Celé číslo (Integer) + Celé číslo > 0. Odpovídá internímu číselnému ID součástky v databázi. + + + part_mpnr + Volitelné + Řetězec + Musí být uvedeno, pokud nejsou vyplněny sloupce part_id, part_ipn nebo part_name. + + + part_ipn + Volitelné + Řetězec + Musí být uvedeno, pokud nejsou vyplněny sloupce part_id, part_mpnr nebo part_name. + + + part_name + Volitelné + Řetězec + Musí být uvedeno, pokud nejsou vyplněny sloupce part_id, part_mpnr nebo part_ipn. + + + part_description + Volitelné + Řetězec + Bude přeneseno do součástky a přepíše aktuální hodnotu, pokud je uveden neprázdný text. + + + Sloupce začínající part_manufacturer_ + + Pokud má být výrobce upraven nebo součástka jednoznačně identifikována pomocí part_mpnr, jeden z následujících sloupců musí být uveden a vyplněn: +
    +
  • part_manufacturer_id
  • +
  • part_manufacturer_name
  • +
+ + + + part_manufacturer_id + Volitelné + Celé číslo (Integer) + Celé číslo > 0. Odpovídá internímu číselnému ID výrobce. + + + part_manufacturer_name + Volitelné + Řetězec + Musí být uvedeno, pokud není vyplněn sloupec part_manufacturer_id. + + + Sloupce začínající part.category_ + + Pokud má být kategorie upravena, jeden z následujících sloupců musí být uveden a vyplněn: +
    +
  • part_category_id
  • +
  • part_category_name
  • +
+ + + + part_category_id + Volitelné + Celé číslo (Integer) + Celé číslo > 0. Odpovídá internímu číselnému ID kategorie součástky. + + + part_category_name + Volitelné + Řetězec + Musí být uvedeno, pokud není vyplněn sloupec part_category_id. + + + + ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.exptected_columns + Očekávané sloupce: + + + + + assembly.bom_import.template.kicad_pcbnew.exptected_columns.note + + Poznámka: Neprobíhá přiřazení ke konkrétním součástem ze správy kategorií.

+ ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.table + + + + + Pole + Podmínka + Datový typ + Popis + + + + + Id + Volitelné + Celé číslo + Volné pole. Unikátní identifikační číslo pro každou součástku. + + + Designator + Volitelné + Řetězec + Volné pole. Unikátní referenční označení součástky na PCB, např. „R1“ pro rezistor 1.
Používá se pro název umístění v rámci součástkové skupiny. + + + Package + Volitelné + Řetězec + Volné pole. Pouzdro nebo formát součástky, např. „0805“ pro SMD rezistory.
Není použito pro záznam součástky v rámci sestavy. + + + Quantity + Povinné pole + Celé číslo + Počet identických součástek potřebných k vytvoření jedné instance sestavy.
Použito jako počet záznamu součástky v rámci sestavy. + + + Designation + Povinné pole + Řetězec + Popis nebo funkce součástky, např. hodnota rezistoru „10kΩ“ nebo hodnota kondenzátoru „100nF“.
Použito jako název záznamu součástky v rámci sestavy. + + + Supplier and ref + Volitelné + Řetězec + Volné pole. Může obsahovat např. specifické informace o distributorovi.
Používá se jako poznámka k záznamu součástky v rámci sestavy. + + + + ]]> +
+
+
+ + + typeahead.parts.part.name + %name% (součást) + + + + + typeahead.parts.assembly.name + %name% (sestava) + + + + + projects.build.form.part + Součást "%name%" + + + + + projects.build.form.assembly + Sestava "%name%" + + + + + projects.build.form.assembly.bom.entry + %name% (potřebné množství: %quantity%) + + + + + projects.build.form.assembly.bom.entry.no.stock + není skladem + + project.bom_import.map_fields @@ -13479,5 +14619,221 @@ Vezměte prosím na vědomí, že se nemůžete vydávat za uživatele se zakáz Minimální šířka náhledu (px) + + + assembly_list.all.title + Všechny sestavy + + + + + assembly.edit.tab.common + Obecné + + + + + assembly.edit.tab.advanced + Pokročilé možnosti + + + + + assembly.edit.tab.attachments + Přílohy + + + + + assembly.filter.dbId + ID databáze + + + + + assembly.filter.ipn + Interní číslo dílu (IPN) + + + + + assembly.filter.name + Název + + + + + assembly.filter.description + Popis + + + + + assembly.filter.comment + Poznámky + + + + + assembly.filter.attachments_count + Počet příloh + + + + + assembly.filter.attachmentName + Název přílohy + + + + + assemblies.create.btn + Vytvořit novou sestavu + + + + + assembly.table.id + ID + + + + + assembly.table.name + Název + + + + + assembly.table.ipn + IPN + + + + + assembly.table.description + Popis + + + + + assembly.table.referencedAssemblies + Referenceované sestavy + + + + + assembly.table.addedDate + Přidáno + + + + + assembly.table.lastModified + Naposledy upraveno + + + + + assembly.table.edit + Upravit + + + + + assembly.table.edit.title + Upravit sestavu + + + + + assembly.table.invalid_regex + Neplatný regulární výraz (regex) + + + + + assembly.bom.table.id + ID + + + + + assembly.bom.table.name + Název + + + + + assembly.bom.table.quantity + Množství + + + + + assembly.bom.table.ipn + IPN + + + + + assembly.bom.table.description + Popis + + + + + assembly.bom.table.category + Kategorie + + + + + assembly.bom.table.manufacturer + Výrobce + + + + + assembly.bom.table.designator + Referenční označení + + + + + assembly.bom.table.mountnames + Názvy osazení + + + + + assembly.bom.table.storage_location + Skladové umístění + + + + + assembly.bom.table.amount + Množství + + + + + assembly.bom.table.addedDate + Vytvořeno + + + + + assembly.bom.table.lastModified + Naposledy změněno + + + + + assembly.bom.table.edit + Upravit + + diff --git a/translations/messages.da.xlf b/translations/messages.da.xlf index d72589864..36c6af058 100644 --- a/translations/messages.da.xlf +++ b/translations/messages.da.xlf @@ -351,6 +351,24 @@ Eksportér alle elementer
+ + + export.readable.label + Læsbar eksport + + + + + export.readable + CSV + + + + + export.readable_bom + PDF + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:185 @@ -9890,6 +9908,48 @@ Element 3 Arkiveret + + + assembly.edit.status + Samlingens status + + + + + assembly.edit.ipn + Internt Partnummer (IPN) + + + + + assembly.status.draft + Kladde + + + + + assembly.status.planning + Under planlægning + + + + + assembly.status.in_production + I produktion + + + + + assembly.status.finished + Ophørt + + + + + assembly.status.archived + Arkiveret + + part.new_build_part.error.build_part_already_exists @@ -11042,6 +11102,18 @@ Oversættelsen Typ + + + project.bom_import.type.json + JSON + + + + + project.bom_import.type.csv + CSV + + project.bom_import.type.kicad_pcbnew @@ -11054,6 +11126,319 @@ Oversættelsen let eksisterende styklisteposter før import + + + project.import_bom.template.header.json + JSON-importskabelon + + + + + project.import_bom.template.header.csv + CSV-importskabelon + + + + + project.import_bom.template.header.kicad_pcbnew + CSV-importskabelon (KiCAD Pcbnew BOM) + + + + + project.bom_import.template.entry.name + Komponentens navn i projektet + + + + + project.bom_import.template.entry.part.mpnr + Unikt produktnummer hos producenten + + + + + project.bom_import.template.entry.part.ipn + Komponentens unikke IPN + + + + + project.bom_import.template.entry.part.name + Komponentens unikke navn + + + + + project.bom_import.template.entry.part.manufacturer.name + Producentens unikke navn + + + + + project.bom_import.template.json.table + + + + + Felt + Betingelse + Datatype + Beskrivelse + + + + + quantity + Obligatorisk + Decimaltal (Float) + Skal være angivet og skal indeholde en decimaltalsværdi (Float), der er større end 0.0. + + + name + Valgfrit + String + Hvis til stede, skal det være en ikke-tom streng. Navnet på posten i stykliste. + + + part + Valgfrit + Objekt/Array + + Hvis en komponent skal knyttes, skal det være et objekt/array, og mindst ét af felterne skal udfyldes: +
    +
  • part.id
  • +
  • part.mpnr
  • +
  • part.ipn
  • +
  • part.name
  • +
+ + + + part.id + Valgfrit + Heltal (Integer) + Heltal (Integer) > 0. Svarer til det interne numeriske ID for komponenten i Part-DB. + + + part.mpnr + Valgfrit + String + En ikke-tom streng, hvis hverken part.id, part.ipn eller part.name er angivet. + + + part.ipn + Valgfrit + String + En ikke-tom streng, hvis hverken part.id, part.mpnr eller part.name er angivet. + + + part.name + Valgfrit + String + En ikke-tom streng, hvis hverken part.id, part.mpnr eller part.ipn er angivet. + + + part.manufacturer + Valgfrit + Objekt/Array + + Hvis en komponents producent skal justeres, eller hvis komponenten skal findes entydigt via part.mpnr, skal det være et objekt/array, og mindst ét af felterne skal udfyldes: +
    +
  • manufacturer.id
  • +
  • manufacturer.name
  • +
+ + + + manufacturer.id + Valgfrit + Heltal (Integer) + Heltal (Integer) > 0. Svarer til producentens interne numeriske ID. + + + manufacturer.name + Valgfrit + String + En ikke-tom streng, hvis manufacturer.id ikke er angivet. + + + + ]]> +
+
+
+ + + project.bom_import.template.csv.exptected_columns + Mulige kolonner: + + + + + project.bom_import.template.csv.table + + + + + Kolonne + Betingelse + Datatype + Beskrivelse + + + + + quantity + Obligatorisk + Decimaltal (Float) + Skal være angivet og indeholde en decimaltalsværdi (Float), som er større end 0,0. + + + name + Optional + String + Hvis tilgængelig, skal det være en ikke-tom streng. Navnet på elementet inden for stykliste. + + + Kolonner, der begynder med part_ + + Hvis en komponent skal tildeles, skal mindst én af følgende kolonner være angivet og udfyldt: +
    +
  • part_id
  • +
  • part_mpnr
  • +
  • part_ipn
  • +
  • part_name
  • +
+ + + + part_id + Valgfri + Heltal (Integer) + Heltal (Integer) > 0. Svarer til den interne numeriske ID for komponenten i Part-DB. + + + part_mpnr + Valgfri + Streng (String) + Skal angives, hvis kolonnerne part_id, part_ipn eller part_name ikke er udfyldt. + + + part_ipn + Valgfri + Streng (String) + Skal angives, hvis kolonnerne part_id, part_mpnr eller part_name ikke er udfyldt. + + + part_name + Valgfri + Streng (String) + Skal angives, hvis kolonnerne part_id, part_mpnr eller part_ipn ikke er udfyldt. + + + Kolonner, der begynder med part_manufacturer_ + + Hvis komponentens producent skal ændres eller identificeres entydigt baseret på part_mpnr, skal mindst én af følgende kolonner være angivet og udfyldt: +
    +
  • part_manufacturer_id
  • +
  • part_manufacturer_name
  • +
+ + + + part_manufacturer_id + Valgfri + Heltal (Integer) + Heltal (Integer) > 0. Svarer til den interne numeriske ID for producenten. + + + part_manufacturer_name + Valgfri + Streng (String) + Skal angives, hvis kolonnen part_manufacturer_id ikke er udfyldt. + + + + ]]> +
+
+
+ + + project.bom_import.template.kicad_pcbnew.exptected_columns + Forventede kolonner: + + + + + project.bom_import.template.kicad_pcbnew.exptected_columns.note + + Bemærk: Der sker ingen tilknytning til specifikke komponenter fra kategoristyringen.

+ ]]> +
+
+
+ + + project.bom_import.template.kicad_pcbnew.table + + + + + Felt + Betingelse + Datatype + Beskrivelse + + + + + Id + Valgfrit + Heltal (Integer) + Fri opgave. Et entydigt identifikationsnummer for hver komponent. + + + Designator + Valgfrit + Streng (String) + Fri opgave. En entydig referencemarkering for komponenten på PCB'et, fx "R1" for modstand 1.
Bliver overført til monteringsnavnet på komponentindgangen. + + + Package + Valgfrit + Streng (String) + Fri opgave. Komponentens pakning eller form, fx "0805" for SMD-modstande.
Bliver ikke overført til komponentindgangen. + + + Quantity + Obligatorisk felt + Heltal (Integer) + Antallet af identiske komponenter, der kræves for at oprette en instans.
Overtages som antallet af komponentposter. + + + Designation + Obligatorisk felt + Streng (String) + Beskrivelse eller funktion af komponenten, fx modstandsværdi "10kΩ" eller kondensatorværdi "100nF".
Bliver overført til komponentindgangens navn. + + + Supplier and ref + Valgfrit + Streng (String) + Fri opgave. Kan eksempelvis indeholde en distributørspecifik værdi.
Bliver overført som en note til komponentindgangen. + + + + ]]> +
+
+
project.bom_import.clear_existing_bom.help @@ -12196,5 +12581,904 @@ Bemærk venligst, at du ikke kan kopiere fra deaktiveret bruger. Hvis du prøver Du forsøgte at fjerne/tilføje en mængde sat til nul! Der blev ikke foretaget nogen handling. + + + part.table.name.value.for_part + %value% (Del) + + + + + part.table.name.value.for_assembly + %value% (Samling) + + + + + part.table.name.value.for_project + %value% (Projekt) + + + + + assembly.label + Samling + + + + + assembly.caption + Samling + + + + + perm.assemblies + Samlinger + + + + + assembly_bom_entry.label + Komponenter + + + + + assembly.labelp + Samlinger + + + + + assembly.referencedAssembly.labelp + Refererede samlinger + + + + + assembly.edit + Rediger samling + + + + + assembly.new + Ny samling + + + + + assembly.edit.bom.import_bom + Importér komponenter + + + + + log.database_updated.failed + __log.database_updated.failed + + + + + log.database_updated.old_version + __log.database_updated.old_version + + + + + log.database_updated.new_version + __log.database_updated.new_version + + + + + tree.tools.edit.assemblies + Samlinger + + + + + assembly.bom_import.flash.success + %count% komponent(er) blev importeret til samlingen med succes. + + + + + assembly.bom_import.flash.invalid_entries + Valideringsfejl! Kontroller venligst den importerede fil! + + + + + assembly.bom_import.flash.invalid_file + Filen kunne ikke importeres. Kontrollér, at du har valgt den korrekte filtype. Fejlmeddelelse: %message% + + + + + assembly.bom.quantity + Mængde + + + + + assembly.bom.mountnames + Monteringsnavne + + + + + assembly.bom.designator + Referencebetegnelse + + + + + assembly.bom.designator.help + Frie referencebetegnelser (designator) + + + + + assembly.bom.instockAmount + Antal på lager + + + + + assembly.info.title + Samleinfo + + + + + assembly.info.info.label + Info + + + + + assembly.info.sub_assemblies.label + Undergruppe + + + + + assembly.info.builds.label + Byggeri + + + + + assembly.info.bom_add_parts + Tilføj dele + + + + + assembly.info.bom_entries_count + Komponenter + + + + + assembly.info.sub_assemblies_count + Undergrupper + + + + + assembly.bom.delete.confirm + Vil du virkelig slette denne post? + + + + + assembly.add_parts_to_assembly + Tilføj dele til samlingen + + + + + part.info.add_part_to_assembly + Tilføj denne del til en samling + + + + + assembly.bom.project + Projekt + + + + + assembly.bom.referencedAssembly + Sammenstilling + + + + + assembly.bom.name + Navn + + + + + assembly.bom.name.help + Menneskelæselig titel på styklisteposten + + + + + assembly.bom.comment + Notater + + + + + assembly.import_bom + Importer dele til samling + + + + + assembly.bom.partOrAssembly + Del eller samling + + + + + assembly.bom.identifiers + Identifikatorer + + + + + assembly.bom.add_entry + Tilføj post + + + + + assembly.bom.price + Pris + + + + + assembly.bom_import.type + Type + + + + + assembly.bom_import.type.json + JSON for en samling + + + + + assembly.bom_import.type.csv + CSV til en samling + + + + + assembly.bom_import.type.kicad_pcbnew + CSV (KiCAD Pcbnew BOM) + + + + + assembly.bom_import.type.kicad_schematic + KiCAD Skematisk editor BOM (CSV-fil) + + + + + assembly.bom_import.clear_existing_bom + Slet eksisterende poster før import + + + + + assembly.bom_import.clear_existing_bom.help + Hvis dette valg er markeret, slettes alle eksisterende komponentposter i samlingen og erstattes med de importerede. + + + + + assembly.import_bom.template.header.json + JSON-importskabelon til en samling + + + + + assembly.import_bom.template.header.csv + Importskabelon CSV til en samling + + + + + assembly.import_bom.template.header.kicad_pcbnew + Importskabelon CSV (KiCAD Pcbnew BOM) til en samling + + + + + assembly.bom_import.template.entry.name + Delens navn i samlingen + + + + + assembly.bom_import.template.entry.part.mpnr + Unik produktnummer hos producenten + + + + + assembly.bom_import.template.entry.part.ipn + Unik IPN for delen + + + + + assembly.bom_import.template.entry.part.name + Unikt komponentnavn + + + + + assembly.bom_import.template.entry.part.manufacturer.name + Unikt producenter navn + + + + + assembly.bom_import.template.entry.part.category.name + Kategoriens unikke navn + + + + + assembly.bom_import.template.json.table + + + + + Felt + Betingelse + Datatype + Beskrivelse + + + + + quantity + Påkrævet felt + Flydende punkt-tal (Float) + Skal være udfyldt og indeholde en flydende værdi (Float), der er større end 0.0. + + + name + Valgfrit + Streng + Hvis det er angivet, skal det være en ikke-tom streng. Navn på posten inden for samlingen. + + + part + Valgfrit + Objekt/Array + + Hvis en del skal tildeles, skal det være et objekt/array, og mindst et af følgende felter skal være udfyldt: +
    +
  • part.id
  • +
  • part.mpnr
  • +
  • part.ipn
  • +
  • part.name
  • +
+ + + + part.id + Valgfrit + Heltal (Integer) + Heltal > 0. Tilsvarer den interne nummer-ID for delen i database. + + + part.mpnr + Valgfrit + Streng + Ikke-tom streng, hvis ingen part.id-, part.ipn- eller part.name-værdi er angivet. + + + part.ipn + Valgfrit + Streng + Ikke-tom streng, hvis ingen part.id-, part.mpnr- eller part.name-værdi er angivet. + + + part.name + Valgfrit + Streng + Ikke-tom streng, hvis ingen part.id-, part.mpnr- eller part.ipn-værdi er angivet. + + + part.description + Valgfrit + Streng eller null + Hvis angivet, skal det være en ikke-tom streng eller null. Værdien bliver overskrevet i delen. + + + part.manufacturer + Valgfrit + Objekt/Array + + Hvis producenten af en del skal ændres eller entydigt søges ved hjælp af part.mpnr-værdien, skal det være et objekt/array og mindst et af følgende felter skal være udfyldt: +
    +
  • manufacturer.id
  • +
  • manufacturer.name
  • +
+ + + + manufacturer.id + Valgfrit + Heltal (Integer) + Heltal > 0. Tilsvarer den interne nummer-ID for producenten. + + + manufacturer.name + Valgfrit + Streng + Ikke-tom streng, hvis ingen manufacturer.id er angivet. + + + part.category + Valgfrit + Objekt/Array + + Hvis en delens kategori skal ændres, skal det være et objekt/array, og mindst et af følgende felter skal være udfyldt: +
    +
  • category.id
  • +
  • category.name
  • +
+ + + + category.id + Valgfrit + Heltal (Integer) + Heltal > 0. Tilsvarer den interne nummer-ID for delens kategori. + + + category.name + Valgfrit + Streng + Ikke-tom streng, hvis ingen category.id er angivet. + + + + ]]> +
+
+
+ + + assembly.bom_import.template.csv.exptected_columns + Mulige kolonner: + + + + + assembly.bom_import.template.csv.table + + + + + Kolonne + Betingelse + Datatype + Beskrivelse + + + + + quantity + Påkrævet felt + Flydende punkt-tal (Float) + Skal være udfyldt og indeholde en flydende værdi (Float), der er større end 0.0. + + + name + Valgfrit + Streng + Navnet på posten inden for stykliste. + + + Kolonner, der starter med part_ + + Hvis en del skal tildeles, skal en af følgende kolonner være angivet og udfyldt: +
    +
  • part_id
  • +
  • part_mpnr
  • +
  • part_ipn
  • +
  • part_name
  • +
+ + + + part_id + Valgfrit + Heltal (Integer) + Heltal > 0. Tilsvarer den interne nummer-ID for delen i databasen. + + + part_mpnr + Valgfrit + Streng + Skal angives, hvis ingen af kolonnerne part_id, part_ipn, eller part_name er udfyldt. + + + part_ipn + Valgfrit + Streng + Skal angives, hvis ingen af kolonnerne part_id, part_mpnr eller part_name er udfyldt. + + + part_name + Valgfrit + Streng + Skal angives, hvis ingen af kolonnerne part_id, part_mpnr eller part_ipn er udfyldt. + + + part_description + Valgfrit + Streng + Vil blive overført og overskrive værdien for delen, hvis en ikke-tom streng er angivet. + + + Kolonner, der starter med part_manufacturer_ + + Hvis producenten for en del skal ændres eller søges entydigt ved hjælp af part_mpnr, skal en af følgende kolonner være angivet og udfyldt: +
    +
  • part_manufacturer_id
  • +
  • part_manufacturer_name
  • +
+ + + + part_manufacturer_id + Valgfrit + Heltal (Integer) + Heltal > 0. Tilsvarer den interne nummer-ID for producenten. + + + part_manufacturer_name + Valgfrit + Streng + Skal angives, hvis ingen part_manufacturer_id er udfyldt. + + + Kolonner, der starter med part.category_ + + Hvis en dels kategori skal ændres, skal en af følgende kolonner være angivet og udfyldt: +
    +
  • part_category_id
  • +
  • part_category_name
  • +
+ + + + part_category_id + Valgfrit + Heltal (Integer) + Heltal > 0. Tilsvarer den interne nummer-ID for delens kategori. + + + part_category_name + Valgfrit + Streng + Skal angives, hvis ingen part_category_id er udfyldt. + + + + ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.exptected_columns + Forventede kolonner: + + + + + assembly.bom_import.template.kicad_pcbnew.exptected_columns.note + + Bemærk: Der foretages ingen tildelinger til konkrete komponenter fra kategoristyringen.

+ ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.table + + + + + Felt + Betingelse + Datatype + Beskrivelse + + + + + Id + Valgfrit + Heltal + Fri tekst. Et unikt identifikationsnummer for hver komponent. + + + Designator + Valgfrit + Streng + Fri tekst. En unik referencebetegnelse for komponenten på PCB'en, f.eks. “R1” for modstand 1.
Bruges som navnet på placeringen i komponentgruppen. + + + Package + Valgfrit + Streng + Fri tekst. Komponentens kabinet eller formfaktor, f.eks. “0805” for SMD-modstande.
Ikke inkluderet som komponentoplysning i samlingen. + + + Quantity + Påkrævet + Heltal + Antallet af identiske komponenter, der kræves for at oprette en enkelt forekomst af samlingen.
Bruges som antal af komponentoplysning i samlingen. + + + Designation + Påkrævet + Streng + Beskrivelse eller funktion af komponenten, f.eks. modstandsværdi “10kΩ” eller kondensatorværdi “100nF”.
Bruges som navnet på komponentoplysningen i samlingen. + + + Supplier and ref + Valgfrit + Streng + Fri tekst. Kan indeholde, for eksempel, specifikke oplysninger fra en distributør.
Bruges som en note til komponentoplysningen i samlingen. + + + + ]]> +
+
+
+ + + assembly_list.all.title + Alle samlinger + + + + + assembly.edit.tab.common + Generelt + + + + + assembly.edit.tab.advanced + Avancerede indstillinger + + + + + assembly.edit.tab.attachments + Vedhæftede filer + + + + + assembly.filter.dbId + Database-ID + + + + + assembly.filter.ipn + Internt delnummer (IPN) + + + + + assembly.filter.name + Navn + + + + + assembly.filter.description + Beskrivelse + + + + + assembly.filter.comment + Kommentarer + + + + + assembly.filter.attachments_count + Antal vedhæftninger + + + + + assembly.filter.attachmentName + Vedhæftningens navn + + + + + assemblies.create.btn + Opret ny samling + + + + + assembly.table.id + ID + + + + + assembly.table.name + Navn + + + + + assembly.table.ipn + IPN + + + + + assembly.table.description + Beskrivelse + + + + + assembly.table.referencedAssemblies + Referencerede forsamlinger + + + + + assembly.table.addedDate + Tilføjet + + + + + assembly.table.lastModified + Sidst ændret + + + + + assembly.table.edit + Rediger + + + + + assembly.table.edit.title + Rediger samling + + + + + assembly.table.invalid_regex + Ugyldigt regulært udtryk (regex) + + + + + assembly.bom.table.id + ID + + + + + assembly.bom.table.name + Navn + + + + + assembly.bom.table.quantity + Mængde + + + + + assembly.bom.table.ipn + IPN + + + + + assembly.bom.table.description + Beskrivelse + + + + + assembly.bom.table.category + Kategori + + + + + assembly.bom.table.manufacturer + Producent + + + + + assembly.bom.table.designator + Referencebetegnelse + + + + + assembly.bom.table.mountnames + Monteringsnavne + + + + + assembly.bom.table.storage_location + Lagerplacering + + + + + assembly.bom.table.amount + Mængde + + + + + assembly.bom.table.addedDate + Oprettet + + + + + assembly.bom.table.lastModified + Sidst ændret + + + + + assembly.bom.table.edit + Rediger + + diff --git a/translations/messages.de.xlf b/translations/messages.de.xlf index 06326a21e..eb57ee1b5 100644 --- a/translations/messages.de.xlf +++ b/translations/messages.de.xlf @@ -1004,6 +1004,24 @@ Subelemente werden beim Löschen nach oben verschoben. Unterelemente auch exportieren
+ + + export.readable.label + Lesbarer Export + + + + + export.readable + CSV + + + + + export.readable_bom + PDF + + Part-DB1\templates\AdminPages\_export_form.html.twig:39 @@ -4740,6 +4758,24 @@ Wenn Sie dies fehlerhafterweise gemacht haben oder ein Computer nicht mehr vertr Name + + + part.table.name.value.for_part + %value% (Bauteil) + + + + + part.table.name.value.for_assembly + %value% (Baugruppe) + + + + + part.table.name.value.for_project + %value% (Projekt) + + Part-DB1\src\DataTables\PartsDataTable.php:178 @@ -9938,6 +9974,48 @@ Element 1 -> Element 1.2 Archiviert + + + assembly.edit.status + Status Baugruppe + + + + + assembly.edit.ipn + Internal Part Number (IPN) + + + + + assembly.status.draft + Entwurf + + + + + assembly.status.planning + In Planung + + + + + assembly.status.in_production + In Produktion + + + + + assembly.status.finished + Abgeschlossen + + + + + assembly.status.archived + Archiviert + + part.new_build_part.error.build_part_already_exists @@ -11090,6 +11168,18 @@ Element 1 -> Element 1.2 Typ + + + project.bom_import.type.json + JSON + + + + + project.bom_import.type.csv + CSV + + project.bom_import.type.kicad_pcbnew @@ -11108,6 +11198,319 @@ Element 1 -> Element 1.2 Wenn diese Option ausgewählt ist, werden alle bereits im Projekt existierenden BOM-Einträge gelöscht und mit den importierten BOM-Daten überschrieben. + + + project.import_bom.template.header.json + Import-Vorlage JSON + + + + + project.import_bom.template.header.csv + Import-Vorlage CSV + + + + + project.import_bom.template.header.kicad_pcbnew + Import-Vorlage CSV (KiCAD Pcbnew BOM) + + + + + project.bom_import.template.entry.name + Name des Bauteils im Projekt + + + + + project.bom_import.template.entry.part.mpnr + Eindeutige Produktnummer innerhalb des Herstellers + + + + + project.bom_import.template.entry.part.ipn + Eideutige IPN des Bauteils + + + + + project.bom_import.template.entry.part.name + Eindeutiger Name des Bauteils + + + + + project.bom_import.template.entry.part.manufacturer.name + Eindeutiger Name des Herstellers + + + + + project.bom_import.template.json.table + + + + + Feld + Bedingung + Datentyp + Beschreibung + + + + + quantity + Pflichtfeld + Gleitkommazahl (Float) + Muss gegeben sein und enthält einen Gleitkommawert (Float), der größer als 0.0 ist. + + + name + Optional + String + Falls vorhanden, muss es ein nicht-leerer String sein. Name des Eintrags innerhalb der Stückliste. + + + part + Optional + Objekt/Array + + Falls ein Bauteil zugeordnet werden soll, muss es ein Objekt/Array und mindestens eines der Felder ausgefüllt sein: +
    +
  • part.id
  • +
  • part.mpnr
  • +
  • part.ipn
  • +
  • part.name
  • +
+ + + + part.id + Optional + Ganzzahl (Integer) + Ganzzahl (Integer) > 0. Entspricht der Part-DB internen numerischen ID des Bauteils. + + + part.mpnr + Optional + String + Nicht-leerer String, falls keine part.id-, part-ipn- bzw. part.name-Angabe gegeben ist. + + + part.ipn + Optional + String + Nicht-leerer String, falls keine part.id-, part.mpnr bzw. part.name-Angabe gegeben ist. + + + part.name + Optional + String + Nicht-leerer String, falls keine part.id-, part.mpnr- bzw. part.ipn-Angabe gegeben ist. + + + part.manufacturer + Optional + Objekt/Array + + Falls der Hersteller eines Bauteils mit angepasst werden oder das Bauteil anhand der part.mpnr-Angabe eindeutig gesucht werden soll, muss es ein Objekt/Array und mindestens eines der Felder ausgefüllt sein: +
    +
  • manufacturer.id
  • +
  • manufacturer.name
  • +
+ + + + manufacturer.id + Optional + Ganzzahl (Integer) + Ganzzahl (Integer) > 0. Entspricht der internen numerischen ID des Herstellers. + + + manufacturer.name + Optional + String + Nicht-leerer String, falls keine manufacturer.id-Angabe gegeben ist. + + + + ]]> +
+
+
+ + + project.bom_import.template.csv.exptected_columns + Mögliche Spalten: + + + + + project.bom_import.template.csv.table + + + + + Spalte + Bedingung + Datentyp + Beschreibung + + + + + quantity + Pflichtfeld + Gleitkommazahl (Float) + Muss gegeben sein und enthält einen Gleitkommawert (Float), der größer als 0.0 ist. + + + name + Optional + String + Name des Eintrags innerhalb der Stückliste. + + + Spalten beginnend mit part_ + + Falls ein Bauteil zugeordnet werden soll, muss eine der folgenden Spalten gegeben und ausgefüllt sein: +
    +
  • part_id
  • +
  • part_mpnr
  • +
  • part_ipn
  • +
  • part_name
  • +
+ + + + part_id + Optional + Ganzzahl (Integer) + Ganzzahl (Integer) > 0. Entspricht der Part-DB internen numerischen ID des Bauteils. + + + part_mpnr + Optional + String + Anzugeben, falls keine part_id-, part_ipn- bzw. part_name-Spalte ausgefüllt gegeben ist. + + + part_ipn + Optional + String + Anzugeben, falls keine part_id-, part_mpnr- bzw. part_name-Spalte ausgefüllt gegeben ist. + + + part_name + Optional + String + Anzugeben, falls keine part_id-, part_mpnr- bzw. part_ipn-Spalte ausgefüllt gegeben ist. + + + Spalten beginnend mit part_manufacturer_ + + Falls der Hersteller eines Bauteils mit angepasst werden oder das Bauteil anhand der part_mpnr-Angabe eindeutig gesucht werden soll, muss eine der folgenden Spalten gegeben und ausgefüllt sein: +
    +
  • part_manufacturer_id
  • +
  • part_manufacturer_name
  • +
+ + + + part_manufacturer_id + Optional + Ganzzahl (Integer) + Ganzzahl (Integer) > 0. Entspricht der internen numerischen ID des Herstellers. + + + part_manufacturer_name + Optional + String + Anzugeben, falls keine part_manufacturer_id-Spalte ausgefüllt gegeben ist. + + + + ]]> +
+
+
+ + + project.bom_import.template.kicad_pcbnew.exptected_columns + Erwartete Spalten: + + + + + project.bom_import.template.kicad_pcbnew.exptected_columns.note + + Hinweis: Es findet keine Zuordnung zu konkreten Bauteilen aus der Kategorie-Verwaltung statt.

+ ]]> +
+
+
+ + + project.bom_import.template.kicad_pcbnew.table + + + + + Feld + Bedingung + Datentyp + Beschreibung + + + + + Id + Optional + Ganzzahl (Integer) + Offene Angabe. Eine eindeutige Identifikationsnummer für jedes Bauteil. + + + Designator + Optional + String + Offene Angabe. Ein eindeutiger Referenzbezeichner des Bauteils auf der Leiterplatte, z.B. „R1“ für Widerstand 1.
Wird in den Bestückungsnamen des Bauteil-Eintrags übernommen. + + + Package + Optional + String + Offene Angabe. Das Gehäuse oder die Bauform des Bauteils, z.B. „0805“ für SMD-Widerstände.
Wird für ein Bauteil-Eintrag nicht übernommen. + + + Quantity + Pflichtfeld + Ganzzahl (Integer) + Anzahl der identischen Bauteile, die benötigt werden, um eine Instanz zu erstellen.
Wird als Anzahl des Bauteil-Eintrags übernommen. + + + Designation + Pflichtfeld + String + Beschreibung oder Funktion des Bauteils, z.B. Widerstandswert „10kΩ“ oder Kondensatorwert „100nF“.
Wird in den Namen des Bauteil-Eintrags übernommen. + + + Supplier and ref + Optional + String + Offene Angabe. Kann z.B. Distributor spezifischen Wert enthalten.
Wird als Notiz zum Bauteil-Eintrag übernommen. + + + + ]]> +
+
+
project.bom_import.flash.invalid_file @@ -12845,6 +13248,30 @@ Bitte beachten Sie, dass Sie sich nicht als deaktivierter Benutzer ausgeben kön Die Spalten, die standardmäßig in Bauteiltabellen angezeigt werden sollen. Die Reihenfolge der Elemente kann per Drag & Drop geändert werden. + + + settings.behavior.table.assemblies_default_columns + Standardmäßige Spalten für Baugruppentabellen + + + + + settings.behavior.table.assemblies_default_columns.help + Die Spalten, die standardmäßig in Baugruppentabellen angezeigt werden sollen. Die Reihenfolge der Elemente kann per Drag & Drop geändert werden. + + + + + settings.behavior.table.assemblies_bom_default_columns + Standardmäßige Spalten für Baugruppen-Stücklisten + + + + + settings.behavior.table.assemblies_bom_default_columns.help + Die Spalten, die standardmäßig in Baugruppen-Stücklisten angezeigt werden sollen. Die Reihenfolge der Elemente kann per Drag & Drop geändert werden. + + settings.ips.oemsecrets @@ -12929,6 +13356,671 @@ Bitte beachten Sie, dass Sie sich nicht als deaktivierter Benutzer ausgeben kön Externe Version anzeigen + + + assembly.label + Baugruppe + + + + + assembly.caption + Baugruppe + + + + + perm.assemblies + Baugruppen + + + + + assembly_bom_entry.label + Bauteile + + + + + assembly.labelp + Baugruppen + + + + + assembly.referencedAssembly.labelp + Referenzierte Baugruppen + + + + + assembly.edit + Bearbeite Baugruppe + + + + + assembly.new + Neue Baugruppe + + + + + assembly.edit.bom.import_bom + Importiere Bauteil-Liste + + + + + log.database_updated.failed + __log.database_updated.failed + + + + + log.database_updated.old_version + __log.database_updated.old_version + + + + + log.database_updated.new_version + __log.database_updated.new_version + + + + + tree.tools.edit.assemblies + Baugruppen + + + + + assembly.bom_import.flash.success + %count% Part Einträge erfolgreich in Baugruppe importiert. + + + + + assembly.bom_import.flash.invalid_entries + Validierungsfehler! Bitte überprüfen Sie die importierte Datei! + + + + + assembly.bom_import.flash.invalid_file + Datei konnte nicht importiert werden. Überprüfen Sie, dass Sie den richtigen Dateityp gewählt haben. Fehlermeldung: %message% + + + + + assembly.bom.quantity + Menge + + + + + assembly.bom.mountnames + Bestückungsnamen + + + + + assembly.bom.designator + Referenzbezeichner (Designator) + + + + + assembly.bom.designator.help + Freie Bezeichnungskennung(en) + + + + + assembly.bom.instockAmount + Bestand im Lager + + + + + assembly.info.title + Baugruppen-Info + + + + + assembly.info.info.label + Info + + + + + assembly.info.sub_assemblies.label + Untergruppe + + + + + assembly.info.builds.label + Bau + + + + + assembly.info.bom_add_parts + Bauteile hinzufügen + + + + + assembly.info.bom_entries_count + Bauteile + + + + + assembly.info.sub_assemblies_count + Untergruppen + + + + + assembly.bom.delete.confirm + Wollen sie diesen Eintrag wirklich löschen? + + + + + assembly.add_parts_to_assembly + Bauteile zur Baugruppe hinzufügen + + + + + part.info.add_part_to_assembly + Dieses Bauteil zu einer Baugruppe hinzufügen + + + + + assembly.bom.project + Projekt + + + + + assembly.bom.referencedAssembly + Baugruppe + + + + + assembly.bom.name + Name + + + + + assembly.bom.name.help + Menschenlesbarer Titel des Stücklisteneintrags + + + + + assembly.bom.comment + Notizen + + + + + assembly.import_bom + Importiere Parts für Baugruppe + + + + + assembly.bom.partOrAssembly + Bauteil oder Baugruppe + + + + + assembly.bom.identifiers + Kennungen + + + + + assembly.bom.add_entry + Eintrag hinzufügen + + + + + assembly.bom.price + Preis + + + + + assembly.bom_import.type + Typ + + + + + assembly.bom_import.type.json + JSON für eine Baugruppe + + + + + assembly.bom_import.type.csv + CSV für eine Baugruppe + + + + + assembly.bom_import.type.kicad_pcbnew + CSV (KiCAD Pcbnew BOM) + + + + + assembly.bom_import.type.kicad_schematic + KiCAD Schaltplaneditor BOM (CSV Datei) + + + + + assembly.bom_import.clear_existing_bom + Lösche existierende Bauteil-Einträge vor dem Import + + + + + assembly.bom_import.clear_existing_bom.help + Wenn diese Option ausgewählt ist, werden alle bereits in der Baugruppe existierenden Bauteile gelöscht und mit den importierten Bauteildaten überschrieben. + + + + + assembly.import_bom.template.header.json + Import-Vorlage JSON für eine Baugruppe + + + + + assembly.import_bom.template.header.csv + Import-Vorlage CSV für eine Baugruppe + + + + + assembly.import_bom.template.header.kicad_pcbnew + Import-Vorlage CSV (KiCAD Pcbnew BOM) für eine Baugruppe + + + + + assembly.bom_import.template.entry.name + Name des Bauteils in der Baugruppe + + + + + assembly.bom_import.template.entry.part.mpnr + Eindeutige Produktnummer innerhalb des Herstellers + + + + + assembly.bom_import.template.entry.part.ipn + Eideutige IPN des Bauteils + + + + + assembly.bom_import.template.entry.part.name + Eindeutiger Name des Bauteils + + + + + assembly.bom_import.template.entry.part.manufacturer.name + Eindeutiger Name des Herstellers + + + + + assembly.bom_import.template.entry.part.category.name + Eindeutiger Name der Kategorie + + + + + assembly.bom_import.template.json.table + + + + + Feld + Bedingung + Datentyp + Beschreibung + + + + + quantity + Pflichtfeld + Gleitkommazahl (Float) + Muss gegeben sein und enthält einen Gleitkommawert (Float), der größer als 0.0 ist. + + + name + Optional + String + Falls vorhanden, muss es ein nicht-leerer String sein. Name des Eintrags innerhalb der Stückliste. + + + part + Optional + Objekt/Array + + Falls ein Bauteil zugeordnet werden soll, muss es ein Objekt/Array und mindestens eines der Felder ausgefüllt sein: +
    +
  • part.id
  • +
  • part.mpnr
  • +
  • part.ipn
  • +
  • part.name
  • +
+ + + + part.id + Optional + Ganzzahl (Integer) + Ganzzahl (Integer) > 0. Entspricht der Part-DB internen numerischen ID des Bauteils. + + + part.mpnr + Optional + String + Nicht-leerer String, falls keine part.id-, part-ipn- bzw. part.name-Angabe gegeben ist. + + + part.ipn + Optional + String + Nicht-leerer String, falls keine part.id-, part.mpnr bzw. part.name-Angabe gegeben ist. + + + part.name + Optional + String + Nicht-leerer String, falls keine part.id-, part.mpnr- bzw. part.ipn-Angabe gegeben ist. + + + part.description + Optional + String oder null + Falls vorhanden, muss es ein nicht-leerer String sein oder null. Wird in das Bauteil übernommen, d.h. der dortige Wert überschrieben. + + + part.manufacturer + Optional + Objekt/Array + + Falls der Hersteller eines Bauteils mit angepasst werden oder das Bauteil anhand der part.mpnr-Angabe eindeutig gesucht werden soll, muss es ein Objekt/Array und mindestens eines der Felder ausgefüllt sein: +
    +
  • manufacturer.id
  • +
  • manufacturer.name
  • +
+ + + + manufacturer.id + Optional + Ganzzahl (Integer) + Ganzzahl (Integer) > 0. Entspricht der internen numerischen ID des Herstellers. + + + manufacturer.name + Optional + String + Nicht-leerer String, falls keine manufacturer.id-Angabe gegeben ist. + + + part.category + Optional + Objekt/Array + + Falls die Kategorie eine Bauteils mit angepasst werden soll, muss es ein Objekt/Array und mindestens eines der Felder ausgefüllt sein: +
    +
  • category.id
  • +
  • category.name
  • +
+ + + + category.id + Optional + Ganzzahl (Integer) + Ganzzahl (Integer) > 0. Entspricht der internen numerischen ID der Kategorie des Bauteils. + + + category.name + Optional + String + Nicht-leerer String, falls keine category.id-Angabe gegeben ist. + + + + ]]> +
+
+
+ + + assembly.bom_import.template.csv.exptected_columns + Mögliche Spalten: + + + + + assembly.bom_import.template.csv.table + + + + + Spalte + Bedingung + Datentyp + Beschreibung + + + + + quantity + Pflichtfeld + Gleitkommazahl (Float) + Muss gegeben sein und enthält einen Gleitkommawert (Float), der größer als 0.0 ist. + + + name + Optional + String + Name des Eintrags innerhalb der Baugruppe. + + + Spalten beginnend mit part_ + + Falls ein Bauteil zugeordnet werden soll, muss eine der folgenden Spalten gegeben und ausgefüllt sein: +
    +
  • part_id
  • +
  • part_mpnr
  • +
  • part_ipn
  • +
  • part_name
  • +
+ + + + part_id + Optional + Ganzzahl (Integer) + Ganzzahl (Integer) > 0. Entspricht der Part-DB internen numerischen ID des Bauteils. + + + part_mpnr + Optional + String + Anzugeben, falls keine part_id-, part_ipn- bzw. part_name-Spalte ausgefüllt gegeben ist. + + + part_ipn + Optional + String + Anzugeben, falls keine part_id-, part_mpnr- bzw. part_name-Spalte ausgefüllt gegeben ist. + + + part_name + Optional + String + Anzugeben, falls keine part_id-, part_mpnr- bzw. part_ipn-Spalte ausgefüllt gegeben ist. + + + part_description + Optional + String + Wird in das Bauteil übernommen, d.h. der dortige Wert überschrieben sofern ein nicht-leerer String gegeben ist. + + + Spalten beginnend mit part_manufacturer_ + + Falls der Hersteller eines Bauteils mit angepasst werden oder das Bauteil anhand der part_mpnr-Angabe eindeutig gesucht werden soll, muss eine der folgenden Spalten gegeben und ausgefüllt sein: +
    +
  • part_manufacturer_id
  • +
  • part_manufacturer_name
  • +
+ + + + part_manufacturer_id + Optional + Ganzzahl (Integer) + Ganzzahl (Integer) > 0. Entspricht der internen numerischen ID des Herstellers. + + + part_manufacturer_name + Optional + String + Anzugeben, falls keine part_manufacturer_id-Spalte ausgefüllt gegeben ist. + + + Spalten beginnend mit part.category_ + + Falls die Kategorie eines Bauteils mit angepasst werden soll, muss eine der folgenden Spalten gegeben und ausgefüllt sein: +
    +
  • part_category_id
  • +
  • part_category_name
  • +
+ + + + part_category_id + Optional + Ganzzahl (Integer) + Ganzzahl (Integer) > 0. Entspricht der internen numerischen ID der Kategorie des Bauteils. + + + part_category_name + Optional + String + Anzugeben, falls keine part_category_id-Spalte ausgefüllt gegeben ist. + + + + ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.exptected_columns + Erwartete Spalten: + + + + + assembly.bom_import.template.kicad_pcbnew.exptected_columns.note + + Hinweis: Es findet keine Zuordnung zu konkreten Bauteilen aus der Kategorie-Verwaltung statt.

+ ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.table + + + + + Feld + Bedingung + Datentyp + Beschreibung + + + + + Id + Optional + Ganzzahl (Integer) + Offene Angabe. Eine eindeutige Identifikationsnummer für jedes Bauteil. + + + Designator + Optional + String + Offene Angabe. Ein eindeutiger Referenzbezeichner des Bauteils auf der Leiterplatte, z.B. „R1“ für Widerstand 1.
Wird in den Bestückungsnamen des Bauteil-Eintrags in der Baugruppe übernommen. + + + Package + Optional + String + Offene Angabe. Das Gehäuse oder die Bauform des Bauteils, z.B. „0805“ für SMD-Widerstände.
Wird für ein Bauteil-Eintrag innerhalb der Baugruppe nicht übernommen. + + + Quantity + Pflichtfeld + Ganzzahl (Integer) + Anzahl der identischen Bauteile, die benötigt werden, um eine Instanz der Baugruppe zu erstellen.
Wird als Anzahl des Bauteil-Eintrags innerhalb der Baugruppe übernommen. + + + Designation + Pflichtfeld + String + Beschreibung oder Funktion des Bauteils, z.B. Widerstandswert „10kΩ“ oder Kondensatorwert „100nF“.
Wird in den Namen des Bauteil-Eintrags innerhalb der Baugruppe übernommen. + + + Supplier and ref + Optional + String + Offene Angabe. Kann z.B. Distributor spezifischen Wert enthalten.
Wird als Notiz zum Bauteil-Eintrag innerhalb der Baugruppe übernommen. + + + + ]]> +
+
+
part.table.actions.error @@ -13055,6 +14147,18 @@ Bitte beachten Sie, dass Sie sich nicht als deaktivierter Benutzer ausgeben kön Wenn Sie Wechselkurse zwischen Nicht-Euro-Währungen benötigen, können Sie hier einen API-Schlüssel von fixer.io eingeben. + + + settings.misc.assembly + Baugruppen + + + + + settings.misc.assembly.useIpnPlaceholderInName + Verwenden Sie einen %%ipn%%-Platzhalter im Namen einer Baugruppe. Der Platzhalter wird beim Speichern durch die eingegebene IPN ersetzt. + + settings.behavior.part_info @@ -14189,5 +15293,221 @@ Bitte beachten Sie, dass Sie sich nicht als deaktivierter Benutzer ausgeben kön Maximale Anzahl von Zuordnungen erreicht + + + assembly_list.all.title + Alle Baugruppen + + + + + assembly.edit.tab.common + Allgemein + + + + + assembly.edit.tab.advanced + Erweiterte Optionen + + + + + assembly.edit.tab.attachments + Dateianhänge + + + + + assembly.filter.dbId + Datenbank ID + + + + + assembly.filter.ipn + Internal Part Number (IPN) + + + + + assembly.filter.name + Name + + + + + assembly.filter.description + Beschreibung + + + + + assembly.filter.comment + Notizen + + + + + assembly.filter.attachments_count + Anzahl der Anhänge + + + + + assembly.filter.attachmentName + Name des Anhangs + + + + + assemblies.create.btn + Neue Baugruppe anlegen + + + + + assembly.table.id + ID + + + + + assembly.table.name + Name + + + + + assembly.table.ipn + IPN + + + + + assembly.table.description + Beschreibung + + + + + assembly.table.referencedAssemblies + Referenzierte Baugruppen + + + + + assembly.table.addedDate + Hinzugefügt + + + + + assembly.table.lastModified + Zuletzt bearbeitet + + + + + assembly.table.edit + Ändern + + + + + assembly.table.edit.title + Baugruppe ändern + + + + + assembly.table.invalid_regex + Ungültiger regulärer Ausdruck (regex) + + + + + assembly.bom.table.id + ID + + + + + assembly.bom.table.name + Name + + + + + assembly.bom.table.quantity + Stückzahl + + + + + assembly.bom.table.ipn + IPN + + + + + assembly.bom.table.description + Beschreibung + + + + + assembly.bom.table.category + Kategorie + + + + + assembly.bom.table.manufacturer + Hersteller + + + + + assembly.bom.table.designator + Referenzbezeichner (Designator) + + + + + assembly.bom.table.mountnames + Bestückungsnamen + + + + + assembly.bom.table.storage_location + Lagerort + + + + + assembly.bom.table.amount + Menge + + + + + assembly.bom.table.addedDate + Erstellt am + + + + + assembly.bom.table.lastModified + Zuletzt bearbeitet + + + + + assembly.bom.table.edit + Bearbeiten + + diff --git a/translations/messages.el.xlf b/translations/messages.el.xlf index cc17d9be4..d5c83591b 100644 --- a/translations/messages.el.xlf +++ b/translations/messages.el.xlf @@ -228,6 +228,24 @@ Εξαγωγή όλων των στοιχείων + + + export.readable.label + Αναγνώσιμη εξαγωγή + + + + + export.readable + CSV + + + + + export.readable_bom + PDF + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:185 @@ -1535,5 +1553,940 @@ Επεξεργασία + + + part.table.name.value.for_part + %value% (Μέρος) + + + + + part.table.name.value.for_assembly + %value% (Συναρμολόγηση) + + + + + part.table.name.value.for_project + %value% (Έργο) + + + + + assembly.edit.status + Κατάσταση συναρμολόγησης + + + + + assembly.status.draft + Προσχέδιο + + + + + assembly.status.planning + Υπό σχεδιασμό + + + + + assembly.status.in_production + Σε παραγωγή + + + + + assembly.status.finished + Ολοκληρώθηκε + + + + + assembly.status.archived + Αρχειοθετήθηκε + + + + + assembly.label + Σύνολο + + + + + assembly.caption + Σύνολο + + + + + perm.assemblies + Συναρμολογήσεις + + + + + assembly_bom_entry.label + Μέρη + + + + + assembly.labelp + Συναρμολογήσεις + + + + + assembly.referencedAssembly.labelp + Αναφερόμενες συναρμολογήσεις + + + + + assembly.edit + Επεξεργασία συνόλου + + + + + assembly.new + Νέο σύνολο + + + + + assembly.edit.bom.import_bom + Εισαγωγή μερών + + + + + log.database_updated.failed + __log.database_updated.failed + + + + + log.database_updated.old_version + __log.database_updated.old_version + + + + + log.database_updated.new_version + __log.database_updated.new_version + + + + + tree.tools.edit.assemblies + Συναρμολογήσεις + + + + + assembly.bom_import.flash.success + %count% εγγραφές εξαρτημάτων εισήχθησαν με επιτυχία στο σύνολο. + + + + + assembly.bom_import.flash.invalid_entries + Σφάλμα επικύρωσης! Ελέγξτε το εισαγόμενο αρχείο! + + + + + assembly.bom_import.flash.invalid_file + Το αρχείο δεν μπόρεσε να εισαχθεί. Ελέγξτε ότι έχετε επιλέξει τον σωστό τύπο αρχείου. Μήνυμα σφάλματος: %message% + + + + + assembly.bom.quantity + Ποσότητα + + + + + assembly.bom.mountnames + Ονόματα συναρμολόγησης + + + + + assembly.bom.designator + Αναγνωριστικό αναφοράς + + + + + assembly.bom.designator.help + Ελεύθερα αναγνωριστικά αναφοράς (designator) + + + + + assembly.bom.instockAmount + Ποσότητα σε απόθεμα + + + + + assembly.info.title + Πληροφορίες συναρμολόγησης + + + + + assembly.info.info.label + Πληροφορίες + + + + + assembly.info.sub_assemblies.label + Υποομάδες + + + + + assembly.info.builds.label + Κατασκευές + + + + + assembly.info.bom_add_parts + Προσθήκη εξαρτημάτων + + + + + assembly.info.bom_entries_count + Εξαρτήματα + + + + + assembly.info.sub_assemblies_count + Υποομάδες + + + + + assembly.bom.delete.confirm + Θέλετε πραγματικά να διαγράψετε αυτήν την εγγραφή; + + + + + assembly.add_parts_to_assembly + Προσθήκη εξαρτημάτων στη συναρμολόγηση + + + + + part.info.add_part_to_assembly + Προσθέστε αυτό το εξάρτημα σε μια συναρμολόγηση + + + + + assembly.bom.project + έργο + + + + + assembly.bom.referencedAssembly + Συναρμολόγηση + + + + + assembly.bom.name + Όνομα + + + + + assembly.bom.name.help + Ανθρώπινα αναγνώσιμος τίτλος της καταχώρησης BOM + + + + + assembly.bom.comment + Σχόλια + + + + + assembly.import_bom + Εισαγωγή εξαρτημάτων συναρμολόγησης + + + + + assembly.bom.partOrAssembly + Μέρος ή συναρμολόγηση + + + + + assembly.bom.identifiers + Αναγνωριστικά + + + + + assembly.bom.add_entry + Προσθήκη καταχώρησης + + + + + assembly.bom.price + Τιμή + + + + + assembly.bom_import.type + Τύπος + + + + + assembly.bom_import.type.json + JSON για συναρμολόγηση + + + + + assembly.bom_import.type.csv + CSV για μια συναρμολόγηση + + + + + assembly.bom_import.type.kicad_pcbnew + CSV (KiCAD Pcbnew BOM) + + + + + assembly.bom_import.type.kicad_schematic + KiCAD Σχηματικό BOM (CSV αρχείο) + + + + + assembly.bom_import.clear_existing_bom + Διαγραφή υπαρχόντων εξαρτημάτων πριν από την εισαγωγή + + + + + assembly.bom_import.clear_existing_bom.help + Εάν επιλεγεί αυτή η επιλογή, όλα τα ήδη υπάρχοντα εξαρτήματα στη συναρμολόγηση θα διαγραφούν και θα αντικατασταθούν με τα δεδομένα εξαρτημάτων που εισάγονται. + + + + + assembly.import_bom.template.header.json + Πρότυπο εισαγωγής JSON για συναρμολόγηση + + + + + assembly.import_bom.template.header.csv + Πρότυπο CSV εισαγωγής για μια συναρμολόγηση + + + + + assembly.import_bom.template.header.kicad_pcbnew + Πρότυπο εισαγωγής CSV (KiCAD Pcbnew BOM) για συναρμολόγηση + + + + + assembly.bom_import.template.entry.name + Όνομα του εξαρτήματος στη συναρμολόγηση + + + + + assembly.bom_import.template.entry.part.mpnr + Μοναδικός αριθμός προϊόντος από τον κατασκευαστή + + + + + assembly.bom_import.template.entry.part.ipn + Μοναδικός IPN του εξαρτήματος + + + + + assembly.bom_import.template.entry.part.name + Μοναδικό όνομα εξαρτήματος + + + + + assembly.bom_import.template.entry.part.manufacturer.name + Μοναδικό όνομα κατασκευαστή + + + + + assembly.bom_import.template.entry.part.category.name + Μοναδικό όνομα κατηγορίας + + + + + assembly.bom_import.template.json.table + + + + + Πεδίο + Προϋπόθεση + Τύπος δεδομένων + Περιγραφή + + + + + quantity + Υποχρεωτικό πεδίο + Αριθμός κινητής υποδιαστολής (Float) + Πρέπει να είναι συμπληρωμένος και να περιέχει μια αριθμητική τιμή (Float) μεγαλύτερη από 0.0. + + + name + Προαιρετικό + Χαρακτηριστική ακολουθία (String) + Αν υπάρχει, πρέπει να είναι μη κενό κείμενο. Το όνομα του είδους μέσα στη συλλογή. + + + part + Προαιρετικό + Αντικείμενο/Πίνακας + + Αν πρόκειται να ανατεθεί ένα εξάρτημα, πρέπει να είναι αντικείμενο/πίνακας και τουλάχιστον ένα από τα παρακάτω πεδία πρέπει να έχει συμπληρωθεί: +
    +
  • part.id
  • +
  • part.mpnr
  • +
  • part.ipn
  • +
  • part.name
  • +
+ + + + part.id + Προαιρετικό + Ακέραιος αριθμός (Integer) + Ακέραιος αριθμός > 0. Αντιστοιχεί στο εσωτερικό αριθμητικό ID του εξαρτήματος στη βάση δεδομένων. + + + part.mpnr + Προαιρετικό + Χαρακτηριστική ακολουθία (String) + Μη κενό κείμενο, αν δεν έχει συμπληρωθεί το part.id, part.ipn ή part.name. + + + part.ipn + Προαιρετικό + Χαρακτηριστική ακολουθία (String) + Μη κενό κείμενο, αν δεν έχει συμπληρωθεί το part.id, part.mpnr ή part.name. + + + part.name + Προαιρετικό + Χαρακτηριστική ακολουθία (String) + Μη κενό κείμενο, αν δεν έχει συμπληρωθεί το part.id, part.mpnr ή part.ipn. + + + part.description + Προαιρετικό + Χαρακτηριστική ακολουθία ή null + Αν υπάρχει, πρέπει να είναι μη κενό κείμενο ή null. Υπερισχύει της υπάρχουσας τιμής στο εξάρτημα. + + + part.manufacturer + Προαιρετικό + Αντικείμενο/Πίνακας + + Αν ο κατασκευαστής ενός εξαρτήματος χρειάζεται να αλλάξει ή να αναζητηθεί μονοσήμαντα μέσω της τιμής part.mpnr, πρέπει να είναι αντικείμενο/πίνακας και τουλάχιστον ένα από τα παρακάτω πεδία να είναι συμπληρωμένα: +
    +
  • manufacturer.id
  • +
  • manufacturer.name
  • +
+ + + + manufacturer.id + Προαιρετικό + Ακέραιος αριθμός (Integer) + Ακέραιος αριθμός > 0. Αντιστοιχεί στο εσωτερικό αριθμητικό ID του κατασκευαστή. + + + manufacturer.name + Προαιρετικό + Χαρακτηριστική ακολουθία (String) + Μη κενό κείμενο, αν δεν έχει συμπληρωθεί το manufacturer.id. + + + part.category + Προαιρετικό + Αντικείμενο/Πίνακας + + Αν χρειάζεται να τροποποιηθεί η κατηγορία του εξαρτήματος, πρέπει να είναι αντικείμενο/πίνακας και τουλάχιστον ένα από τα παρακάτω πεδία να είναι συμπληρωμένα: +
    +
  • category.id
  • +
  • category.name
  • +
+ + + + category.id + Προαιρετικό + Ακέραιος αριθμός (Integer) + Ακέραιος αριθμός > 0. Αντιστοιχεί στο εσωτερικό αριθμητικό ID της κατηγορίας εξαρτήματος. + + + category.name + Προαιρετικό + Χαρακτηριστική ακολουθία (String) + Μη κενό κείμενο, αν δεν έχει συμπληρωθεί το category.id. + + + + ]]> +
+
+
+ + + assembly.bom_import.template.csv.exptected_columns + Δυνατές στήλες: + + + + + assembly.bom_import.template.csv.table + + + + + Στήλη + Προϋπόθεση + Τύπος δεδομένων + Περιγραφή + + + + + quantity + Υποχρεωτικό πεδίο + Αριθμός κινητής υποδιαστολής (Float) + Πρέπει να είναι συμπληρωμένος και να περιέχει μια αριθμητική τιμή (Float) μεγαλύτερη από 0.0. + + + name + Προαιρετικό + Χαρακτηριστική ακολουθία (String) + Το όνομα του είδους μέσα στη συλλογή. + + + Στήλες που ξεκινούν με part_ + + Αν χρειάζεται να αποδοθεί εξάρτημα, πρέπει να συμπληρωθεί μία από τις παρακάτω στήλες: +
    +
  • part_id
  • +
  • part_mpnr
  • +
  • part_ipn
  • +
  • part_name
  • +
+ + + + part_id + Προαιρετικό + Ακέραιος αριθμός (Integer) + Ακέραιος αριθμός > 0. Αντιστοιχεί στο εσωτερικό αριθμητικό ID του εξαρτήματος στη βάση δεδομένων. + + + part_mpnr + Προαιρετικό + Χαρακτηριστική ακολουθία (String) + Πρέπει να συμπληρωθεί αν δεν γεμίσουν οι part_id, part_ipn ή part_name. + + + part_ipn + Προαιρετικό + Χαρακτηριστική ακολουθία (String) + Πρέπει να συμπληρωθεί αν δεν γεμίσουν οι part_id, part_mpnr ή part_name. + + + part_name + Προαιρετικό + Χαρακτηριστική ακολουθία (String) + Πρέπει να συμπληρωθεί αν δεν γεμίσουν οι part_id, part_mpnr ή part_ipn. + + + part_description + Προαιρετικό + Χαρακτηριστική ακολουθία + Θα μεταφερθεί και θα αντικαταστήσει την τιμή στο εξάρτημα, αν δοθεί μια μη κενή ακολουθία. + + + Στήλες που ξεκινούν με part_manufacturer_ + + Αν ο κατασκευαστής του εξαρτήματος πρέπει να αλλάξει ή να αναζητηθεί μονοσήμαντα μέσω της part_mpnr, πρέπει να συμπληρωθεί μία από τις παρακάτω στήλες: +
    +
  • part_manufacturer_id
  • +
  • part_manufacturer_name
  • +
+ + + + part_manufacturer_id + Προαιρετικό + Ακέραιος αριθμός (Integer) + Ακέραιος αριθμός > 0. Αντιστοιχεί στο εσωτερικό αριθμητικό ID του κατασκευαστή. + + + part_manufacturer_name + Προαιρετικό + Χαρακτηριστική ακολουθία (String) + Πρέπει να συμπληρωθεί αν δεν γεμίσει το πεδίο part_manufacturer_id. + + + Στήλες που ξεκινούν με part.category_ + + Αν η κατηγορία του εξαρτήματος πρέπει να αλλάξει, πρέπει να συμπληρωθεί μία από τις παρακάτω στήλες: +
    +
  • part_category_id
  • +
  • part_category_name
  • +
+ + + + part_category_id + Προαιρετικό + Ακέραιος αριθμός (Integer) + Ακέραιος αριθμός > 0. Αντιστοιχεί στο εσωτερικό αριθμητικό ID της κατηγορίας του εξαρτήματος. + + + part_category_name + Προαιρετικό + Χαρακτηριστική ακολουθία (String) + Πρέπει να συμπληρωθεί αν δεν γεμίσει το πεδίο part_category_id. + + + + ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.exptected_columns + Αναμενόμενες στήλες: + + + + + assembly.bom_import.template.kicad_pcbnew.exptected_columns.note + + Σημείωση: Δεν πραγματοποιείται αντιστοίχιση με συγκεκριμένα εξαρτήματα από τη διαχείριση κατηγοριών.

+ ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.table + + + + + Πεδίο + Προϋπόθεση + Τύπος Δεδομένων + Περιγραφή + + + + + Id + Προαιρετικό + Ακέραιος + Πεδίο ελεύθερης μορφής. Ένας μοναδικός αριθμός ταυτοποίησης για κάθε εξάρτημα. + + + Designator + Προαιρετικό + Συμβολοσειρά + Πεδίο ελεύθερης μορφής. Ένας μοναδικός αναγνωριστικός δείκτης για το εξάρτημα στην πλακέτα PCB, π.χ. "R1" για τον αντιστάτη 1.
Χρησιμοποιείται για την ονομασία της θέσης στην ομάδα εξαρτημάτων. + + + Package + Προαιρετικό + Συμβολοσειρά + Πεδίο ελεύθερης μορφής. Η θήκη ή ο μορφολογικός τύπος του εξαρτήματος, π.χ. "0805" για τους SMD αντιστάτες.
Δεν περιλαμβάνεται στις πληροφορίες εξαρτήματος της συναρμολόγησης. + + + Quantity + Απαιτείται + Ακέραιος + Ο αριθμός πανομοιότυπων εξαρτημάτων που απαιτούνται για τη δημιουργία μιας μοναδικής παρουσίας της συναρμολόγησης.
Χρησιμοποιείται ως ποσότητα στις πληροφορίες εξαρτήματος της συναρμολόγησης. + + + Designation + Απαιτείται + Συμβολοσειρά + Η περιγραφή ή η λειτουργία του εξαρτήματος, π.χ. τιμή αντιστάτη "10kΩ" ή τιμή πυκνωτή "100nF".
Χρησιμοποιείται ως το όνομα στις πληροφορίες εξαρτήματος της συναρμολόγησης. + + + Supplier and ref + Προαιρετικό + Συμβολοσειρά + Πεδίο ελεύθερης μορφής. Μπορεί να περιλαμβάνει, για παράδειγμα, συγκεκριμένες πληροφορίες για τον προμηθευτή.
Χρησιμοποιείται ως σημείωση για τις πληροφορίες εξαρτήματος της συναρμολόγησης. + + + + ]]> +
+
+
+ + + assembly_list.all.title + Όλες οι συναρμολογήσεις + + + + + assembly.edit.tab.common + Γενικά + + + + + assembly.edit.tab.advanced + Προηγμένες επιλογές + + + + + assembly.edit.tab.attachments + Συνημμένα + + + + + assembly.filter.dbId + Αναγνωριστικό βάσης δεδομένων + + + + + assembly.filter.ipn + Εσωτερικός αριθμός εξαρτήματος (IPN) + + + + + assembly.filter.name + Όνομα + + + + + assembly.filter.description + Περιγραφή + + + + + assembly.filter.comment + Σχόλια + + + + + assembly.filter.attachments_count + Αριθμός συνημμένων + + + + + assembly.filter.attachmentName + Όνομα συνημμένου + + + + + assemblies.create.btn + Δημιουργία νέας συναρμολόγησης + + + + + assembly.table.id + Αναγνωριστικό + + + + + assembly.table.name + Όνομα + + + + + assembly.table.ipn + IPN + + + + + assembly.table.description + Περιγραφή + + + + + assembly.table.referencedAssemblies + Αναφερόμενες συναρμολογήσεις + + + + + assembly.table.addedDate + Προστέθηκε + + + + + assembly.table.lastModified + Τελευταία επεξεργασία + + + + + assembly.table.edit + Επεξεργασία + + + + + assembly.table.edit.title + Επεξεργασία συναρμολόγησης + + + + + assembly.table.invalid_regex + Μη έγκυρη κανονική έκφραση (regex) + + + + + assembly.bom.table.id + ID + + + + + assembly.bom.table.name + Όνομα + + + + + assembly.bom.table.quantity + Ποσότητα + + + + + assembly.bom.table.ipn + IPN + + + + + assembly.bom.table.description + Περιγραφή + + + + + assembly.bom.table.category + Κατηγορία + + + + + assembly.bom.table.manufacturer + Κατασκευαστής + + + + + assembly.bom.table.designator + Αναγνωριστικό αναφοράς + + + + + assembly.bom.table.mountnames + Ονόματα τοποθέτησης + + + + + assembly.bom.table.storage_location + Θέση αποθήκευσης + + + + + assembly.bom.table.amount + Ποσότητα + + + + + assembly.bom.table.addedDate + Δημιουργήθηκε + + + + + assembly.bom.table.lastModified + Τελευταία τροποποίηση + + + + + assembly.bom.table.edit + Επεξεργασία + + diff --git a/translations/messages.en.xlf b/translations/messages.en.xlf index ce3b82547..8a2f67eb3 100644 --- a/translations/messages.en.xlf +++ b/translations/messages.en.xlf @@ -351,6 +351,24 @@ Export all elements + + + export.readable.label + Readable Export + + + + + export.readable + CSV + + + + + export.readable_bom + PDF + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:185 @@ -4741,6 +4759,24 @@ If you have done this incorrectly or if a computer is no longer trusted, you can Name + + + part.table.name.value.for_part + %value% (Part) + + + + + part.table.name.value.for_assembly + %value% (Assembly) + + + + + part.table.name.value.for_project + %value% (Project) + + Part-DB1\src\DataTables\PartsDataTable.php:178 @@ -9939,6 +9975,48 @@ Element 1 -> Element 1.2]]> Archived + + + assembly.edit.status + Assembly status + + + + + assembly.edit.ipn + Internal Part Number (IPN) + + + + + assembly.status.draft + Draft + + + + + assembly.status.planning + Planning + + + + + assembly.status.in_production + In production + + + + + assembly.status.finished + Finished + + + + + assembly.status.archived + Archived + + part.new_build_part.error.build_part_already_exists @@ -11091,6 +11169,18 @@ Element 1 -> Element 1.2]]> Type + + + project.bom_import.type.json + JSON + + + + + project.bom_import.type.csv + CSV + + project.bom_import.type.kicad_pcbnew @@ -11103,6 +11193,319 @@ Element 1 -> Element 1.2]]> Clear existing BOM entries before importing + + + project.import_bom.template.header.json + JSON Import Template + + + + + project.import_bom.template.header.csv + CSV Import Template + + + + + project.import_bom.template.header.kicad_pcbnew + CSV Import Template (KiCAD Pcbnew BOM) + + + + + project.bom_import.template.entry.name + Component name in the project + + + + + project.bom_import.template.entry.part.mpnr + Unique product number within the manufacturer + + + + + project.bom_import.template.entry.part.ipn + Unique IPN of the component + + + + + project.bom_import.template.entry.part.name + Unique name of the component + + + + + project.bom_import.template.entry.part.manufacturer.name + Unique name of the manufacturer + + + + + project.bom_import.template.json.table + + + + + Field + Condition + Data Type + Description + + + + + quantity + Required + Decimal (Float) + Must be provided and contains a decimal value (Float) greater than 0.0. + + + name + Optional + String + If present, it must be a non-empty string. The name of the entry within the bill of materials. + + + part + Optional + Object/Array + + If a component is to be assigned, it must be an object/array, and at least one of the following fields must be filled in: +
    +
  • part.id
  • +
  • part.mpnr
  • +
  • part.ipn
  • +
  • part.name
  • +
+ + + + part.id + Optional + Integer + Integer > 0. Corresponds to the internal numeric ID of the component in the Part-DB. + + + part.mpnr + Optional + String + A non-empty string if no part.id, part.ipn, or part.name is provided. + + + part.ipn + Optional + String + A non-empty string if no part.id, part.mpnr, or part.name is provided. + + + part.name + Optional + String + A non-empty string if no part.id, part.mpnr, or part.ipn is provided. + + + part.manufacturer + Optional + Object/Array + + If a component's manufacturer is to be adjusted, or the component is to be unambiguously identified based on part.mpnr, it must be an object/array, and at least one of the following fields must be filled in: +
    +
  • manufacturer.id
  • +
  • manufacturer.name
  • +
+ + + + manufacturer.id + Optional + Integer + Integer > 0. Corresponds to the internal numeric ID of the manufacturer. + + + manufacturer.name + Optional + String + A non-empty string if no manufacturer.id is provided. + + + + ]]> +
+
+
+ + + project.bom_import.template.csv.exptected_columns + Possible columns: + + + + + project.bom_import.template.csv.table + + + + + Column + Condition + Data Type + Description + + + + + quantity + Required + Floating-point number (Float) + Must be provided and contain a floating-point value (Float) greater than 0.0. + + + name + Optional + String + If available, it must be a non-empty string. The name of the entry within the bill of materials. + + + Columns starting with part_ + + If a component is to be assigned, at least one of the following columns must be provided and filled in: +
    +
  • part_id
  • +
  • part_mpnr
  • +
  • part_ipn
  • +
  • part_name
  • +
+ + + + part_id + Optional + Integer + Integer > 0. Corresponds to the internal numeric ID of the component in the Part-DB. + + + part_mpnr + Optional + String + Must be provided if the part_id, part_ipn, or part_name columns are not filled in. + + + part_ipn + Optional + String + Must be provided if the part_id, part_mpnr, or part_name columns are not filled in. + + + part_name + Optional + String + Must be provided if the part_id, part_mpnr, or part_ipn columns are not filled in. + + + Columns starting with part_manufacturer_ + + If the manufacturer of a component is to be adjusted or if the component is to be uniquely identified based on the part_mpnr, at least one of the following columns must be provided and filled in: +
    +
  • part_manufacturer_id
  • +
  • part_manufacturer_name
  • +
+ + + + part_manufacturer_id + Optional + Integer + Integer > 0. Corresponds to the internal numeric ID of the manufacturer. + + + part_manufacturer_name + Optional + String + Must be provided if the part_manufacturer_id column is not filled in. + + + + ]]> +
+
+
+ + + project.bom_import.template.kicad_pcbnew.exptected_columns + Expected columns: + + + + + project.bom_import.template.kicad_pcbnew.exptected_columns.note + + Note: No assignment to specific components from the category management is performed.

+ ]]> +
+
+
+ + + project.bom_import.template.kicad_pcbnew.table + + + + + Field + Condition + Data type + Description + + + + + Id + Optional + Integer + Free entry. A unique identification number for each component. + + + Designator + Optional + String + Free entry. A unique reference identifier of the component on the PCB, e.g., "R1" for resistor 1.
It is adopted into the assembly name of the component entry. + + + Package + Optional + String + Free entry. The housing or package type of the component, e.g., "0805" for SMD resistors.
It is not adopted into the component entry. + + + Quantity + Mandatory + Integer + The number of identical components required to create an instance.
It is adopted as the quantity of the entry. + + + Designation + Mandatory + String + Description or function of the component, e.g., resistor value "10kΩ" or capacitor value "100nF".
It is adopted into the name of the component entry. + + + Supplier and ref + Optional + String + Free entry. Can contain a distributor-specific value, for example.
It is adopted as a note to the component entry. + + + + ]]> +
+
+
project.bom_import.clear_existing_bom.help @@ -12846,6 +13249,30 @@ Please note, that you can not impersonate a disabled user. If you try you will g + + + settings.behavior.table.assemblies_default_columns + Default columns for assembly tables + + + + + settings.behavior.table.assemblies_default_columns.help + The columns to show by default in assembly tables. Order of items can be changed via drag & drop. + + + + + settings.behavior.table.assemblies_bom_default_columns + Default columns for assembly BOM tables + + + + + settings.behavior.table.assemblies_bom_default_columns.help + The columns to show by default in assembly BOM tables. Order of items can be changed via drag & drop. + + settings.ips.oemsecrets @@ -12930,6 +13357,671 @@ Please note, that you can not impersonate a disabled user. If you try you will g View external version + + + assembly.label + Assembly + + + + + assembly.caption + Assembly + + + + + assembly_bom_entry.label + Parts + + + + + perm.assemblies + Assemblies + + + + + assembly.labelp + Assemblies + + + + + assembly.referencedAssembly.labelp + Referenced assemblies + + + + + assembly.edit + Edit assembly + + + + + assembly.new + New assembly + + + + + assembly.edit.bom.import_bom + Import part list + + + + + log.database_updated.failed + __log.database_updated.failed + + + + + log.database_updated.old_version + __log.database_updated.old_version + + + + + log.database_updated.new_version + __log.database_updated.new_version + + + + + tree.tools.edit.assemblies + Assemblies + + + + + assembly.bom_import.flash.success + Imported %count% parts in assembly successfully. + + + + + assembly.bom_import.flash.invalid_entries + Validation error! Please check your data! + + + + + assembly.bom_import.flash.invalid_file + File could not be imported. Please check that you have selected the right file type. Error message: %message% + + + + + assembly.bom.quantity + Quantity + + + + + assembly.bom.mountnames + Mount names + + + + + assembly.bom.designator + Designator + + + + + assembly.bom.designator.help + Free identifier(s) + + + + + assembly.bom.instockAmount + Stocked amount + + + + + assembly.info.title + Assembly info + + + + + assembly.info.info.label + Info + + + + + assembly.info.sub_assemblies.label + Sub-assemblies + + + + + assembly.info.builds.label + Build + + + + + assembly.info.bom_add_parts + Add part entries + + + + + assembly.info.bom_entries_count + Part entries + + + + + assembly.info.sub_assemblies_count + Sub-assemblies + + + + + assembly.bom.delete.confirm + Do you really want to delete this entry? + + + + + assembly.add_parts_to_assembly + Add parts to assembly + + + + + part.info.add_part_to_assembly + Add this part to an assembly + + + + + assembly.bom.project + Project + + + + + assembly.bom.referencedAssembly + Assembly + + + + + assembly.bom.name + Name + + + + + assembly.bom.name.help + Human-readable title of the BOM entry + + + + + assembly.bom.comment + Notes + + + + + assembly.import_bom + Import part list for assembly + + + + + assembly.bom.partOrAssembly + Part or assembly + + + + + assembly.bom.identifiers + Identifiers + + + + + assembly.bom.add_entry + Add entry + + + + + assembly.bom.price + Price + + + + + assembly.bom_import.type + Type + + + + + assembly.bom_import.type.json + JSON for an assembly + + + + + assembly.bom_import.type.csv + CSV for an assembly + + + + + assembly.bom_import.type.kicad_pcbnew + CSV (KiCAD Pcbnew BOM) + + + + + assembly.bom_import.type.kicad_schematic + KiCAD Schematic BOM (CSV file) + + + + + assembly.bom_import.clear_existing_bom + Clear existing part entries before importing + + + + + assembly.bom_import.clear_existing_bom.help + Selecting this option will remove all existing part entries in the assembly and overwrite them with the imported part data! + + + + + assembly.import_bom.template.header.json + Import template JSON format for one assembly + + + + + assembly.import_bom.template.header.csv + Import template CSV format for one assembly + + + + + assembly.import_bom.template.header.kicad_pcbnew + Import template CSV format (KiCAD Pcbnew BOM) for one assembly + + + + + assembly.bom_import.template.entry.name + Name of the part in the assembly + + + + + assembly.bom_import.template.entry.part.mpnr + Unique product number within the manufacturer + + + + + assembly.bom_import.template.entry.part.ipn + Unique IPN of the part + + + + + assembly.bom_import.template.entry.part.name + Unique name of the part + + + + + assembly.bom_import.template.entry.part.manufacturer.name + Unique name of the manufacturer + + + + + assembly.bom_import.template.entry.part.category.name + Unique name of the category + + + + + assembly.bom_import.template.json.table + + + + + Field + Condition + Data Type + Description + + + + + quantity + Mandatory + Floating point number (Float) + Must be provided and contains a floating point value (Float), which is greater than 0.0. + + + name + Optional + String + If present, it must be a non-empty string. Name of the entry within the assembly. + + + part + Optional + Object/Array + + If a part is to be associated, it must be an object/array with at least one of the following fields filled out: +
    +
  • part.id
  • +
  • part.mpnr
  • +
  • part.ipn
  • +
  • part.name
  • +
+ + + + part.id + Optional + Integer + Integer > 0. Corresponds to the part database internal numeric ID of the part. + + + part.mpnr + Optional + String + Non-empty string, if no part.id, part.ipn, or part.name is provided. + + + part.ipn + Optional + String + Non-empty string, if no part.id, part.mpnr, or part.name is provided. + + + part.name + Optional + String + Non-empty string, if no part.id, part.mpnr, or part.ipn is provided. + + + part.description + Optional + String or null + If provided, it must be a non-empty string or null. It will be transferred to the part, overwriting its current value. + + + part.manufacturer + Optional + Object/Array + + If the manufacturer of a part is to be adjusted or the part is to be uniquely identified using the part.mpnr, it must be an object/array with at least one of the following fields filled out: +
    +
  • manufacturer.id
  • +
  • manufacturer.name
  • +
+ + + + manufacturer.id + Optional + Integer + Integer > 0. Corresponds to the internal numeric ID of the manufacturer. + + + manufacturer.name + Optional + String + Non-empty string, if no manufacturer.id is provided. + + + part.category + Optional + Object/Array + + If the category of a part is to be adjusted, it must be an object/array with at least one of the following fields filled out: +
    +
  • category.id
  • +
  • category.name
  • +
+ + + + category.id + Optional + Integer + Integer > 0. Corresponds to the internal numeric ID of the part category. + + + category.name + Optional + String + Non-empty string, if no category.id is provided. + + + + ]]> +
+
+
+ + + assembly.bom_import.template.csv.exptected_columns + Possible columns: + + + + + assembly.bom_import.template.csv.table + + + + + Column + Condition + Data Type + Description + + + + + quantity + Mandatory + Floating point number (Float) + Must be provided and contains a floating point value (Float), which is greater than 0.0. + + + name + Optional + String + Name of the entry within the assembly. + + + Columns starting with part_ + + If a part is to be associated, one of the following columns must be provided and filled out: +
    +
  • part_id
  • +
  • part_mpnr
  • +
  • part_ipn
  • +
  • part_name
  • +
+ + + + part_id + Optional + Integer + Integer > 0. Corresponds to the part database internal numeric ID of the part. + + + part_mpnr + Optional + String + Must be provided if no part_id, part_ipn, or part_name column is filled out. + + + part_ipn + Optional + String + Must be provided if no part_id, part_mpnr, or part_name column is filled out. + + + part_name + Optional + String + Must be provided if no part_id, part_mpnr, or part_ipn column is filled out. + + + part_description + Optional + String + Will be transferred to the part, overwriting its current value if a non-empty string is provided. + + + Columns starting with part_manufacturer_ + + If the manufacturer of a part is to be adjusted or the part is to be uniquely identified using the part_mpnr, one of the following columns must be provided and filled out: +
    +
  • part_manufacturer_id
  • +
  • part_manufacturer_name
  • +
+ + + + part_manufacturer_id + Optional + Integer + Integer > 0. Corresponds to the internal numeric ID of the manufacturer. + + + part_manufacturer_name + Optional + String + Must be provided if no part_manufacturer_id column is filled out. + + + Columns starting with part.category_ + + If the category of a part is to be adjusted, one of the following columns must be provided and filled out: +
    +
  • part_category_id
  • +
  • part_category_name
  • +
+ + + + part_category_id + Optional + Integer + Integer > 0. Corresponds to the internal numeric ID of the part category. + + + part_category_name + Optional + String + Must be provided if no part_category_id column is filled out. + + + + ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.exptected_columns + Expected Columns: + + + + + assembly.bom_import.template.kicad_pcbnew.exptected_columns.note + + Note: No mapping is performed with specific components from category management.

+ ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.table + + + + + Field + Condition + Data Type + Description + + + + + Id + Optional + Integer + Free-form field. A unique identification number for each part. + + + Designator + Optional + String + Free-form field. A unique reference designator of the part on the PCB, e.g., “R1” for resistor 1.
Used for the placement name of the part entry in the assembly. + + + Package + Optional + String + Free-form field. The case or form factor of the part, e.g., “0805” for SMD resistors.
Not adopted for a part entry within the assembly. + + + Quantity + Required field + Integer + The number of identical parts needed to create an instance of the assembly.
Adopted as the quantity of the part entry within the assembly. + + + Designation + Required field + String + Description or function of the part, e.g., resistor value “10kΩ” or capacitor value “100nF.”
Adopted into the name of the part entry within the assembly. + + + Supplier and ref + Optional + String + Free-form field. May, for example, contain distributor-specific information.
Adopted as a note for the part entry within the assembly. + + + + ]]> +
+
+
part.table.actions.error @@ -13056,6 +14148,18 @@ Please note, that you can not impersonate a disabled user. If you try you will g If you need exchange rates between non-euro currencies, you can input an API key from fixer.io here. + + + settings.misc.assembly + Assemblies + + + + + settings.misc.assembly.useIpnPlaceholderInName + Use an %%ipn%% placeholder in the name of an assembly. Placeholder is replaced with the ipn input while saving. + + settings.behavior.part_info @@ -14214,5 +15318,221 @@ Please note, that you can not impersonate a disabled user. If you try you will g Misc + + + assembly_list.all.title + All assemblies + + + + + assembly.edit.tab.common + General + + + + + assembly.edit.tab.advanced + Advanced options + + + + + assembly.edit.tab.attachments + Attachments + + + + + assembly.filter.dbId + Database ID + + + + + assembly.filter.ipn + Internal Part Number (IPN) + + + + + assembly.filter.name + Name + + + + + assembly.filter.description + Description + + + + + assembly.filter.comment + Comments + + + + + assembly.filter.attachments_count + Number of attachments + + + + + assembly.filter.attachmentName + Attachment name + + + + + assemblies.create.btn + Create new assembly + + + + + assembly.table.id + ID + + + + + assembly.table.name + Name + + + + + assembly.table.ipn + IPN + + + + + assembly.table.description + Description + + + + + assembly.table.referencedAssemblies + Referenced assemblies + + + + + assembly.table.addedDate + Added + + + + + assembly.table.lastModified + Last modified + + + + + assembly.table.edit + Edit + + + + + assembly.table.edit.title + Edit assembly + + + + + assembly.table.invalid_regex + Invalid regular expression (regex) + + + + + assembly.bom.table.id + ID + + + + + assembly.bom.table.name + Name + + + + + assembly.bom.table.quantity + Quantity + + + + + assembly.bom.table.ipn + IPN + + + + + assembly.bom.table.description + Description + + + + + assembly.bom.table.category + Category + + + + + assembly.bom.table.manufacturer + Manufacturer + + + + + assembly.bom.table.designator + Free identifiers (designator) + + + + + assembly.bom.table.mountnames + Mount names + + + + + assembly.bom.table.storage_location + Storage location + + + + + assembly.bom.table.amount + Amount + + + + + assembly.bom.table.addedDate + Created at + + + + + assembly.bom.table.lastModified + Last modified + + + + + assembly.bom.table.edit + Edit + + diff --git a/translations/messages.es.xlf b/translations/messages.es.xlf index fce38e52f..0dda12e70 100644 --- a/translations/messages.es.xlf +++ b/translations/messages.es.xlf @@ -351,6 +351,24 @@ Exportar todos los elementos + + + export.readable.label + Exportación legible + + + + + export.readable + CSV + + + + + export.readable_bom + PDF + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:185 @@ -4740,6 +4758,24 @@ Subelementos serán desplazados hacia arriba. Nombre + + + part.table.name.value.for_part + %value% (Componente) + + + + + part.table.name.value.for_assembly + %value% (Ensamblaje) + + + + + part.table.name.value.for_project + %value% (Proyecto) + + Part-DB1\src\DataTables\PartsDataTable.php:178 @@ -9882,6 +9918,48 @@ Elemento 3 Archivado + + + assembly.edit.status + Estado del ensamblaje + + + + + assembly.edit.ipn + Número de Componente Interno (IPN) + + + + + assembly.status.draft + Esbozo + + + + + assembly.status.planning + En planificación + + + + + assembly.status.in_production + En producción + + + + + assembly.status.finished + Completado + + + + + assembly.status.archived + Archivado + + part.new_build_part.error.build_part_already_exists @@ -11028,6 +11106,18 @@ Elemento 3 Tipo + + + project.bom_import.type.json + JSON + + + + + project.bom_import.type.csv + CSV + + project.bom_import.type.kicad_pcbnew @@ -11040,6 +11130,319 @@ Elemento 3 Eliminar entradas BOM existentes antes de importar + + + project.import_bom.template.header.json + Plantilla de importación JSON + + + + + project.import_bom.template.header.csv + Plantilla de importación CSV + + + + + project.import_bom.template.header.kicad_pcbnew + Plantilla de importación CSV (KiCAD Pcbnew BOM) + + + + + project.bom_import.template.entry.name + Nombre del componente en el proyecto + + + + + project.bom_import.template.entry.part.mpnr + Número de producto único del fabricante + + + + + project.bom_import.template.entry.part.ipn + IPN único del componente + + + + + project.bom_import.template.entry.part.name + Nombre único del componente + + + + + project.bom_import.template.entry.part.manufacturer.name + Nombre único del fabricante + + + + + project.bom_import.template.json.table + + + + + Campo + Condición + Tipo de Datos + Descripción + + + + + quantity + Requerido + Decimal (Float) + Debe ser proporcionado y contener un valor decimal (Float) mayor que 0.0. + + + name + Opcional + Cadena (String) + Si está presente, debe ser una cadena no vacía. El nombre del elemento dentro de la lista de materiales. + + + part + Opcional + Objeto/Array + + Si se debe asignar un componente, debe ser un objeto/array, y al menos uno de los siguientes campos debe estar cumplimentado: +
    +
  • part.id
  • +
  • part.mpnr
  • +
  • part.ipn
  • +
  • part.name
  • +
+ + + + part.id + Opcional + Entero (Integer) + Entero (Integer) > 0. Corresponde al ID numérico interno del componente en la base de datos de componentes (Part-DB). + + + part.mpnr + Opcional + Cadena (String) + Una cadena no vacía si no se proporciona part.id, part.ipn o part.name. + + + part.ipn + Opcional + Cadena (String) + Una cadena no vacía si no se proporciona part.id, part.mpnr o part.name. + + + part.name + Opcional + Cadena (String) + Una cadena no vacía si no se proporciona part.id, part.mpnr o part.ipn. + + + part.manufacturer + Opcional + Objeto/Array + + Si se debe ajustar el fabricante de un componente, o si el componente debe identificarse de manera unívoca en base a part.mpnr, debe ser un objeto/array, y al menos uno de los siguientes campos debe estar cumplimentado: +
    +
  • manufacturer.id
  • +
  • manufacturer.name
  • +
+ + + + manufacturer.id + Opcional + Entero (Integer) + Entero (Integer) > 0. Corresponde al ID numérico interno del fabricante. + + + manufacturer.name + Opcional + Cadena (String) + Una cadena no vacía si no se proporciona manufacturer.id. + + + + ]]> +
+
+
+ + + project.bom_import.template.csv.exptected_columns + Columnas posibles: + + + + + project.bom_import.template.csv.table + + + + + Columna + Condición + Tipo de dato + Descripción + + + + + quantity + Obligatoria + Número decimal (Float) + Debe proporcionarse y contener un valor decimal (Float) mayor que 0.0. + + + name + Optional + String + Si está disponible, debe ser una cadena no vacía. El nombre del elemento dentro de la lista de materiales. + + + Columnas que comienzan con part_ + + Si se va a asignar un componente, al menos una de las siguientes columnas debe proporcionarse y completarse: +
    +
  • part_id
  • +
  • part_mpnr
  • +
  • part_ipn
  • +
  • part_name
  • +
+ + + + part_id + Opcional + Entero + Entero > 0. Corresponde al ID numérico interno del componente en la base de datos de partes (Part-DB). + + + part_mpnr + Opcional + Cadena (String) + Debe proporcionarse si las columnas part_id, part_ipn o part_name no están completas. + + + part_ipn + Opcional + Cadena (String) + Debe proporcionarse si las columnas part_id, part_mpnr o part_name no están completas. + + + part_name + Opcional + Cadena (String) + Debe proporcionarse si las columnas part_id, part_mpnr o part_ipn no están completas. + + + Columnas que comienzan con part_manufacturer_ + + Si el fabricante de un componente debe ajustarse o si el componente debe identificarse de forma única según el valor part_mpnr, al menos una de las siguientes columnas debe proporcionarse y completarse: +
    +
  • part_manufacturer_id
  • +
  • part_manufacturer_name
  • +
+ + + + part_manufacturer_id + Opcional + Entero + Entero > 0. Corresponde al ID numérico interno del fabricante. + + + part_manufacturer_name + Opcional + Cadena (String) + Debe proporcionarse si la columna part_manufacturer_id no está completa. + + + + ]]> +
+
+
+ + + project.bom_import.template.kicad_pcbnew.exptected_columns + Columnas esperadas: + + + + + project.bom_import.template.kicad_pcbnew.exptected_columns.note + + Nota: No se realiza ninguna asignación a componentes específicos desde la gestión de categorías.

+ ]]> +
+
+
+ + + project.bom_import.template.kicad_pcbnew.table + + + + + Campo + Condición + Tipo de dato + Descripción + + + + + Id + Opcional + Entero + Entrada libre. Un número de identificación único para cada componente. + + + Designator + Opcional + Cadena (String) + Entrada libre. Un identificador de referencia único del componente en el PCB, por ejemplo, "R1" para la resistencia 1.
Se adopta en el nombre de ensamblaje del registro del componente. + + + Package + Opcional + Cadena (String) + Entrada libre. El encapsulado o tipo de la carcasa del componente, por ejemplo, "0805" para resistencias SMD.
No se adopta en el registro del componente. + + + Quantity + Obligatorio + Entero + El número de componentes idénticos necesarios para crear una instancia.
Se toma como la cantidad de la entrada del componente. + + + Designation + Obligatorio + Cadena (String) + Descripción o función del componente, por ejemplo, valor de resistencia "10kΩ" o valor de condensador "100nF".
Se adopta en el nombre del registro del componente. + + + Supplier and ref + Opcional + Cadena (String) + Entrada libre. Puede contener, por ejemplo, un valor específico del distribuidor.
Se adopta como una nota en el registro del componente. + + + + ]]> +
+
+
project.bom_import.clear_existing_bom.help @@ -12344,6 +12747,671 @@ Por favor ten en cuenta que no puedes personificar a un usuario deshabilitado. S Ver versión externa + + + assembly.label + Ensamblaje + + + + + assembly.caption + Ensamblaje + + + + + perm.assemblies + Ensamblajes + + + + + assembly_bom_entry.label + Componentes + + + + + assembly.labelp + Ensamblajes + + + + + assembly.referencedAssembly.labelp + Conjuntos referenciados + + + + + assembly.edit + Editar ensamblaje + + + + + assembly.new + Nuevo ensamblaje + + + + + assembly.edit.bom.import_bom + Importar componentes + + + + + log.database_updated.failed + __log.database_updated.failed + + + + + log.database_updated.old_version + __log.database_updated.old_version + + + + + log.database_updated.new_version + __log.database_updated.new_version + + + + + tree.tools.edit.assemblies + Ensamblajes + + + + + assembly.bom_import.flash.success + %count% componente(s) se importaron correctamente al ensamblaje. + + + + + assembly.bom_import.flash.invalid_entries + ¡Error de validación! ¡Revisa el archivo importado! + + + + + assembly.bom_import.flash.invalid_file + No se pudo importar el archivo. Asegúrate de haber seleccionado el tipo de archivo correcto. Mensaje de error: %message% + + + + + assembly.bom.quantity + Cantidad + + + + + assembly.bom.mountnames + Nombres de montaje + + + + + assembly.bom.designator + Designador de referencia + + + + + assembly.bom.designator.help + Identificadores de referencia libres (designator) + + + + + assembly.bom.instockAmount + Cantidad en stock + + + + + assembly.info.title + Información del ensamblaje + + + + + assembly.info.info.label + Información + + + + + assembly.info.sub_assemblies.label + Subconjuntos + + + + + assembly.info.builds.label + Construcciones + + + + + assembly.info.bom_add_parts + Añadir piezas + + + + + assembly.info.bom_entries_count + Componentes + + + + + assembly.info.sub_assemblies_count + Subconjuntos + + + + + assembly.bom.delete.confirm + ¿Realmente desea eliminar esta entrada? + + + + + assembly.add_parts_to_assembly + Añadir piezas al ensamblaje + + + + + part.info.add_part_to_assembly + Agregar esta parte a un ensamblaje + + + + + assembly.bom.project + Proyecto + + + + + assembly.bom.referencedAssembly + Ensamblaje + + + + + assembly.bom.name + Nombre + + + + + assembly.bom.name.help + Título legible por humanos de la entrada de la lista de materiales + + + + + assembly.bom.comment + Comentarios + + + + + assembly.import_bom + Importar piezas para ensamblaje + + + + + assembly.bom.partOrAssembly + Parte o conjunto + + + + + assembly.bom.identifiers + Identificadores + + + + + assembly.bom.add_entry + Añadir entrada + + + + + assembly.bom.price + Precio + + + + + assembly.bom_import.type + Tipo + + + + + assembly.bom_import.type.json + JSON para un ensamblaje + + + + + assembly.bom_import.type.csv + CSV para un ensamblaje + + + + + assembly.bom_import.type.kicad_pcbnew + CSV (KiCAD Pcbnew BOM) + + + + + assembly.bom_import.type.kicad_schematic + KiCAD Editor Esquemático BOM (archivo CSV) + + + + + assembly.bom_import.clear_existing_bom + Eliminar entradas de componentes existentes antes de la importación + + + + + assembly.bom_import.clear_existing_bom.help + Si esta opción está seleccionada, se eliminarán todos los componentes existentes en el ensamblaje y serán reemplazados por los datos de los componentes importados. + + + + + assembly.import_bom.template.header.json + Plantilla de importación JSON para un ensamblaje + + + + + assembly.import_bom.template.header.csv + Plantilla de importación CSV para un ensamblaje + + + + + assembly.import_bom.template.header.kicad_pcbnew + Plantilla de importación CSV (KiCAD Pcbnew BOM) para un ensamblaje + + + + + assembly.bom_import.template.entry.name + Nombre del componente en el ensamblaje + + + + + assembly.bom_import.template.entry.part.mpnr + Número de parte único dentro del fabricante + + + + + assembly.bom_import.template.entry.part.ipn + IPN único del componente + + + + + assembly.bom_import.template.entry.part.name + Nombre único del componente + + + + + assembly.bom_import.template.entry.part.manufacturer.name + Nombre único del fabricante + + + + + assembly.bom_import.template.entry.part.category.name + Nombre único de la categoría + + + + + assembly.bom_import.template.json.table + + + + + Campo + Condición + Tipo de datos + Descripción + + + + + quantity + Campo obligatorio + Número de punto flotante (Float) + Debe completarse y contener un valor flotante (Float) mayor a 0.0. + + + name + Opcional + Cadena + Si se especifica, debe ser una cadena no vacía. El nombre del elemento dentro del conjunto. + + + part + Opcional + Objeto/Array + + Si se debe asignar una pieza, debe ser un objeto/array, y al menos uno de los siguientes campos debe completarse: +
    +
  • part.id
  • +
  • part.mpnr
  • +
  • part.ipn
  • +
  • part.name
  • +
+ + + + part.id + Opcional + Entero (Integer) + Entero > 0. Corresponde al ID interno numérico de la pieza en la base de datos. + + + part.mpnr + Opcional + Cadena + Cadena no vacía si no se rellenan los campos part.id, part.ipn o part.name. + + + part.ipn + Opcional + Cadena + Cadena no vacía si no se rellenan los campos part.id, part.mpnr o part.name. + + + part.name + Opcional + Cadena + Cadena no vacía si no se rellenan los campos part.id, part.mpnr o part.ipn. + + + part.description + Opcional + Cadena o null + Si se especifica, debe ser una cadena no vacía o null. Este valor sobrescribirá el existente en la pieza. + + + part.manufacturer + Opcional + Objeto/Array + + Si se desea cambiar el fabricante de la pieza o buscarlo de forma única utilizando el valor part.mpnr, debe ser un objeto/array y al menos uno de los siguientes campos debe completarse: +
    +
  • manufacturer.id
  • +
  • manufacturer.name
  • +
+ + + + manufacturer.id + Opcional + Entero (Integer) + Entero > 0. Corresponde al ID interno numérico del fabricante. + + + manufacturer.name + Opcional + Cadena + Cadena no vacía si no se proporciona el campo manufacturer.id. + + + part.category + Opcional + Objeto/Array + + Si se desea cambiar la categoría de la pieza, debe ser un objeto/array y al menos uno de los siguientes campos debe completarse: +
    +
  • category.id
  • +
  • category.name
  • +
+ + + + category.id + Opcional + Entero (Integer) + Entero > 0. Corresponde al ID interno numérico de la categoría de la pieza. + + + category.name + Opcional + Cadena + Cadena no vacía si no se proporciona el campo category.id. + + + + ]]> +
+
+
+ + + assembly.bom_import.template.csv.exptected_columns + Columnas posibles: + + + + + assembly.bom_import.template.csv.table + + + + + Columna + Condición + Tipo de datos + Descripción + + + + + quantity + Campo obligatorio + Número de punto flotante (Float) + Debe completarse y contener un valor flotante (Float) mayor a 0.0. + + + name + Opcional + Cadena + El nombre del elemento dentro del conjunto. + + + Columnas que comienzan con part_ + + Si se debe asignar una pieza, al menos una de las siguientes columnas debe completarse: +
    +
  • part_id
  • +
  • part_mpnr
  • +
  • part_ipn
  • +
  • part_name
  • +
+ + + + part_id + Opcional + Entero (Integer) + Entero > 0. Corresponde al ID interno numérico de la pieza en la base de datos. + + + part_mpnr + Opcional + Cadena + Debe completarse si no se han rellenado las columnas part_id, part_ipn o part_name. + + + part_ipn + Opcional + Cadena + Debe completarse si no se han rellenado las columnas part_id, part_mpnr o part_name. + + + part_name + Opcional + Cadena + Debe completarse si no se han rellenado las columnas part_id, part_mpnr o part_ipn. + + + part_description + Opcional + Cadena + Se transferirá y reemplazará el valor de la descripción de la pieza si se proporciona una cadena no vacía. + + + Columnas que comienzan con part_manufacturer_ + + Si el fabricante de la pieza debe cambiarse o buscarse exclusivamente mediante part_mpnr, al menos una de las siguientes columnas debe completarse: +
    +
  • part_manufacturer_id
  • +
  • part_manufacturer_name
  • +
+ + + + part_manufacturer_id + Opcional + Entero (Integer) + Entero > 0. Corresponde al ID interno numérico del fabricante. + + + part_manufacturer_name + Opcional + Cadena + Debe completarse si no se ha proporcionado el campo part_manufacturer_id. + + + Columnas que comienzan con part.category_ + + Si se necesita modificar la categoría de la pieza, al menos una de las siguientes columnas debe completarse: +
    +
  • part_category_id
  • +
  • part_category_name
  • +
+ + + + part_category_id + Opcional + Entero (Integer) + Entero > 0. Corresponde al ID interno numérico de la categoría de la pieza. + + + part_category_name + Opcional + Cadena + Debe completarse si no se ha proporcionado el campo part_category_id. + + + + ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.exptected_columns + Columnas esperadas: + + + + + assembly.bom_import.template.kicad_pcbnew.exptected_columns.note + + Nota: No se realiza una asociación con componentes específicos de la gestión de categorías.

+ ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.table + + + + + Campo + Condición + Tipo de Datos + Descripción + + + + + Id + Opcional + Entero + Campo libre. Un número único de identificación para cada componente. + + + Designator + Opcional + Cadena + Campo libre. Un designador de referencia único para el componente en la PCB, por ejemplo, "R1" para la resistencia 1.
Se utiliza como el nombre de ubicación en la entrada de componentes dentro del ensamblaje. + + + Package + Opcional + Cadena + Campo libre. El encapsulado o formato del componente, por ejemplo, "0805" para resistencias SMD.
No se incluye en la entrada del componente dentro del ensamblaje. + + + Quantity + Requerido + Entero + El número de componentes idénticos necesarios para crear una instancia del ensamblaje.
Se usa como la cantidad en la entrada de componentes dentro del ensamblaje. + + + Designation + Requerido + Cadena + Descripción o función del componente, por ejemplo, valor de resistencia "10kΩ" o valor de condensador "100nF".
Se usa como el nombre de la entrada del componente dentro del ensamblaje. + + + Supplier and ref + Opcional + Cadena + Campo libre. Puede contener, por ejemplo, información específica del distribuidor.
Se usa como una nota en la entrada del componente dentro del ensamblaje. + + + + ]]> +
+
+
part.table.actions.error @@ -12368,5 +13436,221 @@ Por favor ten en cuenta que no puedes personificar a un usuario deshabilitado. S Este componente contiene más de un stock. Cambie la ubicación manualmente para seleccionar el stock deseado. + + + assembly_list.all.title + Todas las ensamblajes + + + + + assembly.edit.tab.common + General + + + + + assembly.edit.tab.advanced + Opciones avanzadas + + + + + assembly.edit.tab.attachments + Archivos adjuntos + + + + + assembly.filter.dbId + ID de la base de datos + + + + + assembly.filter.ipn + Número interno de pieza (IPN) + + + + + assembly.filter.name + Nombre + + + + + assembly.filter.description + Descripción + + + + + assembly.filter.comment + Comentarios + + + + + assembly.filter.attachments_count + Cantidad de adjuntos + + + + + assembly.filter.attachmentName + Nombre del adjunto + + + + + assemblies.create.btn + Crear una nueva ensamblaje + + + + + assembly.table.id + ID + + + + + assembly.table.name + Nombre + + + + + assembly.table.ipn + IPN + + + + + assembly.table.description + Descripción + + + + + assembly.table.referencedAssemblies + Ensambles referenciados + + + + + assembly.table.addedDate + Añadido + + + + + assembly.table.lastModified + Última modificación + + + + + assembly.table.edit + Editar + + + + + assembly.table.edit.title + Editar ensamblaje + + + + + assembly.table.invalid_regex + Expresión regular no válida (regex) + + + + + assembly.bom.table.id + ID + + + + + assembly.bom.table.name + Nombre + + + + + assembly.bom.table.quantity + Cantidad + + + + + assembly.bom.table.ipn + IPN + + + + + assembly.bom.table.description + Descripción + + + + + assembly.bom.table.category + Categoría + + + + + assembly.bom.table.manufacturer + Fabricante + + + + + assembly.bom.table.designator + Designador de referencia + + + + + assembly.bom.table.mountnames + Nombres de montaje + + + + + assembly.bom.table.storage_location + Ubicación de almacenamiento + + + + + assembly.bom.table.amount + Cantidad + + + + + assembly.bom.table.addedDate + Creado el + + + + + assembly.bom.table.lastModified + Última modificación + + + + + assembly.bom.table.edit + Editar + + diff --git a/translations/messages.fr.xlf b/translations/messages.fr.xlf index 292dbafaa..ffbc71b6a 100644 --- a/translations/messages.fr.xlf +++ b/translations/messages.fr.xlf @@ -1,9101 +1,10066 @@ - - - - - - Part-DB1\templates\AdminPages\AttachmentTypeAdmin.html.twig:4 - Part-DB1\templates\AdminPages\AttachmentTypeAdmin.html.twig:4 - templates\AdminPages\AttachmentTypeAdmin.html.twig:4 - - - attachment_type.caption - Types pour fichiers joints - - - - - Part-DB1\templates\AdminPages\AttachmentTypeAdmin.html.twig:12 - new - - - attachment_type.edit - Modifier le type de pièce jointe - - - - - Part-DB1\templates\AdminPages\AttachmentTypeAdmin.html.twig:16 - new - - - attachment_type.new - Nouveau type de pièce jointe - - - - - Part-DB1\templates\AdminPages\CategoryAdmin.html.twig:4 - Part-DB1\templates\_sidebar.html.twig:22 - Part-DB1\templates\_sidebar.html.twig:7 - Part-DB1\templates\AdminPages\CategoryAdmin.html.twig:4 - Part-DB1\templates\_sidebar.html.twig:22 - Part-DB1\templates\_sidebar.html.twig:7 - templates\AdminPages\CategoryAdmin.html.twig:4 - templates\base.html.twig:163 - templates\base.html.twig:170 - templates\base.html.twig:197 - templates\base.html.twig:225 - - - category.labelp - Catégories - - - - - Part-DB1\templates\AdminPages\CategoryAdmin.html.twig:8 - Part-DB1\templates\AdminPages\StorelocationAdmin.html.twig:19 - Part-DB1\templates\AdminPages\CategoryAdmin.html.twig:8 - Part-DB1\templates\AdminPages\StorelocationAdmin.html.twig:11 - templates\AdminPages\CategoryAdmin.html.twig:8 - - - admin.options - Options - - - - - Part-DB1\templates\AdminPages\CategoryAdmin.html.twig:9 - Part-DB1\templates\AdminPages\CompanyAdminBase.html.twig:15 - Part-DB1\templates\AdminPages\CategoryAdmin.html.twig:9 - Part-DB1\templates\AdminPages\CompanyAdminBase.html.twig:15 - templates\AdminPages\CategoryAdmin.html.twig:9 - - - admin.advanced - Avancé - - - - - Part-DB1\templates\AdminPages\CategoryAdmin.html.twig:13 - new - - - category.edit - Éditer la catégorie - - - - - Part-DB1\templates\AdminPages\CategoryAdmin.html.twig:17 - new - - - category.new - Nouvelle catégorie - - - - - Part-DB1\templates\AdminPages\CurrencyAdmin.html.twig:4 - Part-DB1\templates\AdminPages\CurrencyAdmin.html.twig:4 - - - currency.caption - Devise - - - - - Part-DB1\templates\AdminPages\CurrencyAdmin.html.twig:12 - Part-DB1\templates\AdminPages\CurrencyAdmin.html.twig:12 - - - currency.iso_code.caption - Code ISO - - - - - Part-DB1\templates\AdminPages\CurrencyAdmin.html.twig:15 - Part-DB1\templates\AdminPages\CurrencyAdmin.html.twig:15 - - - currency.symbol.caption - Symbole de la devise - - - - - Part-DB1\templates\AdminPages\CurrencyAdmin.html.twig:29 - new - - - currency.edit - Editer la devise - - - - - Part-DB1\templates\AdminPages\CurrencyAdmin.html.twig:33 - new - - - currency.new - Nouvelle devise - - - - - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:19 - Part-DB1\templates\_navbar_search.html.twig:67 - Part-DB1\templates\_sidebar.html.twig:27 - Part-DB1\templates\_sidebar.html.twig:43 - Part-DB1\templates\_sidebar.html.twig:63 - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:19 - Part-DB1\templates\_navbar_search.html.twig:61 - Part-DB1\templates\_sidebar.html.twig:27 - Part-DB1\templates\_sidebar.html.twig:43 - Part-DB1\templates\_sidebar.html.twig:63 - templates\AdminPages\EntityAdminBase.html.twig:9 - templates\base.html.twig:80 - templates\base.html.twig:179 - templates\base.html.twig:206 - templates\base.html.twig:237 - - - search.placeholder - Recherche - - - - - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:23 - Part-DB1\templates\_sidebar.html.twig:3 - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:23 - Part-DB1\templates\_sidebar.html.twig:3 - templates\AdminPages\EntityAdminBase.html.twig:13 - templates\base.html.twig:166 - templates\base.html.twig:193 - templates\base.html.twig:221 - - - expandAll - Agrandir tout - - - - - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:27 - Part-DB1\templates\_sidebar.html.twig:4 - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:27 - Part-DB1\templates\_sidebar.html.twig:4 - templates\AdminPages\EntityAdminBase.html.twig:17 - templates\base.html.twig:167 - templates\base.html.twig:194 - templates\base.html.twig:222 - - - reduceAll - Réduire tout - - - - - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:54 - Part-DB1\templates\Parts\info\_sidebar.html.twig:4 - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:54 - Part-DB1\templates\Parts\info\_sidebar.html.twig:4 - - - part.info.timetravel_hint - C'est ainsi que le composant apparaissait avant le %timestamp%. <i>Veuillez noter que cette fonctionnalité est expérimentale, donc les infos ne sont peut-être pas correctes. </i> - - - - - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:60 - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:60 - templates\AdminPages\EntityAdminBase.html.twig:42 - - - standard.label - Propriétés - - - - - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:61 - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:61 - templates\AdminPages\EntityAdminBase.html.twig:43 - - - infos.label - Informations - - - - - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:63 - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:63 - new - - - history.label - Historique - - - - - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:66 - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:66 - templates\AdminPages\EntityAdminBase.html.twig:45 - - - export.label - Exporter - - - - - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:68 - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:68 - templates\AdminPages\EntityAdminBase.html.twig:47 - - - import_export.label - Importer exporter - - - - - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:69 - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:69 - - - mass_creation.label - Création multiple - - - - - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:82 - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:82 - templates\AdminPages\EntityAdminBase.html.twig:59 - - - admin.common - Commun - - - - - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:86 - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:86 - - - admin.attachments - Fichiers joints - - - - - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:90 - - - admin.parameters - Paramètres - - - - - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:179 - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:167 - templates\AdminPages\EntityAdminBase.html.twig:142 - - - export_all.label - Exporter tous les éléments - - - - - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:185 - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:173 - - - mass_creation.help - Chaque ligne sera interprétée comme le nom d'un élément qui sera créé. - - - - - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:45 - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:45 - templates\AdminPages\EntityAdminBase.html.twig:35 - - - edit.caption - Éditer l'élément "%name" - - - - - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:50 - Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:50 - templates\AdminPages\EntityAdminBase.html.twig:37 - - - new.caption - Nouvel élément - - - - - Part-DB1\templates\AdminPages\FootprintAdmin.html.twig:4 - Part-DB1\templates\_sidebar.html.twig:9 - Part-DB1\templates\AdminPages\FootprintAdmin.html.twig:4 - Part-DB1\templates\_sidebar.html.twig:9 - templates\base.html.twig:172 - templates\base.html.twig:199 - templates\base.html.twig:227 - - - footprint.labelp - Empreintes - - - - - Part-DB1\templates\AdminPages\FootprintAdmin.html.twig:13 - new - - - footprint.edit - Editer l'empreinte - - - - - Part-DB1\templates\AdminPages\FootprintAdmin.html.twig:17 - new - - - footprint.new - Nouvelle empreinte - - - - - Part-DB1\templates\AdminPages\GroupAdmin.html.twig:4 - Part-DB1\templates\AdminPages\GroupAdmin.html.twig:4 - - - group.edit.caption - Groupes - - - - - Part-DB1\templates\AdminPages\GroupAdmin.html.twig:9 - Part-DB1\templates\AdminPages\UserAdmin.html.twig:16 - Part-DB1\templates\AdminPages\GroupAdmin.html.twig:9 - Part-DB1\templates\AdminPages\UserAdmin.html.twig:16 - - - user.edit.permissions - Permissions - - - - - Part-DB1\templates\AdminPages\GroupAdmin.html.twig:24 - new - - - group.edit - Editer le groupe - - - - - Part-DB1\templates\AdminPages\GroupAdmin.html.twig:28 - new - - - group.new - Nouveau groupe - - - - - Part-DB1\templates\AdminPages\LabelProfileAdmin.html.twig:4 - - - label_profile.caption - Profil des étiquettes - - - - - Part-DB1\templates\AdminPages\LabelProfileAdmin.html.twig:8 - - - label_profile.advanced - Avancé - - - - - Part-DB1\templates\AdminPages\LabelProfileAdmin.html.twig:9 - - - label_profile.comment - Commentaire - - - - - Part-DB1\templates\AdminPages\LabelProfileAdmin.html.twig:55 - new - - - label_profile.edit - Editer profil d'étiquette - - - - - Part-DB1\templates\AdminPages\LabelProfileAdmin.html.twig:59 - new - - - label_profile.new - Nouveau profil d'étiquette - - - - - Part-DB1\templates\AdminPages\ManufacturerAdmin.html.twig:4 - Part-DB1\templates\AdminPages\ManufacturerAdmin.html.twig:4 - templates\AdminPages\ManufacturerAdmin.html.twig:4 - - - manufacturer.caption - Fabricants - - - - - Part-DB1\templates\AdminPages\ManufacturerAdmin.html.twig:8 - new - - - manufacturer.edit - Modifiez le fabricant - - - - - Part-DB1\templates\AdminPages\ManufacturerAdmin.html.twig:12 - new - - - manufacturer.new - Nouveau fabricant - - - - - Part-DB1\templates\AdminPages\MeasurementUnitAdmin.html.twig:4 - Part-DB1\templates\AdminPages\MeasurementUnitAdmin.html.twig:4 - - - measurement_unit.caption - Unité de mesure - - - - - Part-DB1\templates\AdminPages\StorelocationAdmin.html.twig:5 - Part-DB1\templates\_sidebar.html.twig:8 - Part-DB1\templates\AdminPages\StorelocationAdmin.html.twig:4 - Part-DB1\templates\_sidebar.html.twig:8 - templates\base.html.twig:171 - templates\base.html.twig:198 - templates\base.html.twig:226 - - - storelocation.labelp - Emplacement de stockage - - - - - Part-DB1\templates\AdminPages\StorelocationAdmin.html.twig:32 - new - - - storelocation.edit - Modifier l'emplacement de stockage - - - - - Part-DB1\templates\AdminPages\StorelocationAdmin.html.twig:36 - new - - - storelocation.new - Nouvel emplacement de stockage - - - - - Part-DB1\templates\AdminPages\SupplierAdmin.html.twig:4 - Part-DB1\templates\AdminPages\SupplierAdmin.html.twig:4 - templates\AdminPages\SupplierAdmin.html.twig:4 - - - supplier.caption - Fournisseurs - - - - - Part-DB1\templates\AdminPages\SupplierAdmin.html.twig:16 - new - - - supplier.edit - Modifier le fournisseur - - - - - Part-DB1\templates\AdminPages\SupplierAdmin.html.twig:20 - new - - - supplier.new - Nouveau fournisseur - - - - - Part-DB1\templates\AdminPages\UserAdmin.html.twig:8 - Part-DB1\templates\AdminPages\UserAdmin.html.twig:8 - - - user.edit.caption - Utilisateurs - - - - - Part-DB1\templates\AdminPages\UserAdmin.html.twig:14 - Part-DB1\templates\AdminPages\UserAdmin.html.twig:14 - - - user.edit.configuration - Configuration - - - - - Part-DB1\templates\AdminPages\UserAdmin.html.twig:15 - Part-DB1\templates\AdminPages\UserAdmin.html.twig:15 - - - user.edit.password - Mot de passe - - - - - Part-DB1\templates\AdminPages\UserAdmin.html.twig:45 - Part-DB1\templates\AdminPages\UserAdmin.html.twig:45 - - - user.edit.tfa.caption - Authentification à deux facteurs - - - - - Part-DB1\templates\AdminPages\UserAdmin.html.twig:47 - Part-DB1\templates\AdminPages\UserAdmin.html.twig:47 - - - user.edit.tfa.google_active - Application d'authentification active - - - - - Part-DB1\templates\AdminPages\UserAdmin.html.twig:48 - Part-DB1\templates\Users\backup_codes.html.twig:15 - Part-DB1\templates\Users\_2fa_settings.html.twig:95 - Part-DB1\templates\AdminPages\UserAdmin.html.twig:48 - Part-DB1\templates\Users\backup_codes.html.twig:15 - Part-DB1\templates\Users\_2fa_settings.html.twig:95 - - - tfa_backup.remaining_tokens - Nombre de codes de secours restant - - - - - Part-DB1\templates\AdminPages\UserAdmin.html.twig:49 - Part-DB1\templates\Users\backup_codes.html.twig:17 - Part-DB1\templates\Users\_2fa_settings.html.twig:96 - Part-DB1\templates\AdminPages\UserAdmin.html.twig:49 - Part-DB1\templates\Users\backup_codes.html.twig:17 - Part-DB1\templates\Users\_2fa_settings.html.twig:96 - - - tfa_backup.generation_date - Date de génération des codes de secours - - - - - Part-DB1\templates\AdminPages\UserAdmin.html.twig:53 - Part-DB1\templates\AdminPages\UserAdmin.html.twig:60 - Part-DB1\templates\AdminPages\UserAdmin.html.twig:53 - Part-DB1\templates\AdminPages\UserAdmin.html.twig:60 - - - user.edit.tfa.disabled - Méthode désactivée - - - - - Part-DB1\templates\AdminPages\UserAdmin.html.twig:56 - Part-DB1\templates\AdminPages\UserAdmin.html.twig:56 - - - user.edit.tfa.u2f_keys_count - Clés de sécurité actives - - - - - Part-DB1\templates\AdminPages\UserAdmin.html.twig:72 - Part-DB1\templates\AdminPages\UserAdmin.html.twig:72 - - - user.edit.tfa.disable_tfa_title - Voulez vous vraiment poursuivre ? - - - - - Part-DB1\templates\AdminPages\UserAdmin.html.twig:72 - Part-DB1\templates\AdminPages\UserAdmin.html.twig:72 - - - user.edit.tfa.disable_tfa_message - Cela désactivera <b> toutes les méthodes d'authentification à deux facteurs de l'utilisateur</b> et supprimera <b>les codes de secours</b>! -<br> -L'utilisateur devra configurer à nouveau toutes les méthodes d'authentification à deux facteurs et créer de nouveaux codes de secours!<br><br> -<b>Ne faites ceci qu'en étant sûr de l'identité de l'utilisateur (ayant besoin d'aide),autrement le compte pourrai être compromis!</b> - - - - - Part-DB1\templates\AdminPages\UserAdmin.html.twig:73 - Part-DB1\templates\AdminPages\UserAdmin.html.twig:73 - - - user.edit.tfa.disable_tfa.btn - Désactiver toutes les méthodes d'authentification à deux facteurs - - - - - Part-DB1\templates\AdminPages\UserAdmin.html.twig:85 - new - - - user.edit - Modifier l'utilisateur - - - - - Part-DB1\templates\AdminPages\UserAdmin.html.twig:89 - new - - - user.new - Nouvel utilisateur - - - - - Part-DB1\templates\AdminPages\_attachments.html.twig:4 - Part-DB1\templates\Parts\edit\_attachments.html.twig:4 - Part-DB1\templates\AdminPages\_attachments.html.twig:4 - Part-DB1\templates\Parts\edit\_attachments.html.twig:4 - Part-DB1\templates\Parts\info\_attachments_info.html.twig:63 - - - attachment.delete - Supprimer - - - - - Part-DB1\templates\AdminPages\_attachments.html.twig:41 - Part-DB1\templates\Parts\edit\_attachments.html.twig:38 - Part-DB1\templates\Parts\info\_attachments_info.html.twig:35 - Part-DB1\src\DataTables\AttachmentDataTable.php:159 - Part-DB1\templates\Parts\edit\_attachments.html.twig:38 - Part-DB1\src\DataTables\AttachmentDataTable.php:159 - - - attachment.external - Externe - - - - - Part-DB1\templates\AdminPages\_attachments.html.twig:49 - Part-DB1\templates\Parts\edit\_attachments.html.twig:47 - Part-DB1\templates\AdminPages\_attachments.html.twig:47 - Part-DB1\templates\Parts\edit\_attachments.html.twig:45 - - - attachment.preview.alt - Miniature du fichier joint - - - - - Part-DB1\templates\AdminPages\_attachments.html.twig:52 - Part-DB1\templates\Parts\edit\_attachments.html.twig:50 - Part-DB1\templates\Parts\info\_attachments_info.html.twig:62 - Part-DB1\templates\AdminPages\_attachments.html.twig:50 - Part-DB1\templates\Parts\edit\_attachments.html.twig:48 - Part-DB1\templates\Parts\info\_attachments_info.html.twig:45 - - - attachment.view - Afficher - - - - - Part-DB1\templates\AdminPages\_attachments.html.twig:58 - Part-DB1\templates\Parts\edit\_attachments.html.twig:56 - Part-DB1\templates\Parts\info\_attachments_info.html.twig:43 - Part-DB1\src\DataTables\AttachmentDataTable.php:166 - Part-DB1\templates\AdminPages\_attachments.html.twig:56 - Part-DB1\templates\Parts\edit\_attachments.html.twig:54 - Part-DB1\templates\Parts\info\_attachments_info.html.twig:38 - Part-DB1\src\DataTables\AttachmentDataTable.php:166 - - - attachment.file_not_found - Fichier introuvable - - - - - Part-DB1\templates\AdminPages\_attachments.html.twig:66 - Part-DB1\templates\Parts\edit\_attachments.html.twig:64 - Part-DB1\templates\Parts\info\_attachments_info.html.twig:48 - Part-DB1\templates\Parts\edit\_attachments.html.twig:62 - - - attachment.secure - Fichier joint privé - - - - - Part-DB1\templates\AdminPages\_attachments.html.twig:79 - Part-DB1\templates\Parts\edit\_attachments.html.twig:77 - Part-DB1\templates\AdminPages\_attachments.html.twig:77 - Part-DB1\templates\Parts\edit\_attachments.html.twig:75 - - - attachment.create - Ajouter un fichier joint - - - - - Part-DB1\templates\AdminPages\_attachments.html.twig:84 - Part-DB1\templates\Parts\edit\_attachments.html.twig:82 - Part-DB1\templates\Parts\edit\_lots.html.twig:33 - Part-DB1\templates\AdminPages\_attachments.html.twig:82 - Part-DB1\templates\Parts\edit\_attachments.html.twig:80 - Part-DB1\templates\Parts\edit\_lots.html.twig:33 - - - part_lot.edit.delete.confirm - Voulez vous vraiment supprimer ce stock ? Cette action ne pourra pas être annulée! - - - - - Part-DB1\templates\AdminPages\_delete_form.html.twig:2 - Part-DB1\templates\AdminPages\_delete_form.html.twig:2 - templates\AdminPages\_delete_form.html.twig:2 - - - entity.delete.confirm_title - Voulez vous vraiment supprimer %name%? - - - - - Part-DB1\templates\AdminPages\_delete_form.html.twig:3 - Part-DB1\templates\AdminPages\_delete_form.html.twig:3 - templates\AdminPages\_delete_form.html.twig:3 - - - entity.delete.message - Cette action ne pourra pas être annulée! -<br> -Les sous éléments seront déplacés vers le haut. - - - - - Part-DB1\templates\AdminPages\_delete_form.html.twig:11 - Part-DB1\templates\AdminPages\_delete_form.html.twig:11 - templates\AdminPages\_delete_form.html.twig:9 - - - entity.delete - Supprimer l'élément - - - - - Part-DB1\templates\AdminPages\_delete_form.html.twig:16 - Part-DB1\templates\Parts\info\_tools.html.twig:45 - Part-DB1\src\Form\Part\PartBaseType.php:286 - Part-DB1\templates\AdminPages\_delete_form.html.twig:16 - Part-DB1\templates\Parts\info\_tools.html.twig:43 - Part-DB1\src\Form\Part\PartBaseType.php:267 - new - - - edit.log_comment - Éditer le commentaire - - - - - Part-DB1\templates\AdminPages\_delete_form.html.twig:24 - Part-DB1\templates\AdminPages\_delete_form.html.twig:24 - templates\AdminPages\_delete_form.html.twig:12 - - - entity.delete.recursive - Suppression récursive (tous les sous éléments) - - - - - Part-DB1\templates\AdminPages\_duplicate.html.twig:3 - - - entity.duplicate - Dupliquer l’élément - - - - - Part-DB1\templates\AdminPages\_export_form.html.twig:4 - Part-DB1\src\Form\AdminPages\ImportType.php:76 - Part-DB1\templates\AdminPages\_export_form.html.twig:4 - Part-DB1\src\Form\AdminPages\ImportType.php:76 - templates\AdminPages\_export_form.html.twig:4 - src\Form\ImportType.php:67 - - - export.format - Format de fichier - - - - - Part-DB1\templates\AdminPages\_export_form.html.twig:16 - Part-DB1\templates\AdminPages\_export_form.html.twig:16 - templates\AdminPages\_export_form.html.twig:16 - - - export.level - Niveau de verbosité - - - - - Part-DB1\templates\AdminPages\_export_form.html.twig:19 - Part-DB1\templates\AdminPages\_export_form.html.twig:19 - templates\AdminPages\_export_form.html.twig:19 - - - export.level.simple - Simple - - - - - Part-DB1\templates\AdminPages\_export_form.html.twig:20 - Part-DB1\templates\AdminPages\_export_form.html.twig:20 - templates\AdminPages\_export_form.html.twig:20 - - - export.level.extended - Étendu - - - - - Part-DB1\templates\AdminPages\_export_form.html.twig:21 - Part-DB1\templates\AdminPages\_export_form.html.twig:21 - templates\AdminPages\_export_form.html.twig:21 - - - export.level.full - Complet - - - - - Part-DB1\templates\AdminPages\_export_form.html.twig:31 - Part-DB1\templates\AdminPages\_export_form.html.twig:31 - templates\AdminPages\_export_form.html.twig:31 - - - export.include_children - Exporter également les sous éléments - - - - - Part-DB1\templates\AdminPages\_export_form.html.twig:39 - Part-DB1\templates\AdminPages\_export_form.html.twig:39 - templates\AdminPages\_export_form.html.twig:39 - - - export.btn - Exporter - - - - - Part-DB1\templates\AdminPages\_info.html.twig:4 - Part-DB1\templates\Parts\edit\edit_part_info.html.twig:12 - Part-DB1\templates\Parts\info\show_part_info.html.twig:24 - Part-DB1\templates\Parts\info\_extended_infos.html.twig:36 - Part-DB1\templates\AdminPages\_info.html.twig:4 - Part-DB1\templates\Parts\edit\edit_part_info.html.twig:12 - Part-DB1\templates\Parts\info\show_part_info.html.twig:24 - Part-DB1\templates\Parts\info\_extended_infos.html.twig:36 - templates\AdminPages\EntityAdminBase.html.twig:94 - templates\Parts\edit_part_info.html.twig:12 - templates\Parts\show_part_info.html.twig:11 - - - id.label - ID - - - - - Part-DB1\templates\AdminPages\_info.html.twig:11 - Part-DB1\templates\Parts\info\_attachments_info.html.twig:76 - Part-DB1\templates\Parts\info\_attachments_info.html.twig:77 - Part-DB1\templates\Parts\info\_extended_infos.html.twig:6 - Part-DB1\templates\Parts\info\_order_infos.html.twig:69 - Part-DB1\templates\Parts\info\_sidebar.html.twig:12 - Part-DB1\templates\Parts\lists\_info_card.html.twig:77 - Part-DB1\templates\AdminPages\_info.html.twig:11 - Part-DB1\templates\Parts\info\_attachments_info.html.twig:59 - Part-DB1\templates\Parts\info\_attachments_info.html.twig:60 - Part-DB1\templates\Parts\info\_extended_infos.html.twig:6 - Part-DB1\templates\Parts\info\_order_infos.html.twig:69 - Part-DB1\templates\Parts\info\_sidebar.html.twig:12 - Part-DB1\templates\Parts\lists\_info_card.html.twig:53 - templates\AdminPages\EntityAdminBase.html.twig:101 - templates\Parts\show_part_info.html.twig:248 - - - createdAt - Créé le - - - - - Part-DB1\templates\AdminPages\_info.html.twig:25 - Part-DB1\templates\Parts\info\_extended_infos.html.twig:21 - Part-DB1\templates\Parts\info\_sidebar.html.twig:8 - Part-DB1\templates\Parts\lists\_info_card.html.twig:73 - Part-DB1\templates\AdminPages\_info.html.twig:25 - Part-DB1\templates\Parts\info\_extended_infos.html.twig:21 - Part-DB1\templates\Parts\info\_sidebar.html.twig:8 - Part-DB1\templates\Parts\lists\_info_card.html.twig:49 - templates\AdminPages\EntityAdminBase.html.twig:114 - templates\Parts\show_part_info.html.twig:263 - - - lastModified - Dernière modification - - - - - Part-DB1\templates\AdminPages\_info.html.twig:38 - Part-DB1\templates\AdminPages\_info.html.twig:38 - - - entity.info.parts_count - Nombre de composants avec cet élément - - - - - Part-DB1\templates\AdminPages\_parameters.html.twig:6 - Part-DB1\templates\helper.twig:125 - Part-DB1\templates\Parts\edit\_specifications.html.twig:6 - - - specifications.property - Paramètre - - - - - Part-DB1\templates\AdminPages\_parameters.html.twig:7 - Part-DB1\templates\Parts\edit\_specifications.html.twig:7 - - - specifications.symbol - Symbole - - - - - Part-DB1\templates\AdminPages\_parameters.html.twig:8 - Part-DB1\templates\Parts\edit\_specifications.html.twig:8 - - - specifications.value_min - Min. - - - - - Part-DB1\templates\AdminPages\_parameters.html.twig:9 - Part-DB1\templates\Parts\edit\_specifications.html.twig:9 - - - specifications.value_typ - Typ. - - - - - Part-DB1\templates\AdminPages\_parameters.html.twig:10 - Part-DB1\templates\Parts\edit\_specifications.html.twig:10 - - - specifications.value_max - Max. - - - - - Part-DB1\templates\AdminPages\_parameters.html.twig:11 - Part-DB1\templates\Parts\edit\_specifications.html.twig:11 - - - specifications.unit - Unité - - - - - Part-DB1\templates\AdminPages\_parameters.html.twig:12 - Part-DB1\templates\Parts\edit\_specifications.html.twig:12 - - - specifications.text - Texte - - - - - Part-DB1\templates\AdminPages\_parameters.html.twig:13 - Part-DB1\templates\Parts\edit\_specifications.html.twig:13 - - - specifications.group - Groupe - - - - - Part-DB1\templates\AdminPages\_parameters.html.twig:26 - Part-DB1\templates\Parts\edit\_specifications.html.twig:26 - - - specification.create - Nouveau paramètre - - - - - Part-DB1\templates\AdminPages\_parameters.html.twig:31 - Part-DB1\templates\Parts\edit\_specifications.html.twig:31 - - - parameter.delete.confirm - Souhaitez-vous vraiment supprimer ce paramètre ? - - - - - Part-DB1\templates\attachment_list.html.twig:3 - Part-DB1\templates\attachment_list.html.twig:3 - - - attachment.list.title - Liste des fichiers joints - - - - - Part-DB1\templates\attachment_list.html.twig:10 - Part-DB1\templates\LogSystem\_log_table.html.twig:8 - Part-DB1\templates\Parts\lists\_parts_list.html.twig:6 - Part-DB1\templates\attachment_list.html.twig:10 - Part-DB1\templates\LogSystem\_log_table.html.twig:8 - Part-DB1\templates\Parts\lists\_parts_list.html.twig:6 - - - part_list.loading.caption - Chargement - - - - - Part-DB1\templates\attachment_list.html.twig:11 - Part-DB1\templates\LogSystem\_log_table.html.twig:9 - Part-DB1\templates\Parts\lists\_parts_list.html.twig:7 - Part-DB1\templates\attachment_list.html.twig:11 - Part-DB1\templates\LogSystem\_log_table.html.twig:9 - Part-DB1\templates\Parts\lists\_parts_list.html.twig:7 - - - part_list.loading.message - Cela peut prendre un moment.Si ce message ne disparaît pas, essayez de recharger la page. - - - - - Part-DB1\templates\base.html.twig:68 - Part-DB1\templates\base.html.twig:68 - templates\base.html.twig:246 - - - vendor.base.javascript_hint - Activez Javascipt pour profiter de toutes les fonctionnalités! - - - - - Part-DB1\templates\base.html.twig:73 - Part-DB1\templates\base.html.twig:73 - - - sidebar.big.toggle - Afficher/Cacher le panneau latéral -Show/Hide sidebar - - - - - Part-DB1\templates\base.html.twig:95 - Part-DB1\templates\base.html.twig:95 - templates\base.html.twig:271 - - - loading.caption - Chargement: - - - - - Part-DB1\templates\base.html.twig:96 - Part-DB1\templates\base.html.twig:96 - templates\base.html.twig:272 - - - loading.message - Cela peut prendre un moment.Si ce message ne disparaît pas, essayez de recharger la page. - - - - - Part-DB1\templates\base.html.twig:101 - Part-DB1\templates\base.html.twig:101 - templates\base.html.twig:277 - - - loading.bar - Chargement... - - - - - Part-DB1\templates\base.html.twig:112 - Part-DB1\templates\base.html.twig:112 - templates\base.html.twig:288 - - - back_to_top - Retour en haut de page - - - - - Part-DB1\templates\Form\permissionLayout.html.twig:35 - Part-DB1\templates\Form\permissionLayout.html.twig:35 - - - permission.edit.permission - Permissions - - - - - Part-DB1\templates\Form\permissionLayout.html.twig:36 - Part-DB1\templates\Form\permissionLayout.html.twig:36 - - - permission.edit.value - Valeur - - - - - Part-DB1\templates\Form\permissionLayout.html.twig:53 - Part-DB1\templates\Form\permissionLayout.html.twig:53 - - - permission.legend.title - Explication des états: - - - - - Part-DB1\templates\Form\permissionLayout.html.twig:57 - Part-DB1\templates\Form\permissionLayout.html.twig:57 - - - permission.legend.disallow - Interdire - - - - - Part-DB1\templates\Form\permissionLayout.html.twig:61 - Part-DB1\templates\Form\permissionLayout.html.twig:61 - - - permission.legend.allow - Autoriser - - - - - Part-DB1\templates\Form\permissionLayout.html.twig:65 - Part-DB1\templates\Form\permissionLayout.html.twig:65 - - - permission.legend.inherit - Hériter du groupe (parent) - - - - - Part-DB1\templates\helper.twig:3 - Part-DB1\templates\helper.twig:3 - - - bool.true - Vrai - - - - - Part-DB1\templates\helper.twig:5 - Part-DB1\templates\helper.twig:5 - - - bool.false - Faux - - - - - Part-DB1\templates\helper.twig:92 - Part-DB1\templates\helper.twig:87 - - - Yes - Oui - - - - - Part-DB1\templates\helper.twig:94 - Part-DB1\templates\helper.twig:89 - - - No - Non - - - - - Part-DB1\templates\helper.twig:126 - - - specifications.value - Valeur - - - - - Part-DB1\templates\homepage.html.twig:7 - Part-DB1\templates\homepage.html.twig:7 - templates\homepage.html.twig:7 - - - version.caption - Version - - - - - Part-DB1\templates\homepage.html.twig:22 - Part-DB1\templates\homepage.html.twig:22 - templates\homepage.html.twig:19 - - - homepage.license - Information de license - - - - - Part-DB1\templates\homepage.html.twig:31 - Part-DB1\templates\homepage.html.twig:31 - templates\homepage.html.twig:28 - - - homepage.github.caption - Page du projet - - - - - Part-DB1\templates\homepage.html.twig:31 - Part-DB1\templates\homepage.html.twig:31 - templates\homepage.html.twig:28 - - - homepage.github.text - Retrouvez les téléchargements, report de bugs, to-do-list etc. sur <a href="%href%" class="link-external" target="_blank">la page du projet GitHub</a> - - - - - Part-DB1\templates\homepage.html.twig:32 - Part-DB1\templates\homepage.html.twig:32 - templates\homepage.html.twig:29 - - - homepage.help.caption - Aide - - - - - Part-DB1\templates\homepage.html.twig:32 - Part-DB1\templates\homepage.html.twig:32 - templates\homepage.html.twig:29 - - - homepage.help.text - De l'aide et des conseils sont disponibles sur le Wiki de la <a href="%href%" class="link-external" target="_blank">page GitHub</a> - - - - - Part-DB1\templates\homepage.html.twig:33 - Part-DB1\templates\homepage.html.twig:33 - templates\homepage.html.twig:30 - - - homepage.forum.caption - Forum - - - - - Part-DB1\templates\homepage.html.twig:45 - Part-DB1\templates\homepage.html.twig:45 - new - - - homepage.last_activity - Activité récente - - - - - Part-DB1\templates\LabelSystem\dialog.html.twig:3 - Part-DB1\templates\LabelSystem\dialog.html.twig:6 - - - label_generator.title - Générateur d'étiquettes - - - - - Part-DB1\templates\LabelSystem\dialog.html.twig:16 - - - label_generator.common - Commun - - - - - Part-DB1\templates\LabelSystem\dialog.html.twig:20 - - - label_generator.advanced - Avancé - - - - - Part-DB1\templates\LabelSystem\dialog.html.twig:24 - - - label_generator.profiles - Profils - - - - - Part-DB1\templates\LabelSystem\dialog.html.twig:58 - - - label_generator.selected_profile - Profil actuellement sélectionné - - - - - Part-DB1\templates\LabelSystem\dialog.html.twig:62 - - - label_generator.edit_profile - Modifier le profil - - - - - Part-DB1\templates\LabelSystem\dialog.html.twig:75 - - - label_generator.load_profile - Charger le profil - - - - - Part-DB1\templates\LabelSystem\dialog.html.twig:102 - - - label_generator.download - Télécharger - - - - - Part-DB1\templates\LabelSystem\dropdown_macro.html.twig:3 - Part-DB1\templates\LabelSystem\dropdown_macro.html.twig:5 - - - label_generator.label_btn - Générer une étiquette - - - - - Part-DB1\templates\LabelSystem\dropdown_macro.html.twig:20 - - - label_generator.label_empty - Nouvelle étiquette vide - - - - - Part-DB1\templates\LabelSystem\Scanner\dialog.html.twig:3 - - - label_scanner.title - Lecteur d'étiquettes - - - - - Part-DB1\templates\LabelSystem\Scanner\dialog.html.twig:7 - - - label_scanner.no_cam_found.title - Aucune webcam trouvée - - - - - Part-DB1\templates\LabelSystem\Scanner\dialog.html.twig:7 - - - label_scanner.no_cam_found.text - Vous devez disposer d'une webcam et donner l'autorisation d'utiliser la fonction de scanner. Vous pouvez entrer le code à barres manuellement ci-dessous. - - - - - Part-DB1\templates\LabelSystem\Scanner\dialog.html.twig:27 - - - label_scanner.source_select - Sélectionnez une source - - - - - Part-DB1\templates\LogSystem\log_list.html.twig:3 - Part-DB1\templates\LogSystem\log_list.html.twig:3 - - - log.list.title - Journal système - - - - - Part-DB1\templates\LogSystem\_log_table.html.twig:1 - Part-DB1\templates\LogSystem\_log_table.html.twig:1 - new - - - log.undo.confirm_title - Annuler le changement / revenir à une date antérieure ? - - - - - Part-DB1\templates\LogSystem\_log_table.html.twig:2 - Part-DB1\templates\LogSystem\_log_table.html.twig:2 - new - - - log.undo.confirm_message - Voulez-vous annuler la modification donnée / réinitialiser l'élément à une date donnée ? - - - - - Part-DB1\templates\mail\base.html.twig:24 - Part-DB1\templates\mail\base.html.twig:24 - - - mail.footer.email_sent_by - Cet email a été envoyé automatiquement par - - - - - Part-DB1\templates\mail\base.html.twig:24 - Part-DB1\templates\mail\base.html.twig:24 - - - mail.footer.dont_reply - Ne répondez pas à cet email. - - - - - Part-DB1\templates\mail\pw_reset.html.twig:6 - Part-DB1\templates\mail\pw_reset.html.twig:6 - - - email.hi %name% - Bonjour %name% - - - - - Part-DB1\templates\mail\pw_reset.html.twig:7 - Part-DB1\templates\mail\pw_reset.html.twig:7 - - - email.pw_reset.message - Quelqu’un (surement vous) a demandé une réinitialisation de votre mot de passe.Si ce n'est pas le cas, ignorez simplement cet email. - - - - - Part-DB1\templates\mail\pw_reset.html.twig:9 - Part-DB1\templates\mail\pw_reset.html.twig:9 - - - email.pw_reset.button - Cliquez ici pour réinitialiser votre mot de passe - - - - - Part-DB1\templates\mail\pw_reset.html.twig:11 - Part-DB1\templates\mail\pw_reset.html.twig:11 - - - email.pw_reset.fallback - Si cela ne fonctionne pas pour vous, allez à <a href="%url%">%url%</a> et entrez les informations suivantes - - - - - Part-DB1\templates\mail\pw_reset.html.twig:16 - Part-DB1\templates\mail\pw_reset.html.twig:16 - - - email.pw_reset.username - Nom d'utilisateur - - - - - Part-DB1\templates\mail\pw_reset.html.twig:19 - Part-DB1\templates\mail\pw_reset.html.twig:19 - - - email.pw_reset.token - Jeton - - - - - Part-DB1\templates\mail\pw_reset.html.twig:24 - Part-DB1\templates\mail\pw_reset.html.twig:24 - - - email.pw_reset.valid_unit %date% - Le jeton de réinitialisation sera valable jusqu'au <i>%date%</i>. - - - - - Part-DB1\templates\Parts\edit\edit_form_styles.html.twig:18 - Part-DB1\templates\Parts\edit\edit_form_styles.html.twig:58 - Part-DB1\templates\Parts\edit\edit_form_styles.html.twig:78 - Part-DB1\templates\Parts\edit\edit_form_styles.html.twig:58 - - - orderdetail.delete - Supprimer - - - - - Part-DB1\templates\Parts\edit\edit_form_styles.html.twig:39 - Part-DB1\templates\Parts\edit\edit_form_styles.html.twig:39 - - - pricedetails.edit.min_qty - Quantité minimale de commande - - - - - Part-DB1\templates\Parts\edit\edit_form_styles.html.twig:40 - Part-DB1\templates\Parts\edit\edit_form_styles.html.twig:40 - - - pricedetails.edit.price - Prix - - - - - Part-DB1\templates\Parts\edit\edit_form_styles.html.twig:41 - Part-DB1\templates\Parts\edit\edit_form_styles.html.twig:41 - - - pricedetails.edit.price_qty - Pour la quantité - - - - - Part-DB1\templates\Parts\edit\edit_form_styles.html.twig:54 - Part-DB1\templates\Parts\edit\edit_form_styles.html.twig:54 - - - pricedetail.create - Ajouter prix - - - - - Part-DB1\templates\Parts\edit\edit_part_info.html.twig:4 - Part-DB1\templates\Parts\edit\edit_part_info.html.twig:4 - templates\Parts\edit_part_info.html.twig:4 - - - part.edit.title - Éditer le composant - - - - - Part-DB1\templates\Parts\edit\edit_part_info.html.twig:9 - Part-DB1\templates\Parts\edit\edit_part_info.html.twig:9 - templates\Parts\edit_part_info.html.twig:9 - - - part.edit.card_title - Éditer le composant - - - - - Part-DB1\templates\Parts\edit\edit_part_info.html.twig:22 - Part-DB1\templates\Parts\edit\edit_part_info.html.twig:22 - - - part.edit.tab.common - Général - - - - - Part-DB1\templates\Parts\edit\edit_part_info.html.twig:28 - Part-DB1\templates\Parts\edit\edit_part_info.html.twig:28 - - - part.edit.tab.manufacturer - Fabricant - - - - - Part-DB1\templates\Parts\edit\edit_part_info.html.twig:34 - Part-DB1\templates\Parts\edit\edit_part_info.html.twig:34 - - - part.edit.tab.advanced - Avancé - - - - - Part-DB1\templates\Parts\edit\edit_part_info.html.twig:40 - Part-DB1\templates\Parts\edit\edit_part_info.html.twig:40 - - - part.edit.tab.part_lots - Stocks - - - - - Part-DB1\templates\Parts\edit\edit_part_info.html.twig:46 - Part-DB1\templates\Parts\edit\edit_part_info.html.twig:46 - - - part.edit.tab.attachments - Fichiers joints - - - - - Part-DB1\templates\Parts\edit\edit_part_info.html.twig:52 - Part-DB1\templates\Parts\edit\edit_part_info.html.twig:52 - - - part.edit.tab.orderdetails - Informations pour la commande - - - - - Part-DB1\templates\Parts\edit\edit_part_info.html.twig:58 - - - part.edit.tab.specifications - Caractéristiques - - - - - Part-DB1\templates\Parts\edit\edit_part_info.html.twig:64 - Part-DB1\templates\Parts\edit\edit_part_info.html.twig:58 - - - part.edit.tab.comment - Commentaire - - - - - Part-DB1\templates\Parts\edit\new_part.html.twig:8 - Part-DB1\templates\Parts\edit\new_part.html.twig:8 - templates\Parts\new_part.html.twig:8 - - - part.new.card_title - Créer un nouveau composant - - - - - Part-DB1\templates\Parts\edit\_lots.html.twig:5 - Part-DB1\templates\Parts\edit\_lots.html.twig:5 - - - part_lot.delete - Supprimer - - - - - Part-DB1\templates\Parts\edit\_lots.html.twig:28 - Part-DB1\templates\Parts\edit\_lots.html.twig:28 - - - part_lot.create - Créer un inventaire - - - - - Part-DB1\templates\Parts\edit\_orderdetails.html.twig:13 - Part-DB1\templates\Parts\edit\_orderdetails.html.twig:13 - - - orderdetail.create - Ajouter un fournisseur - - - - - Part-DB1\templates\Parts\edit\_orderdetails.html.twig:18 - Part-DB1\templates\Parts\edit\_orderdetails.html.twig:18 - - - pricedetails.edit.delete.confirm - Voulez-vous vraiment supprimer ce prix ? Cela ne peut pas être défait ! - - - - - Part-DB1\templates\Parts\edit\_orderdetails.html.twig:62 - Part-DB1\templates\Parts\edit\_orderdetails.html.twig:61 - - - orderdetails.edit.delete.confirm - Voulez-vous vraiment supprimer ce fournisseur ? Cela ne peut pas être défait ! - - - - - Part-DB1\templates\Parts\info\show_part_info.html.twig:4 - Part-DB1\templates\Parts\info\show_part_info.html.twig:19 - Part-DB1\templates\Parts\info\show_part_info.html.twig:4 - Part-DB1\templates\Parts\info\show_part_info.html.twig:19 - templates\Parts\show_part_info.html.twig:4 - templates\Parts\show_part_info.html.twig:9 - - - part.info.title - Informations détaillées pour - - - - - Part-DB1\templates\Parts\info\show_part_info.html.twig:47 - Part-DB1\templates\Parts\info\show_part_info.html.twig:47 - - - part.part_lots.label - Stocks - - - - - Part-DB1\templates\Parts\info\show_part_info.html.twig:56 - Part-DB1\templates\Parts\lists\_info_card.html.twig:43 - Part-DB1\templates\_navbar_search.html.twig:31 - Part-DB1\templates\_navbar_search.html.twig:26 - templates\base.html.twig:62 - templates\Parts\show_part_info.html.twig:74 - src\Form\PartType.php:86 - - - comment.label - Commentaire - - - - - Part-DB1\templates\Parts\info\show_part_info.html.twig:64 - - - part.info.specifications - Caractéristiques - - - - - Part-DB1\templates\Parts\info\show_part_info.html.twig:74 - Part-DB1\templates\Parts\info\show_part_info.html.twig:64 - templates\Parts\show_part_info.html.twig:82 - - - attachment.labelp - Fichiers joints - - - - - Part-DB1\templates\Parts\info\show_part_info.html.twig:83 - Part-DB1\templates\Parts\info\show_part_info.html.twig:71 - templates\Parts\show_part_info.html.twig:88 - - - vendor.partinfo.shopping_infos - Informations de commande - - - - - Part-DB1\templates\Parts\info\show_part_info.html.twig:91 - Part-DB1\templates\Parts\info\show_part_info.html.twig:78 - templates\Parts\show_part_info.html.twig:94 - - - vendor.partinfo.history - Historique - - - - - Part-DB1\templates\Parts\info\show_part_info.html.twig:97 - Part-DB1\templates\_sidebar.html.twig:54 - Part-DB1\templates\_sidebar.html.twig:13 - Part-DB1\templates\Parts\info\show_part_info.html.twig:84 - Part-DB1\templates\_sidebar.html.twig:54 - Part-DB1\templates\_sidebar.html.twig:13 - templates\base.html.twig:176 - templates\base.html.twig:203 - templates\base.html.twig:217 - templates\base.html.twig:231 - templates\Parts\show_part_info.html.twig:100 - - - tools.label - Outils - - - - - Part-DB1\templates\Parts\info\show_part_info.html.twig:103 - Part-DB1\templates\Parts\info\show_part_info.html.twig:90 - - - extended_info.label - Informations complémentaires - - - - - Part-DB1\templates\Parts\info\_attachments_info.html.twig:7 - Part-DB1\templates\Parts\info\_attachments_info.html.twig:7 - - - attachment.name - Nom - - - - - Part-DB1\templates\Parts\info\_attachments_info.html.twig:8 - Part-DB1\templates\Parts\info\_attachments_info.html.twig:8 - - - attachment.attachment_type - Type de fichier joint - - - - - Part-DB1\templates\Parts\info\_attachments_info.html.twig:9 - Part-DB1\templates\Parts\info\_attachments_info.html.twig:9 - - - attachment.file_name - Nom du fichier - - - - - Part-DB1\templates\Parts\info\_attachments_info.html.twig:10 - Part-DB1\templates\Parts\info\_attachments_info.html.twig:10 - - - attachment.file_size - Taille du fichier - - - - - Part-DB1\templates\Parts\info\_attachments_info.html.twig:54 - - - attachment.preview - Aperçu de l'image - - - - - Part-DB1\templates\Parts\info\_attachments_info.html.twig:67 - Part-DB1\templates\Parts\info\_attachments_info.html.twig:50 - - - attachment.download - Téléchargement - - - - - Part-DB1\templates\Parts\info\_extended_infos.html.twig:11 - Part-DB1\templates\Parts\info\_extended_infos.html.twig:11 - new - - - user.creating_user - Utilisateur qui a créé ce composant - - - - - Part-DB1\templates\Parts\info\_extended_infos.html.twig:13 - Part-DB1\templates\Parts\info\_extended_infos.html.twig:28 - Part-DB1\templates\Parts\info\_extended_infos.html.twig:50 - Part-DB1\templates\Parts\info\_extended_infos.html.twig:13 - Part-DB1\templates\Parts\info\_extended_infos.html.twig:28 - Part-DB1\templates\Parts\info\_extended_infos.html.twig:50 - - - Unknown - Inconnu - - - - - Part-DB1\templates\Parts\info\_extended_infos.html.twig:15 - Part-DB1\templates\Parts\info\_extended_infos.html.twig:30 - Part-DB1\templates\Parts\info\_extended_infos.html.twig:15 - Part-DB1\templates\Parts\info\_extended_infos.html.twig:30 - new - - - accessDenied - Accès refusé - - - - - Part-DB1\templates\Parts\info\_extended_infos.html.twig:26 - Part-DB1\templates\Parts\info\_extended_infos.html.twig:26 - new - - - user.last_editing_user - Utilisateur qui a édité ce composant en dernier - - - - - Part-DB1\templates\Parts\info\_extended_infos.html.twig:41 - Part-DB1\templates\Parts\info\_extended_infos.html.twig:41 - - - part.isFavorite - Favoris - - - - - Part-DB1\templates\Parts\info\_extended_infos.html.twig:46 - Part-DB1\templates\Parts\info\_extended_infos.html.twig:46 - - - part.minOrderAmount - Quantité minimale de commande - - - - - Part-DB1\templates\Parts\info\_main_infos.html.twig:8 - Part-DB1\templates\_navbar_search.html.twig:46 - Part-DB1\src\Services\ElementTypeNameGenerator.php:84 - Part-DB1\templates\Parts\info\_main_infos.html.twig:8 - Part-DB1\templates\_navbar_search.html.twig:41 - Part-DB1\src\Services\ElementTypeNameGenerator.php:84 - templates\base.html.twig:70 - templates\Parts\show_part_info.html.twig:24 - src\Form\PartType.php:80 - - - manufacturer.label - Fabricant - - - - - Part-DB1\templates\Parts\info\_main_infos.html.twig:24 - Part-DB1\templates\_navbar_search.html.twig:11 - templates\base.html.twig:54 - src\Form\PartType.php:62 - - - name.label - Nom - - - - - Part-DB1\templates\Parts\info\_main_infos.html.twig:27 - Part-DB1\templates\Parts\info\_main_infos.html.twig:27 - new - - - part.back_to_info - Retour à la version actuelle - - - - - Part-DB1\templates\Parts\info\_main_infos.html.twig:32 - Part-DB1\templates\_navbar_search.html.twig:19 - Part-DB1\templates\Parts\info\_main_infos.html.twig:32 - Part-DB1\templates\_navbar_search.html.twig:18 - templates\base.html.twig:58 - templates\Parts\show_part_info.html.twig:31 - src\Form\PartType.php:65 - - - description.label - Description - - - - - Part-DB1\templates\Parts\info\_main_infos.html.twig:34 - Part-DB1\templates\_navbar_search.html.twig:15 - Part-DB1\src\Services\ElementTypeNameGenerator.php:80 - Part-DB1\templates\Parts\info\_main_infos.html.twig:34 - Part-DB1\templates\_navbar_search.html.twig:14 - Part-DB1\src\Services\ElementTypeNameGenerator.php:80 - templates\base.html.twig:56 - templates\Parts\show_part_info.html.twig:32 - src\Form\PartType.php:74 - - - category.label - Catégorie - - - - - Part-DB1\templates\Parts\info\_main_infos.html.twig:39 - Part-DB1\templates\Parts\info\_main_infos.html.twig:39 - templates\Parts\show_part_info.html.twig:42 - src\Form\PartType.php:69 - - - instock.label - En stock - - - - - Part-DB1\templates\Parts\info\_main_infos.html.twig:41 - Part-DB1\templates\Parts\info\_main_infos.html.twig:41 - templates\Parts\show_part_info.html.twig:44 - src\Form\PartType.php:72 - - - mininstock.label - Stock minimum - - - - - Part-DB1\templates\Parts\info\_main_infos.html.twig:45 - Part-DB1\templates\_navbar_search.html.twig:52 - Part-DB1\src\Services\ElementTypeNameGenerator.php:83 - Part-DB1\templates\Parts\info\_main_infos.html.twig:45 - Part-DB1\templates\_navbar_search.html.twig:47 - Part-DB1\src\Services\ElementTypeNameGenerator.php:83 - templates\base.html.twig:73 - templates\Parts\show_part_info.html.twig:47 - - - footprint.label - Empreinte - - - - - Part-DB1\templates\Parts\info\_main_infos.html.twig:56 - Part-DB1\templates\Parts\info\_main_infos.html.twig:59 - Part-DB1\templates\Parts\info\_main_infos.html.twig:57 - Part-DB1\templates\Parts\info\_main_infos.html.twig:60 - templates\Parts\show_part_info.html.twig:51 - - - part.avg_price.label - Prix moyen - - - - - Part-DB1\templates\Parts\info\_order_infos.html.twig:5 - Part-DB1\templates\Parts\info\_order_infos.html.twig:5 - - - part.supplier.name - Nom - - - - - Part-DB1\templates\Parts\info\_order_infos.html.twig:6 - Part-DB1\templates\Parts\info\_order_infos.html.twig:6 - - - part.supplier.partnr - Lien/Code cmd. - - - - - Part-DB1\templates\Parts\info\_order_infos.html.twig:28 - Part-DB1\templates\Parts\info\_order_infos.html.twig:28 - - - part.order.minamount - Nombre minimum - - - - - Part-DB1\templates\Parts\info\_order_infos.html.twig:29 - Part-DB1\templates\Parts\info\_order_infos.html.twig:29 - - - part.order.price - Prix - - - - - Part-DB1\templates\Parts\info\_order_infos.html.twig:31 - Part-DB1\templates\Parts\info\_order_infos.html.twig:31 - - - part.order.single_price - Prix unitaire - - - - - Part-DB1\templates\Parts\info\_order_infos.html.twig:71 - Part-DB1\templates\Parts\info\_order_infos.html.twig:71 - - - edit.caption_short - Éditer - - - - - Part-DB1\templates\Parts\info\_order_infos.html.twig:72 - Part-DB1\templates\Parts\info\_order_infos.html.twig:72 - - - delete.caption - Supprimer - - - - - Part-DB1\templates\Parts\info\_part_lots.html.twig:7 - Part-DB1\templates\Parts\info\_part_lots.html.twig:6 - - - part_lots.description - Description - - - - - Part-DB1\templates\Parts\info\_part_lots.html.twig:8 - Part-DB1\templates\Parts\info\_part_lots.html.twig:7 - - - part_lots.storage_location - Emplacement de stockage - - - - - Part-DB1\templates\Parts\info\_part_lots.html.twig:9 - Part-DB1\templates\Parts\info\_part_lots.html.twig:8 - - - part_lots.amount - Quantité - - - - - Part-DB1\templates\Parts\info\_part_lots.html.twig:24 - Part-DB1\templates\Parts\info\_part_lots.html.twig:22 - - - part_lots.location_unknown - Emplacement de stockage inconnu - - - - - Part-DB1\templates\Parts\info\_part_lots.html.twig:31 - Part-DB1\templates\Parts\info\_part_lots.html.twig:29 - - - part_lots.instock_unknown - Quantité inconnue - - - - - Part-DB1\templates\Parts\info\_part_lots.html.twig:40 - Part-DB1\templates\Parts\info\_part_lots.html.twig:38 - - - part_lots.expiration_date - Date d'expiration - - - - - Part-DB1\templates\Parts\info\_part_lots.html.twig:48 - Part-DB1\templates\Parts\info\_part_lots.html.twig:46 - - - part_lots.is_expired - Expiré - - - - - Part-DB1\templates\Parts\info\_part_lots.html.twig:55 - Part-DB1\templates\Parts\info\_part_lots.html.twig:53 - - - part_lots.need_refill - Doit être rempli à nouveau - - - - - Part-DB1\templates\Parts\info\_picture.html.twig:15 - Part-DB1\templates\Parts\info\_picture.html.twig:15 - - - part.info.prev_picture - Image précédente - - - - - Part-DB1\templates\Parts\info\_picture.html.twig:19 - Part-DB1\templates\Parts\info\_picture.html.twig:19 - - - part.info.next_picture - Image suivante - - - - - Part-DB1\templates\Parts\info\_sidebar.html.twig:21 - Part-DB1\templates\Parts\info\_sidebar.html.twig:21 - - - part.mass.tooltip - Poids - - - - - Part-DB1\templates\Parts\info\_sidebar.html.twig:30 - Part-DB1\templates\Parts\info\_sidebar.html.twig:30 - - - part.needs_review.badge - Révision nécessaire - - - - - Part-DB1\templates\Parts\info\_sidebar.html.twig:39 - Part-DB1\templates\Parts\info\_sidebar.html.twig:39 - - - part.favorite.badge - Favoris - - - - - Part-DB1\templates\Parts\info\_sidebar.html.twig:47 - Part-DB1\templates\Parts\info\_sidebar.html.twig:47 - - - part.obsolete.badge - N'est plus disponible - - - - - Part-DB1\templates\Parts\info\_specifications.html.twig:10 - - - parameters.extracted_from_description - Automatiquement extrait de la description - - - - - Part-DB1\templates\Parts\info\_specifications.html.twig:15 - - - parameters.auto_extracted_from_comment - Automatiquement extrait du commentaire - - - - - Part-DB1\templates\Parts\info\_tools.html.twig:6 - Part-DB1\templates\Parts\info\_tools.html.twig:4 - templates\Parts\show_part_info.html.twig:125 - - - part.edit.btn - Éditer - - - - - Part-DB1\templates\Parts\info\_tools.html.twig:16 - Part-DB1\templates\Parts\info\_tools.html.twig:14 - templates\Parts\show_part_info.html.twig:135 - - - part.clone.btn - Duplication - - - - - Part-DB1\templates\Parts\info\_tools.html.twig:24 - Part-DB1\templates\Parts\lists\_action_bar.html.twig:4 - templates\Parts\show_part_info.html.twig:143 - - - part.create.btn - Créer un nouveau composant - - - - - Part-DB1\templates\Parts\info\_tools.html.twig:31 - Part-DB1\templates\Parts\info\_tools.html.twig:29 - - - part.delete.confirm_title - Voulez-vous vraiment supprimer ce composant ? - - - - - Part-DB1\templates\Parts\info\_tools.html.twig:32 - Part-DB1\templates\Parts\info\_tools.html.twig:30 - - - part.delete.message - Le composant et toutes les informations associées (stocks, fichiers joints, etc.) sont supprimés. Cela ne pourra pas être annulé. - - - - - Part-DB1\templates\Parts\info\_tools.html.twig:39 - Part-DB1\templates\Parts\info\_tools.html.twig:37 - - - part.delete - Supprimer le composant - - - - - Part-DB1\templates\Parts\lists\all_list.html.twig:4 - Part-DB1\templates\Parts\lists\all_list.html.twig:4 - - - parts_list.all.title - Tous les composants - - - - - Part-DB1\templates\Parts\lists\category_list.html.twig:4 - Part-DB1\templates\Parts\lists\category_list.html.twig:4 - - - parts_list.category.title - Composants avec catégorie - - - - - Part-DB1\templates\Parts\lists\footprint_list.html.twig:4 - Part-DB1\templates\Parts\lists\footprint_list.html.twig:4 - - - parts_list.footprint.title - Composants avec empreinte - - - - - Part-DB1\templates\Parts\lists\manufacturer_list.html.twig:4 - Part-DB1\templates\Parts\lists\manufacturer_list.html.twig:4 - - - parts_list.manufacturer.title - Composants avec fabricant - - - - - Part-DB1\templates\Parts\lists\search_list.html.twig:4 - Part-DB1\templates\Parts\lists\search_list.html.twig:4 - - - parts_list.search.title - Recherche de composants - - - - - Part-DB1\templates\Parts\lists\store_location_list.html.twig:4 - Part-DB1\templates\Parts\lists\store_location_list.html.twig:4 - - - parts_list.storelocation.title - Composants avec lieu de stockage - - - - - Part-DB1\templates\Parts\lists\supplier_list.html.twig:4 - Part-DB1\templates\Parts\lists\supplier_list.html.twig:4 - - - parts_list.supplier.title - Composants avec fournisseur - - - - - Part-DB1\templates\Parts\lists\tags_list.html.twig:4 - Part-DB1\templates\Parts\lists\tags_list.html.twig:4 - - - parts_list.tags.title - Composants avec tag - - - - - Part-DB1\templates\Parts\lists\_info_card.html.twig:22 - Part-DB1\templates\Parts\lists\_info_card.html.twig:17 - - - entity.info.common.tab - Général - - - - - Part-DB1\templates\Parts\lists\_info_card.html.twig:26 - Part-DB1\templates\Parts\lists\_info_card.html.twig:20 - - - entity.info.statistics.tab - Statistiques - - - - - Part-DB1\templates\Parts\lists\_info_card.html.twig:31 - - - entity.info.attachments.tab - Pièces jointes - - - - - Part-DB1\templates\Parts\lists\_info_card.html.twig:37 - - - entity.info.parameters.tab - Caractéristiques - - - - - Part-DB1\templates\Parts\lists\_info_card.html.twig:54 - Part-DB1\templates\Parts\lists\_info_card.html.twig:30 - - - entity.info.name - Nom - - - - - Part-DB1\templates\Parts\lists\_info_card.html.twig:58 - Part-DB1\templates\Parts\lists\_info_card.html.twig:96 - Part-DB1\templates\Parts\lists\_info_card.html.twig:34 - Part-DB1\templates\Parts\lists\_info_card.html.twig:67 - - - entity.info.parent - Parent - - - - - Part-DB1\templates\Parts\lists\_info_card.html.twig:70 - Part-DB1\templates\Parts\lists\_info_card.html.twig:46 - - - entity.edit.btn - Éditer - - - - - Part-DB1\templates\Parts\lists\_info_card.html.twig:92 - Part-DB1\templates\Parts\lists\_info_card.html.twig:63 - - - entity.info.children_count - Nombre de sous-éléments - - - - - Part-DB1\templates\security\2fa_base_form.html.twig:3 - Part-DB1\templates\security\2fa_base_form.html.twig:5 - Part-DB1\templates\security\2fa_base_form.html.twig:3 - Part-DB1\templates\security\2fa_base_form.html.twig:5 - - - tfa.check.title - Authentification à deux facteurs requise - - - - - Part-DB1\templates\security\2fa_base_form.html.twig:39 - Part-DB1\templates\security\2fa_base_form.html.twig:39 - - - tfa.code.trusted_pc - Il s'agit d'un ordinateur de confiance (si cette fonction est activée, aucune autre requête à deux facteurs n'est effectuée sur cet ordinateur) - - - - - Part-DB1\templates\security\2fa_base_form.html.twig:52 - Part-DB1\templates\security\login.html.twig:58 - Part-DB1\templates\security\2fa_base_form.html.twig:52 - Part-DB1\templates\security\login.html.twig:58 - - - login.btn - Connexion - - - - - Part-DB1\templates\security\2fa_base_form.html.twig:53 - Part-DB1\templates\security\U2F\u2f_login.html.twig:13 - Part-DB1\templates\_navbar.html.twig:42 - Part-DB1\templates\security\2fa_base_form.html.twig:53 - Part-DB1\templates\security\U2F\u2f_login.html.twig:13 - Part-DB1\templates\_navbar.html.twig:40 - - - user.logout - Déconnexion - - - - - Part-DB1\templates\security\2fa_form.html.twig:6 - Part-DB1\templates\security\2fa_form.html.twig:6 - - - tfa.check.code.label - Code d'application de l'authentificateur - - - - - Part-DB1\templates\security\2fa_form.html.twig:10 - Part-DB1\templates\security\2fa_form.html.twig:10 - - - tfa.check.code.help - Entrez le code à 6 chiffres de votre application d'authentification ou l'un de vos codes de secours si l'authentificateur n'est pas disponible. - - - - - Part-DB1\templates\security\login.html.twig:3 - Part-DB1\templates\security\login.html.twig:3 - templates\security\login.html.twig:3 - - - login.title - Connexion - - - - - Part-DB1\templates\security\login.html.twig:7 - Part-DB1\templates\security\login.html.twig:7 - templates\security\login.html.twig:7 - - - login.card_title - Connexion - - - - - Part-DB1\templates\security\login.html.twig:31 - Part-DB1\templates\security\login.html.twig:31 - templates\security\login.html.twig:31 - - - login.username.label - Nom d'utilisateur - - - - - Part-DB1\templates\security\login.html.twig:34 - Part-DB1\templates\security\login.html.twig:34 - templates\security\login.html.twig:34 - - - login.username.placeholder - Nom d'utilisateur - - - - - Part-DB1\templates\security\login.html.twig:38 - Part-DB1\templates\security\login.html.twig:38 - templates\security\login.html.twig:38 - - - login.password.label - Mot de passe - - - - - Part-DB1\templates\security\login.html.twig:40 - Part-DB1\templates\security\login.html.twig:40 - templates\security\login.html.twig:40 - - - login.password.placeholder - Mot de passe - - - - - Part-DB1\templates\security\login.html.twig:50 - Part-DB1\templates\security\login.html.twig:50 - templates\security\login.html.twig:50 - - - login.rememberme - Rester connecté (non recommandé sur les ordinateurs publics) - - - - - Part-DB1\templates\security\login.html.twig:64 - Part-DB1\templates\security\login.html.twig:64 - - - pw_reset.password_forget - Nom d'utilisateur/mot de passe oublié ? - - - - - Part-DB1\templates\security\pw_reset_new_pw.html.twig:5 - Part-DB1\templates\security\pw_reset_new_pw.html.twig:5 - - - pw_reset.new_pw.header.title - Définir un nouveau mot de passe - - - - - Part-DB1\templates\security\pw_reset_request.html.twig:5 - Part-DB1\templates\security\pw_reset_request.html.twig:5 - - - pw_reset.request.header.title - Demander un nouveau mot de passe - - - - - Part-DB1\templates\security\U2F\u2f_login.html.twig:7 - Part-DB1\templates\security\U2F\u2f_register.html.twig:10 - Part-DB1\templates\security\U2F\u2f_login.html.twig:7 - Part-DB1\templates\security\U2F\u2f_register.html.twig:10 - - - tfa_u2f.http_warning - Vous accédez à cette page en utilisant la méthode HTTP non sécurisée, donc U2F ne fonctionnera probablement pas (message d'erreur "Bad Request"). Demandez à un administrateur de mettre en place la méthode HTTPS sécurisée si vous souhaitez utiliser des clés de sécurité. - - - - - Part-DB1\templates\security\U2F\u2f_login.html.twig:10 - Part-DB1\templates\security\U2F\u2f_register.html.twig:22 - Part-DB1\templates\security\U2F\u2f_login.html.twig:10 - Part-DB1\templates\security\U2F\u2f_register.html.twig:22 - - - r_u2f_two_factor.pressbutton - Veuillez insérer la clé de sécurité et appuyer sur le bouton ! - - - - - Part-DB1\templates\security\U2F\u2f_register.html.twig:3 - Part-DB1\templates\security\U2F\u2f_register.html.twig:3 - - - tfa_u2f.add_key.title - Ajouter une clé de sécurité - - - - - Part-DB1\templates\security\U2F\u2f_register.html.twig:6 - Part-DB1\templates\Users\_2fa_settings.html.twig:111 - Part-DB1\templates\security\U2F\u2f_register.html.twig:6 - Part-DB1\templates\Users\_2fa_settings.html.twig:111 - - - tfa_u2f.explanation - À l'aide d'une clé de sécurité compatible U2F/FIDO (par exemple YubiKey ou NitroKey), une authentification à deux facteurs sûre et pratique peut être obtenue. Les clés de sécurité peuvent être enregistrées ici, et si une vérification à deux facteurs est nécessaire, il suffit d'insérer la clé via USB ou de la taper sur le dispositif via NFC. - - - - - Part-DB1\templates\security\U2F\u2f_register.html.twig:7 - Part-DB1\templates\security\U2F\u2f_register.html.twig:7 - - - tfa_u2f.add_key.backup_hint - Pour garantir l'accès même en cas de perte de la clé, il est recommandé d'enregistrer une deuxième clé en guise de sauvegarde et de la conserver dans un endroit sûr ! - - - - - Part-DB1\templates\security\U2F\u2f_register.html.twig:16 - Part-DB1\templates\security\U2F\u2f_register.html.twig:16 - - - r_u2f_two_factor.name - Afficher le nom de la clé (par exemple, sauvegarde) - - - - - Part-DB1\templates\security\U2F\u2f_register.html.twig:19 - Part-DB1\templates\security\U2F\u2f_register.html.twig:19 - - - tfa_u2f.add_key.add_button - Ajouter une clé de sécurité - - - - - Part-DB1\templates\security\U2F\u2f_register.html.twig:27 - Part-DB1\templates\security\U2F\u2f_register.html.twig:27 - - - tfa_u2f.add_key.back_to_settings - Retour aux paramètres - - - - - Part-DB1\templates\Statistics\statistics.html.twig:5 - Part-DB1\templates\Statistics\statistics.html.twig:8 - Part-DB1\templates\Statistics\statistics.html.twig:5 - Part-DB1\templates\Statistics\statistics.html.twig:8 - new - - - statistics.title - Statistiques - - - - - Part-DB1\templates\Statistics\statistics.html.twig:14 - Part-DB1\templates\Statistics\statistics.html.twig:14 - new - - - statistics.parts - Composants - - - - - Part-DB1\templates\Statistics\statistics.html.twig:19 - Part-DB1\templates\Statistics\statistics.html.twig:19 - new - - - statistics.data_structures - Structures des données - - - - - Part-DB1\templates\Statistics\statistics.html.twig:24 - Part-DB1\templates\Statistics\statistics.html.twig:24 - new - - - statistics.attachments - Fichiers joints - - - - - Part-DB1\templates\Statistics\statistics.html.twig:34 - Part-DB1\templates\Statistics\statistics.html.twig:59 - Part-DB1\templates\Statistics\statistics.html.twig:104 - Part-DB1\templates\Statistics\statistics.html.twig:34 - Part-DB1\templates\Statistics\statistics.html.twig:59 - Part-DB1\templates\Statistics\statistics.html.twig:104 - new - - - statistics.property - Propriété - - - - - Part-DB1\templates\Statistics\statistics.html.twig:35 - Part-DB1\templates\Statistics\statistics.html.twig:60 - Part-DB1\templates\Statistics\statistics.html.twig:105 - Part-DB1\templates\Statistics\statistics.html.twig:35 - Part-DB1\templates\Statistics\statistics.html.twig:60 - Part-DB1\templates\Statistics\statistics.html.twig:105 - new - - - statistics.value - Valeur - - - - - Part-DB1\templates\Statistics\statistics.html.twig:40 - Part-DB1\templates\Statistics\statistics.html.twig:40 - new - - - statistics.distinct_parts_count - Nombre de composants distincts - - - - - Part-DB1\templates\Statistics\statistics.html.twig:44 - Part-DB1\templates\Statistics\statistics.html.twig:44 - new - - - statistics.parts_instock_sum - Somme de tout les composants en stock - - - - - Part-DB1\templates\Statistics\statistics.html.twig:48 - Part-DB1\templates\Statistics\statistics.html.twig:48 - new - - - statistics.parts_with_price - Nombre de composants avec information de prix - - - - - Part-DB1\templates\Statistics\statistics.html.twig:65 - Part-DB1\templates\Statistics\statistics.html.twig:65 - new - - - statistics.categories_count - Nombre de catégories - - - - - Part-DB1\templates\Statistics\statistics.html.twig:69 - Part-DB1\templates\Statistics\statistics.html.twig:69 - new - - - statistics.footprints_count - Nombre d'empreintes - - - - - Part-DB1\templates\Statistics\statistics.html.twig:73 - Part-DB1\templates\Statistics\statistics.html.twig:73 - new - - - statistics.manufacturers_count - Nombre de fabricants - - - - - Part-DB1\templates\Statistics\statistics.html.twig:77 - Part-DB1\templates\Statistics\statistics.html.twig:77 - new - - - statistics.storelocations_count - Nombre d'emplacements de stockage - - - - - Part-DB1\templates\Statistics\statistics.html.twig:81 - Part-DB1\templates\Statistics\statistics.html.twig:81 - new - - - statistics.suppliers_count - Nombre de fournisseurs - - - - - Part-DB1\templates\Statistics\statistics.html.twig:85 - Part-DB1\templates\Statistics\statistics.html.twig:85 - new - - - statistics.currencies_count - Nombre de devises - - - - - Part-DB1\templates\Statistics\statistics.html.twig:89 - Part-DB1\templates\Statistics\statistics.html.twig:89 - new - - - statistics.measurement_units_count - Nombre d'unités de mesure - - - - - Part-DB1\templates\Statistics\statistics.html.twig:93 - Part-DB1\templates\Statistics\statistics.html.twig:93 - new - - - statistics.devices_count - Nombre de projets - - - - - Part-DB1\templates\Statistics\statistics.html.twig:110 - Part-DB1\templates\Statistics\statistics.html.twig:110 - new - - - statistics.attachment_types_count - Nombre de types de fichiers joints - - - - - Part-DB1\templates\Statistics\statistics.html.twig:114 - Part-DB1\templates\Statistics\statistics.html.twig:114 - new - - - statistics.all_attachments_count - Total des pièces jointes - - - - - Part-DB1\templates\Statistics\statistics.html.twig:118 - Part-DB1\templates\Statistics\statistics.html.twig:118 - new - - - statistics.user_uploaded_attachments_count - Nombre de fichiers joints envoyées - - - - - Part-DB1\templates\Statistics\statistics.html.twig:122 - Part-DB1\templates\Statistics\statistics.html.twig:122 - new - - - statistics.private_attachments_count - Nombre de fichiers joints privés - - - - - Part-DB1\templates\Statistics\statistics.html.twig:126 - Part-DB1\templates\Statistics\statistics.html.twig:126 - new - - - statistics.external_attachments_count - Nombre de fichiers joints externes - - - - - Part-DB1\templates\Users\backup_codes.html.twig:3 - Part-DB1\templates\Users\backup_codes.html.twig:9 - Part-DB1\templates\Users\backup_codes.html.twig:3 - Part-DB1\templates\Users\backup_codes.html.twig:9 - - - tfa_backup.codes.title - Codes de secours - - - - - Part-DB1\templates\Users\backup_codes.html.twig:12 - Part-DB1\templates\Users\backup_codes.html.twig:12 - - - tfa_backup.codes.explanation - Imprimez ces codes et conservez-les dans un endroit sûr ! - - - - - Part-DB1\templates\Users\backup_codes.html.twig:13 - Part-DB1\templates\Users\backup_codes.html.twig:13 - - - tfa_backup.codes.help - Si vous n'avez plus accès à votre appareil avec l'application d'authentification (smartphone perdu, perte de données, etc.), vous pouvez utiliser un de ces codes pour accéder à votre compte et éventuellement configurer une nouvelle application d'authentification. Chacun de ces codes peut être utilisé une fois, il est recommandé de supprimer les codes utilisés. Toute personne ayant accès à ces codes peut potentiellement accéder à votre compte, alors gardez-les en lieu sûr. - - - - - Part-DB1\templates\Users\backup_codes.html.twig:16 - Part-DB1\templates\Users\backup_codes.html.twig:16 - - - tfa_backup.username - Nom d'utilisateur - - - - - Part-DB1\templates\Users\backup_codes.html.twig:29 - Part-DB1\templates\Users\backup_codes.html.twig:29 - - - tfa_backup.codes.page_generated_on - Page générée le %date% - - - - - Part-DB1\templates\Users\backup_codes.html.twig:32 - Part-DB1\templates\Users\backup_codes.html.twig:32 - - - tfa_backup.codes.print - Imprimer - - - - - Part-DB1\templates\Users\backup_codes.html.twig:35 - Part-DB1\templates\Users\backup_codes.html.twig:35 - - - tfa_backup.codes.copy_clipboard - Copier dans le presse-papier - - - - - Part-DB1\templates\Users\user_info.html.twig:3 - Part-DB1\templates\Users\user_info.html.twig:6 - Part-DB1\templates\_navbar.html.twig:40 - Part-DB1\templates\Users\user_info.html.twig:3 - Part-DB1\templates\Users\user_info.html.twig:6 - Part-DB1\templates\_navbar.html.twig:38 - templates\base.html.twig:99 - templates\Users\user_info.html.twig:3 - templates\Users\user_info.html.twig:6 - - - user.info.label - Informations sur l'utilisateur - - - - - Part-DB1\templates\Users\user_info.html.twig:18 - Part-DB1\src\Form\UserSettingsType.php:77 - Part-DB1\templates\Users\user_info.html.twig:18 - Part-DB1\src\Form\UserSettingsType.php:77 - templates\Users\user_info.html.twig:18 - src\Form\UserSettingsType.php:32 - - - user.firstName.label - Prénom - - - - - Part-DB1\templates\Users\user_info.html.twig:24 - Part-DB1\src\Form\UserSettingsType.php:82 - Part-DB1\templates\Users\user_info.html.twig:24 - Part-DB1\src\Form\UserSettingsType.php:82 - templates\Users\user_info.html.twig:24 - src\Form\UserSettingsType.php:35 - - - user.lastName.label - Nom - - - - - Part-DB1\templates\Users\user_info.html.twig:30 - Part-DB1\src\Form\UserSettingsType.php:92 - Part-DB1\templates\Users\user_info.html.twig:30 - Part-DB1\src\Form\UserSettingsType.php:92 - templates\Users\user_info.html.twig:30 - src\Form\UserSettingsType.php:41 - - - user.email.label - Email - - - - - Part-DB1\templates\Users\user_info.html.twig:37 - Part-DB1\src\Form\UserSettingsType.php:87 - Part-DB1\templates\Users\user_info.html.twig:37 - Part-DB1\src\Form\UserSettingsType.php:87 - templates\Users\user_info.html.twig:37 - src\Form\UserSettingsType.php:38 - - - user.department.label - Département - - - - - Part-DB1\templates\Users\user_info.html.twig:47 - Part-DB1\src\Form\UserSettingsType.php:73 - Part-DB1\templates\Users\user_info.html.twig:47 - Part-DB1\src\Form\UserSettingsType.php:73 - templates\Users\user_info.html.twig:47 - src\Form\UserSettingsType.php:30 - - - user.username.label - Nom d'utilisateur - - - - - Part-DB1\templates\Users\user_info.html.twig:53 - Part-DB1\src\Services\ElementTypeNameGenerator.php:93 - Part-DB1\templates\Users\user_info.html.twig:53 - Part-DB1\src\Services\ElementTypeNameGenerator.php:93 - templates\Users\user_info.html.twig:53 - - - group.label - Groupe - - - - - Part-DB1\templates\Users\user_info.html.twig:67 - Part-DB1\templates\Users\user_info.html.twig:67 - - - user.permissions - Autorisations - - - - - Part-DB1\templates\Users\user_settings.html.twig:3 - Part-DB1\templates\Users\user_settings.html.twig:6 - Part-DB1\templates\_navbar.html.twig:39 - Part-DB1\templates\Users\user_settings.html.twig:3 - Part-DB1\templates\Users\user_settings.html.twig:6 - Part-DB1\templates\_navbar.html.twig:37 - templates\base.html.twig:98 - templates\Users\user_settings.html.twig:3 - templates\Users\user_settings.html.twig:6 - - - user.settings.label - Paramètres utilisateur - - - - - Part-DB1\templates\Users\user_settings.html.twig:18 - Part-DB1\templates\Users\user_settings.html.twig:18 - templates\Users\user_settings.html.twig:14 - - - user_settings.data.label - Données personnelles - - - - - Part-DB1\templates\Users\user_settings.html.twig:22 - Part-DB1\templates\Users\user_settings.html.twig:22 - templates\Users\user_settings.html.twig:18 - - - user_settings.configuration.label - Configuration - - - - - Part-DB1\templates\Users\user_settings.html.twig:55 - Part-DB1\templates\Users\user_settings.html.twig:55 - templates\Users\user_settings.html.twig:48 - - - user.settings.change_pw - Changer de mot de passe - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:6 - Part-DB1\templates\Users\_2fa_settings.html.twig:6 - - - user.settings.2fa_settings - Authentification à deux facteurs - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:13 - Part-DB1\templates\Users\_2fa_settings.html.twig:13 - - - tfa.settings.google.tab - Application d'authentification - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:17 - Part-DB1\templates\Users\_2fa_settings.html.twig:17 - - - tfa.settings.bakup.tab - Codes de secours - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:21 - Part-DB1\templates\Users\_2fa_settings.html.twig:21 - - - tfa.settings.u2f.tab - Clés de sécurité (U2F) - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:25 - Part-DB1\templates\Users\_2fa_settings.html.twig:25 - - - tfa.settings.trustedDevices.tab - Appareils de confiance - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:33 - Part-DB1\templates\Users\_2fa_settings.html.twig:33 - - - tfa_google.disable.confirm_title - Voulez-vous vraiment désactiver l'application d'authentification ? - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:33 - Part-DB1\templates\Users\_2fa_settings.html.twig:33 - - - tfa_google.disable.confirm_message - Si vous désactivez l'application d'authentification, tous les codes de sauvegarde seront supprimés, vous devrez donc peut-être les réimprimer.<br> -Notez également que sans authentification à deux facteurs, votre compte n'est pas aussi bien protégé ! - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:39 - Part-DB1\templates\Users\_2fa_settings.html.twig:39 - - - tfa_google.disabled_message - Application d'authentification désactivée - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:48 - Part-DB1\templates\Users\_2fa_settings.html.twig:48 - - - tfa_google.step.download - Télécharger une application d'authentification (par exemple <a class="link-external" target="_blank" href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2">Authentificateur Google</a> ou <a class="link-external" target="_blank" href="https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp">Authentificateur FreeOTP</a>) - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:49 - Part-DB1\templates\Users\_2fa_settings.html.twig:49 - - - tfa_google.step.scan - Scannez le QR code adjacent avec l'application ou saisissez les données manuellement - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:50 - Part-DB1\templates\Users\_2fa_settings.html.twig:50 - - - tfa_google.step.input_code - Entrez le code généré dans le champ ci-dessous et confirmez - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:51 - Part-DB1\templates\Users\_2fa_settings.html.twig:51 - - - tfa_google.step.download_backup - Imprimez vos codes de secours et conservez-les dans un endroit sûr - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:58 - Part-DB1\templates\Users\_2fa_settings.html.twig:58 - - - tfa_google.manual_setup - Configuration manuelle - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:62 - Part-DB1\templates\Users\_2fa_settings.html.twig:62 - - - tfa_google.manual_setup.type - Type - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:63 - Part-DB1\templates\Users\_2fa_settings.html.twig:63 - - - tfa_google.manual_setup.username - Nom d'utilisateur - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:64 - Part-DB1\templates\Users\_2fa_settings.html.twig:64 - - - tfa_google.manual_setup.secret - Secret - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:65 - Part-DB1\templates\Users\_2fa_settings.html.twig:65 - - - tfa_google.manual_setup.digit_count - Nombre de caractères - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:74 - Part-DB1\templates\Users\_2fa_settings.html.twig:74 - - - tfa_google.enabled_message - Application d'authentification activée - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:83 - Part-DB1\templates\Users\_2fa_settings.html.twig:83 - - - tfa_backup.disabled - Codes de secours désactivés. Configurez l'application d'authentification pour activer les codes de secours. - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:84 - Part-DB1\templates\Users\_2fa_settings.html.twig:92 - Part-DB1\templates\Users\_2fa_settings.html.twig:84 - Part-DB1\templates\Users\_2fa_settings.html.twig:92 - - - tfa_backup.explanation - Grâce à ces codes de secours, vous pouvez accéder à votre compte même si vous perdez l'appareil avec l'application d'authentification. Imprimez les codes et conservez-les dans un endroit sûr. - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:88 - Part-DB1\templates\Users\_2fa_settings.html.twig:88 - - - tfa_backup.reset_codes.confirm_title - Etes vous sûr de vouloir réinitialiser les codes ? - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:88 - Part-DB1\templates\Users\_2fa_settings.html.twig:88 - - - tfa_backup.reset_codes.confirm_message - Cela permettra de supprimer tous les codes précédents et de générer un ensemble de nouveaux codes. Cela ne peut pas être annulé. N'oubliez pas d'imprimer les nouveaux codes et de les conserver dans un endroit sûr ! - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:91 - Part-DB1\templates\Users\_2fa_settings.html.twig:91 - - - tfa_backup.enabled - Codes de secours activés - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:99 - Part-DB1\templates\Users\_2fa_settings.html.twig:99 - - - tfa_backup.show_codes - Afficher les codes de secours - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:114 - Part-DB1\templates\Users\_2fa_settings.html.twig:114 - - - tfa_u2f.table_caption - Clés de sécurité enregistrées - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:115 - Part-DB1\templates\Users\_2fa_settings.html.twig:115 - - - tfa_u2f.delete_u2f.confirm_title - Etes vous sûr de vouloir supprimer cette clé de sécurité ? - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:116 - Part-DB1\templates\Users\_2fa_settings.html.twig:116 - - - tfa_u2f.delete_u2f.confirm_message - Si vous supprimez cette clé, il ne sera plus possible de se connecter avec cette clé. S'il ne reste aucune clé de sécurité, l'authentification à deux facteurs sera désactivée. - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:123 - Part-DB1\templates\Users\_2fa_settings.html.twig:123 - - - tfa_u2f.keys.name - Nom de la clé - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:124 - Part-DB1\templates\Users\_2fa_settings.html.twig:124 - - - tfa_u2f.keys.added_date - Date d'enregistrement - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:134 - Part-DB1\templates\Users\_2fa_settings.html.twig:134 - - - tfa_u2f.key_delete - Supprimer la clé - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:141 - Part-DB1\templates\Users\_2fa_settings.html.twig:141 - - - tfa_u2f.no_keys_registered - Aucune clé de sécurité enregistrée - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:144 - Part-DB1\templates\Users\_2fa_settings.html.twig:144 - - - tfa_u2f.add_new_key - Enregistrer une nouvelle clé de sécurité - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:148 - Part-DB1\templates\Users\_2fa_settings.html.twig:148 - - - tfa_trustedDevices.explanation - Lors de la vérification du deuxième facteur, l'ordinateur actuel peut être marqué comme étant digne de confiance, de sorte qu'il n'est plus nécessaire de procéder à des vérifications à deux facteurs sur cet ordinateur. -Si vous avez fait cela de manière incorrecte ou si un ordinateur n'est plus fiable, vous pouvez réinitialiser le statut de <i>tous</i> les ordinateurs ici. - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:149 - Part-DB1\templates\Users\_2fa_settings.html.twig:149 - - - tfa_trustedDevices.invalidate.confirm_title - Etes vous sûr de vouloir supprimer tous les ordinateurs de confiance ? - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:150 - Part-DB1\templates\Users\_2fa_settings.html.twig:150 - - - tfa_trustedDevices.invalidate.confirm_message - Vous devrez à nouveau procéder à une authentification à deux facteurs sur tous les ordinateurs. Assurez-vous d'avoir votre appareil à deux facteurs à portée de main. - - - - - Part-DB1\templates\Users\_2fa_settings.html.twig:154 - Part-DB1\templates\Users\_2fa_settings.html.twig:154 - - - tfa_trustedDevices.invalidate.btn - Supprimer tous les dispositifs de confiance - - - - - Part-DB1\templates\_navbar.html.twig:4 - Part-DB1\templates\_navbar.html.twig:4 - templates\base.html.twig:29 - - - sidebar.toggle - Activer/désactiver la barre latérale - - - - - Part-DB1\templates\_navbar.html.twig:22 - - - navbar.scanner.link - Scanner - - - - - Part-DB1\templates\_navbar.html.twig:38 - Part-DB1\templates\_navbar.html.twig:36 - templates\base.html.twig:97 - - - user.loggedin.label - Connecté en tant que - - - - - Part-DB1\templates\_navbar.html.twig:44 - Part-DB1\templates\_navbar.html.twig:42 - templates\base.html.twig:103 - - - user.login - Connexion - - - - - Part-DB1\templates\_navbar.html.twig:50 - Part-DB1\templates\_navbar.html.twig:48 - - - ui.toggle_darkmode - Darkmode - - - - - Part-DB1\templates\_navbar.html.twig:54 - Part-DB1\src\Form\UserSettingsType.php:97 - Part-DB1\templates\_navbar.html.twig:52 - Part-DB1\src\Form\UserSettingsType.php:97 - templates\base.html.twig:106 - src\Form\UserSettingsType.php:44 - - - user.language_select - Langue - - - - - Part-DB1\templates\_navbar_search.html.twig:4 - Part-DB1\templates\_navbar_search.html.twig:4 - templates\base.html.twig:49 - - - search.options.label - Options de recherche - - - - - Part-DB1\templates\_navbar_search.html.twig:23 - - - tags.label - Tags - - - - - Part-DB1\templates\_navbar_search.html.twig:27 - Part-DB1\src\Form\LabelOptionsType.php:68 - Part-DB1\src\Services\ElementTypeNameGenerator.php:88 - Part-DB1\src\Services\ElementTypeNameGenerator.php:88 - templates\base.html.twig:60 - templates\Parts\show_part_info.html.twig:36 - src\Form\PartType.php:77 - - - storelocation.label - Emplacement de stockage - - - - - Part-DB1\templates\_navbar_search.html.twig:36 - Part-DB1\templates\_navbar_search.html.twig:31 - templates\base.html.twig:65 - - - ordernumber.label.short - Codecmd. - - - - - Part-DB1\templates\_navbar_search.html.twig:40 - Part-DB1\src\Services\ElementTypeNameGenerator.php:89 - Part-DB1\templates\_navbar_search.html.twig:35 - Part-DB1\src\Services\ElementTypeNameGenerator.php:89 - templates\base.html.twig:67 - - - supplier.label - Fournisseur - - - - - Part-DB1\templates\_navbar_search.html.twig:57 - Part-DB1\templates\_navbar_search.html.twig:52 - templates\base.html.twig:75 - - - search.deactivateBarcode - Désa. Code barres - - - - - Part-DB1\templates\_navbar_search.html.twig:61 - Part-DB1\templates\_navbar_search.html.twig:56 - templates\base.html.twig:77 - - - search.regexmatching - Reg.Ex. Correspondance - - - - - Part-DB1\templates\_navbar_search.html.twig:68 - Part-DB1\templates\_navbar_search.html.twig:62 - - - search.submit - Rechercher! - - - - - Part-DB1\templates\_sidebar.html.twig:2 - Part-DB1\templates\_sidebar.html.twig:2 - templates\base.html.twig:165 - templates\base.html.twig:192 - templates\base.html.twig:220 - - - actions - Actions - - - - - Part-DB1\templates\_sidebar.html.twig:6 - Part-DB1\templates\_sidebar.html.twig:6 - templates\base.html.twig:169 - templates\base.html.twig:196 - templates\base.html.twig:224 - - - datasource - Source de données - - - - - Part-DB1\templates\_sidebar.html.twig:10 - Part-DB1\templates\_sidebar.html.twig:10 - templates\base.html.twig:173 - templates\base.html.twig:200 - templates\base.html.twig:228 - - - manufacturer.labelp - Fabricants - - - - - Part-DB1\templates\_sidebar.html.twig:11 - Part-DB1\templates\_sidebar.html.twig:11 - templates\base.html.twig:174 - templates\base.html.twig:201 - templates\base.html.twig:229 - - - supplier.labelp - Fournisseurs - - - - - Part-DB1\src\Controller\AdminPages\BaseAdminController.php:213 - Part-DB1\src\Controller\AdminPages\BaseAdminController.php:293 - Part-DB1\src\Controller\PartController.php:173 - Part-DB1\src\Controller\PartController.php:293 - Part-DB1\src\Controller\AdminPages\BaseAdminController.php:181 - Part-DB1\src\Controller\AdminPages\BaseAdminController.php:243 - Part-DB1\src\Controller\PartController.php:173 - Part-DB1\src\Controller\PartController.php:268 - - - attachment.download_failed - Le téléchargement du fichier joint a échoué ! - - - - - Part-DB1\src\Controller\AdminPages\BaseAdminController.php:222 - Part-DB1\src\Controller\AdminPages\BaseAdminController.php:190 - - - entity.edit_flash - Changements sauvegardés avec succès. - - - - - Part-DB1\src\Controller\AdminPages\BaseAdminController.php:231 - Part-DB1\src\Controller\AdminPages\BaseAdminController.php:196 - - - entity.edit_flash.invalid - Les changements n'ont pas pu être sauvegardés ! Veuillez vérifier vos données ! - - - - - Part-DB1\src\Controller\AdminPages\BaseAdminController.php:302 - Part-DB1\src\Controller\AdminPages\BaseAdminController.php:252 - - - entity.created_flash - Élément créé avec succès ! - - - - - Part-DB1\src\Controller\AdminPages\BaseAdminController.php:308 - Part-DB1\src\Controller\AdminPages\BaseAdminController.php:258 - - - entity.created_flash.invalid - L'élément n'a pas pu être créé ! Vérifiez vos données ! - - - - - Part-DB1\src\Controller\AdminPages\BaseAdminController.php:399 - Part-DB1\src\Controller\AdminPages\BaseAdminController.php:352 - src\Controller\BaseAdminController.php:154 - - - attachment_type.deleted - Élément supprimé ! - - - - - Part-DB1\src\Controller\AdminPages\BaseAdminController.php:401 - Part-DB1\src\Controller\UserController.php:109 - Part-DB1\src\Controller\UserSettingsController.php:159 - Part-DB1\src\Controller\UserSettingsController.php:193 - Part-DB1\src\Controller\AdminPages\BaseAdminController.php:354 - Part-DB1\src\Controller\UserController.php:101 - Part-DB1\src\Controller\UserSettingsController.php:150 - Part-DB1\src\Controller\UserSettingsController.php:182 - - - csfr_invalid - Le jeton RFTS n'est pas valable ! Rechargez cette page ou contactez un administrateur si le problème persiste ! - - - - - Part-DB1\src\Controller\LabelController.php:125 - - - label_generator.no_entities_found - Aucune entité correspondant à la gamme trouvée. - - - - - Part-DB1\src\Controller\LogController.php:149 - Part-DB1\src\Controller\LogController.php:154 - new - - - log.undo.target_not_found - L'élément ciblé n'a pas pu être trouvé dans la base de données ! - - - - - Part-DB1\src\Controller\LogController.php:156 - Part-DB1\src\Controller\LogController.php:160 - new - - - log.undo.revert_success - Rétablissement réussi. - - - - - Part-DB1\src\Controller\LogController.php:176 - Part-DB1\src\Controller\LogController.php:180 - new - - - log.undo.element_undelete_success - Élément restauré avec succès. - - - - - Part-DB1\src\Controller\LogController.php:178 - Part-DB1\src\Controller\LogController.php:182 - new - - - log.undo.element_element_already_undeleted - L'élément a déjà été restauré ! - - - - - Part-DB1\src\Controller\LogController.php:185 - Part-DB1\src\Controller\LogController.php:189 - new - - - log.undo.element_delete_success - L'élément a été supprimé avec succès. - - - - - Part-DB1\src\Controller\LogController.php:187 - Part-DB1\src\Controller\LogController.php:191 - new - - - log.undo.element.element_already_delted - L'élément a déjà été supprimé ! - - - - - Part-DB1\src\Controller\LogController.php:194 - Part-DB1\src\Controller\LogController.php:198 - new - - - log.undo.element_change_undone - Annulation de la modification de l'élément - - - - - Part-DB1\src\Controller\LogController.php:196 - Part-DB1\src\Controller\LogController.php:200 - new - - - log.undo.do_undelete_before - Vous devez supprimer l'élément avant de pouvoir annuler ce changement ! - - - - - Part-DB1\src\Controller\LogController.php:199 - Part-DB1\src\Controller\LogController.php:203 - new - - - log.undo.log_type_invalid - Cette entrée de journal ne peut pas être annulée ! - - - - - Part-DB1\src\Controller\PartController.php:182 - Part-DB1\src\Controller\PartController.php:182 - src\Controller\PartController.php:80 - - - part.edited_flash - Changements sauvegardés ! - - - - - Part-DB1\src\Controller\PartController.php:186 - Part-DB1\src\Controller\PartController.php:186 - - - part.edited_flash.invalid - Erreur lors de l'enregistrement : Vérifiez vos données ! - - - - - Part-DB1\src\Controller\PartController.php:216 - Part-DB1\src\Controller\PartController.php:219 - - - part.deleted - Composant supprimé avec succès. - - - - - Part-DB1\src\Controller\PartController.php:302 - Part-DB1\src\Controller\PartController.php:277 - Part-DB1\src\Controller\PartController.php:317 - src\Controller\PartController.php:113 - src\Controller\PartController.php:142 - - - part.created_flash - Composants créés avec succès ! - - - - - Part-DB1\src\Controller\PartController.php:308 - Part-DB1\src\Controller\PartController.php:283 - - - part.created_flash.invalid - Erreur lors de la création : Vérifiez vos données ! - - - - - Part-DB1\src\Controller\ScanController.php:68 - Part-DB1\src\Controller\ScanController.php:90 - - - scan.qr_not_found - Aucun élément trouvé pour le code-barres donné. - - - - - Part-DB1\src\Controller\ScanController.php:71 - - - scan.format_unknown - Format inconnu ! - - - - - Part-DB1\src\Controller\ScanController.php:86 - - - scan.qr_success - Élément trouvé. - - - - - Part-DB1\src\Controller\SecurityController.php:114 - Part-DB1\src\Controller\SecurityController.php:109 - - - pw_reset.user_or_email - Nom d'utilisateur / Email - - - - - Part-DB1\src\Controller\SecurityController.php:131 - Part-DB1\src\Controller\SecurityController.php:126 - - - pw_reset.request.success - Demande de mot de passe réussie ! Consultez vos e-mails pour plus d'informations. - - - - - Part-DB1\src\Controller\SecurityController.php:162 - Part-DB1\src\Controller\SecurityController.php:160 - - - pw_reset.username - Nom d'utilisateur - - - - - Part-DB1\src\Controller\SecurityController.php:165 - Part-DB1\src\Controller\SecurityController.php:163 - - - pw_reset.token - Jeton - - - - - Part-DB1\src\Controller\SecurityController.php:194 - Part-DB1\src\Controller\SecurityController.php:192 - - - pw_reset.new_pw.error - Nom d'utilisateur ou jeton invalide ! Veuillez vérifier vos données. - - - - - Part-DB1\src\Controller\SecurityController.php:196 - Part-DB1\src\Controller\SecurityController.php:194 - - - pw_reset.new_pw.success - Le mot de passe a été réinitialisé avec succès. Vous pouvez maintenant vous connecter avec le nouveau mot de passe. - - - - - Part-DB1\src\Controller\UserController.php:107 - Part-DB1\src\Controller\UserController.php:99 - - - user.edit.reset_success - Toutes les méthodes d'authentification à deux facteurs ont été désactivées avec succès. - - - - - Part-DB1\src\Controller\UserSettingsController.php:101 - Part-DB1\src\Controller\UserSettingsController.php:92 - - - tfa_backup.no_codes_enabled - Aucun code de secours n'est activé ! - - - - - Part-DB1\src\Controller\UserSettingsController.php:138 - Part-DB1\src\Controller\UserSettingsController.php:132 - - - tfa_u2f.u2f_delete.not_existing - Il n'y a pas de clé de sécurité avec cet ID ! - - - - - Part-DB1\src\Controller\UserSettingsController.php:145 - Part-DB1\src\Controller\UserSettingsController.php:139 - - - tfa_u2f.u2f_delete.access_denied - Vous ne pouvez pas supprimer les clés de sécurité des autres utilisateurs ! - - - - - Part-DB1\src\Controller\UserSettingsController.php:153 - Part-DB1\src\Controller\UserSettingsController.php:147 - - - tfa.u2f.u2f_delete.success - Clé de sécurité retirée avec succès. - - - - - Part-DB1\src\Controller\UserSettingsController.php:188 - Part-DB1\src\Controller\UserSettingsController.php:180 - - - tfa_trustedDevice.invalidate.success - Les appareils de confiance ont été réinitialisés avec succès. - - - - - Part-DB1\src\Controller\UserSettingsController.php:235 - Part-DB1\src\Controller\UserSettingsController.php:226 - src\Controller\UserController.php:98 - - - user.settings.saved_flash - Paramètres sauvegardés ! - - - - - Part-DB1\src\Controller\UserSettingsController.php:297 - Part-DB1\src\Controller\UserSettingsController.php:288 - src\Controller\UserController.php:130 - - - user.settings.pw_changed_flash - Mot de passe changé ! - - - - - Part-DB1\src\Controller\UserSettingsController.php:317 - Part-DB1\src\Controller\UserSettingsController.php:306 - - - user.settings.2fa.google.activated - L'application d'authentification a été activée avec succès. - - - - - Part-DB1\src\Controller\UserSettingsController.php:328 - Part-DB1\src\Controller\UserSettingsController.php:315 - - - user.settings.2fa.google.disabled - L'application d'authentification a été désactivée avec succès. - - - - - Part-DB1\src\Controller\UserSettingsController.php:346 - Part-DB1\src\Controller\UserSettingsController.php:332 - - - user.settings.2fa.backup_codes.regenerated - De nouveaux codes de secours ont été générés avec succès. - - - - - Part-DB1\src\DataTables\AttachmentDataTable.php:148 - Part-DB1\src\DataTables\AttachmentDataTable.php:148 - - - attachment.table.filename - Nom du fichier - - - - - Part-DB1\src\DataTables\AttachmentDataTable.php:153 - Part-DB1\src\DataTables\AttachmentDataTable.php:153 - - - attachment.table.filesize - Taille du fichier - - - - - Part-DB1\src\DataTables\AttachmentDataTable.php:183 - Part-DB1\src\DataTables\AttachmentDataTable.php:191 - Part-DB1\src\DataTables\AttachmentDataTable.php:200 - Part-DB1\src\DataTables\AttachmentDataTable.php:209 - Part-DB1\src\DataTables\PartsDataTable.php:245 - Part-DB1\src\DataTables\PartsDataTable.php:252 - Part-DB1\src\DataTables\AttachmentDataTable.php:183 - Part-DB1\src\DataTables\AttachmentDataTable.php:191 - Part-DB1\src\DataTables\AttachmentDataTable.php:200 - Part-DB1\src\DataTables\AttachmentDataTable.php:209 - Part-DB1\src\DataTables\PartsDataTable.php:193 - Part-DB1\src\DataTables\PartsDataTable.php:200 - - - true - Vrai - - - - - Part-DB1\src\DataTables\AttachmentDataTable.php:184 - Part-DB1\src\DataTables\AttachmentDataTable.php:192 - Part-DB1\src\DataTables\AttachmentDataTable.php:201 - Part-DB1\src\DataTables\AttachmentDataTable.php:210 - Part-DB1\src\DataTables\PartsDataTable.php:246 - Part-DB1\src\DataTables\PartsDataTable.php:253 - Part-DB1\src\Form\Type\SIUnitType.php:139 - Part-DB1\src\DataTables\AttachmentDataTable.php:184 - Part-DB1\src\DataTables\AttachmentDataTable.php:192 - Part-DB1\src\DataTables\AttachmentDataTable.php:201 - Part-DB1\src\DataTables\AttachmentDataTable.php:210 - Part-DB1\src\DataTables\PartsDataTable.php:194 - Part-DB1\src\DataTables\PartsDataTable.php:201 - Part-DB1\src\Form\Type\SIUnitType.php:139 - - - false - Faux - - - - - Part-DB1\src\DataTables\Column\LogEntryTargetColumn.php:128 - Part-DB1\src\DataTables\Column\LogEntryTargetColumn.php:119 - - - log.target_deleted - Cible supprimée. - - - - - Part-DB1\src\DataTables\Column\RevertLogColumn.php:57 - Part-DB1\src\DataTables\Column\RevertLogColumn.php:60 - new - - - log.undo.undelete - Annuler la suppression - - - - - Part-DB1\src\DataTables\Column\RevertLogColumn.php:63 - Part-DB1\src\DataTables\Column\RevertLogColumn.php:66 - new - - - log.undo.undo - Annuler la modification - - - - - Part-DB1\src\DataTables\Column\RevertLogColumn.php:83 - Part-DB1\src\DataTables\Column\RevertLogColumn.php:86 - new - - - log.undo.revert - Restaurer à cette date - - - - - Part-DB1\src\DataTables\LogDataTable.php:173 - Part-DB1\src\DataTables\LogDataTable.php:161 - - - log.id - ID - - - - - Part-DB1\src\DataTables\LogDataTable.php:178 - Part-DB1\src\DataTables\LogDataTable.php:166 - - - log.timestamp - Horodatage - - - - - Part-DB1\src\DataTables\LogDataTable.php:183 - Part-DB1\src\DataTables\LogDataTable.php:171 - - - log.type - Type - - - - - Part-DB1\src\DataTables\LogDataTable.php:191 - Part-DB1\src\DataTables\LogDataTable.php:179 - - - log.level - Niveau - - - - - Part-DB1\src\DataTables\LogDataTable.php:200 - Part-DB1\src\DataTables\LogDataTable.php:188 - - - log.user - Utilisateur - - - - - Part-DB1\src\DataTables\LogDataTable.php:213 - Part-DB1\src\DataTables\LogDataTable.php:201 - - - log.target_type - Type de cible - - - - - Part-DB1\src\DataTables\LogDataTable.php:226 - Part-DB1\src\DataTables\LogDataTable.php:214 - - - log.target - Cible - - - - - Part-DB1\src\DataTables\LogDataTable.php:231 - Part-DB1\src\DataTables\LogDataTable.php:218 - new - - - log.extra - Extra - - - - - Part-DB1\src\DataTables\PartsDataTable.php:168 - Part-DB1\src\DataTables\PartsDataTable.php:116 - - - part.table.name - Nom - - - - - Part-DB1\src\DataTables\PartsDataTable.php:178 - Part-DB1\src\DataTables\PartsDataTable.php:126 - - - part.table.id - ID - - - - - Part-DB1\src\DataTables\PartsDataTable.php:182 - Part-DB1\src\DataTables\PartsDataTable.php:130 - - - part.table.description - Description - - - - - Part-DB1\src\DataTables\PartsDataTable.php:185 - Part-DB1\src\DataTables\PartsDataTable.php:133 - - - part.table.category - Catégorie - - - - - Part-DB1\src\DataTables\PartsDataTable.php:190 - Part-DB1\src\DataTables\PartsDataTable.php:138 - - - part.table.footprint - Empreinte - - - - - Part-DB1\src\DataTables\PartsDataTable.php:194 - Part-DB1\src\DataTables\PartsDataTable.php:142 - - - part.table.manufacturer - Fabricant - - - - - Part-DB1\src\DataTables\PartsDataTable.php:197 - Part-DB1\src\DataTables\PartsDataTable.php:145 - - - part.table.storeLocations - Emplacement de stockage - - - - - Part-DB1\src\DataTables\PartsDataTable.php:216 - Part-DB1\src\DataTables\PartsDataTable.php:164 - - - part.table.amount - Quantité - - - - - Part-DB1\src\DataTables\PartsDataTable.php:224 - Part-DB1\src\DataTables\PartsDataTable.php:172 - - - part.table.minamount - Quantité min. - - - - - Part-DB1\src\DataTables\PartsDataTable.php:232 - Part-DB1\src\DataTables\PartsDataTable.php:180 - - - part.table.partUnit - Unité de mesure - - - - - Part-DB1\src\DataTables\PartsDataTable.php:236 - Part-DB1\src\DataTables\PartsDataTable.php:184 - - - part.table.addedDate - Créé le - - - - - Part-DB1\src\DataTables\PartsDataTable.php:240 - Part-DB1\src\DataTables\PartsDataTable.php:188 - - - part.table.lastModified - Dernière modification - - - - - Part-DB1\src\DataTables\PartsDataTable.php:244 - Part-DB1\src\DataTables\PartsDataTable.php:192 - - - part.table.needsReview - Révision nécessaire - - - - - Part-DB1\src\DataTables\PartsDataTable.php:251 - Part-DB1\src\DataTables\PartsDataTable.php:199 - - - part.table.favorite - Favoris - - - - - Part-DB1\src\DataTables\PartsDataTable.php:258 - Part-DB1\src\DataTables\PartsDataTable.php:206 - - - part.table.manufacturingStatus - État - - - - - Part-DB1\src\DataTables\PartsDataTable.php:260 - Part-DB1\src\DataTables\PartsDataTable.php:262 - Part-DB1\src\Form\Part\PartBaseType.php:90 - Part-DB1\src\DataTables\PartsDataTable.php:208 - Part-DB1\src\DataTables\PartsDataTable.php:210 - Part-DB1\src\Form\Part\PartBaseType.php:88 - - - m_status.unknown - Inconnu - - - - - Part-DB1\src\DataTables\PartsDataTable.php:263 - Part-DB1\src\Form\Part\PartBaseType.php:90 - Part-DB1\src\DataTables\PartsDataTable.php:211 - Part-DB1\src\Form\Part\PartBaseType.php:88 - - - m_status.announced - Annoncé - - - - - Part-DB1\src\DataTables\PartsDataTable.php:264 - Part-DB1\src\Form\Part\PartBaseType.php:90 - Part-DB1\src\DataTables\PartsDataTable.php:212 - Part-DB1\src\Form\Part\PartBaseType.php:88 - - - m_status.active - Actif - - - - - Part-DB1\src\DataTables\PartsDataTable.php:265 - Part-DB1\src\Form\Part\PartBaseType.php:90 - Part-DB1\src\DataTables\PartsDataTable.php:213 - Part-DB1\src\Form\Part\PartBaseType.php:88 - - - m_status.nrfnd - Non recommandé pour les nouvelles conceptions - - - - - Part-DB1\src\DataTables\PartsDataTable.php:266 - Part-DB1\src\Form\Part\PartBaseType.php:90 - Part-DB1\src\DataTables\PartsDataTable.php:214 - Part-DB1\src\Form\Part\PartBaseType.php:88 - - - m_status.eol - Fin de vie - - - - - Part-DB1\src\DataTables\PartsDataTable.php:267 - Part-DB1\src\Form\Part\PartBaseType.php:90 - Part-DB1\src\DataTables\PartsDataTable.php:215 - Part-DB1\src\Form\Part\PartBaseType.php:88 - - - m_status.discontinued - Arrêtés - - - - - Part-DB1\src\DataTables\PartsDataTable.php:271 - Part-DB1\src\DataTables\PartsDataTable.php:219 - - - part.table.mpn - MPN - - - - - Part-DB1\src\DataTables\PartsDataTable.php:275 - Part-DB1\src\DataTables\PartsDataTable.php:223 - - - part.table.mass - Poids - - - - - Part-DB1\src\DataTables\PartsDataTable.php:279 - Part-DB1\src\DataTables\PartsDataTable.php:227 - - - part.table.tags - Tags - - - - - Part-DB1\src\DataTables\PartsDataTable.php:283 - Part-DB1\src\DataTables\PartsDataTable.php:231 - - - part.table.attachments - Fichiers joints - - - - - Part-DB1\src\EventSubscriber\UserSystem\LoginSuccessSubscriber.php:82 - Part-DB1\src\EventSubscriber\LoginSuccessListener.php:82 - - - flash.login_successful - Connexion réussie. - - - - - Part-DB1\src\Form\AdminPages\ImportType.php:77 - Part-DB1\src\Form\AdminPages\ImportType.php:77 - src\Form\ImportType.php:68 - - - JSON - JSON - - - - - Part-DB1\src\Form\AdminPages\ImportType.php:77 - Part-DB1\src\Form\AdminPages\ImportType.php:77 - src\Form\ImportType.php:68 - - - XML - XML - - - - - Part-DB1\src\Form\AdminPages\ImportType.php:77 - Part-DB1\src\Form\AdminPages\ImportType.php:77 - src\Form\ImportType.php:68 - - - CSV - CSV - - - - - Part-DB1\src\Form\AdminPages\ImportType.php:77 - Part-DB1\src\Form\AdminPages\ImportType.php:77 - src\Form\ImportType.php:68 - - - YAML - YAML - - - - - Part-DB1\src\Form\AdminPages\ImportType.php:124 - Part-DB1\src\Form\AdminPages\ImportType.php:124 - - - import.abort_on_validation.help - Si cette option est activée, l'ensemble du processus est interrompu si des données non valides sont détectées. Si cette option n'est pas active, les entrées non valides sont ignorées et une tentative est faite pour importer les autres entrées. - - - - - Part-DB1\src\Form\AdminPages\ImportType.php:86 - Part-DB1\src\Form\AdminPages\ImportType.php:86 - src\Form\ImportType.php:70 - - - import.csv_separator - Séparateur CSV - - - - - Part-DB1\src\Form\AdminPages\ImportType.php:93 - Part-DB1\src\Form\AdminPages\ImportType.php:93 - src\Form\ImportType.php:72 - - - parent.label - Élément parent - - - - - Part-DB1\src\Form\AdminPages\ImportType.php:101 - Part-DB1\src\Form\AdminPages\ImportType.php:101 - src\Form\ImportType.php:75 - - - import.file - Fichier - - - - - Part-DB1\src\Form\AdminPages\ImportType.php:111 - Part-DB1\src\Form\AdminPages\ImportType.php:111 - src\Form\ImportType.php:78 - - - import.preserve_children - Importer également des sous-éléments - - - - - Part-DB1\src\Form\AdminPages\ImportType.php:120 - Part-DB1\src\Form\AdminPages\ImportType.php:120 - src\Form\ImportType.php:80 - - - import.abort_on_validation - Interrompre sur donnée invalide - - - - - Part-DB1\src\Form\AdminPages\ImportType.php:132 - Part-DB1\src\Form\AdminPages\ImportType.php:132 - src\Form\ImportType.php:85 - - - import.btn - Importer - - - - - Part-DB1\src\Form\AttachmentFormType.php:113 - Part-DB1\src\Form\AttachmentFormType.php:109 - - - attachment.edit.secure_file.help - Un fichier joint marqué comme étant privé ne peut être consulté que par un utilisateur connecté qui a l'autorisation appropriée. Si cette option est activée, aucune miniature n'est générée et l'accès au fichier est plus lent. - - - - - Part-DB1\src\Form\AttachmentFormType.php:127 - Part-DB1\src\Form\AttachmentFormType.php:123 - - - attachment.edit.url.help - Il est possible de saisir ici soit l'URL d'un fichier externe, soit un mot clé pour rechercher les ressources intégrées (par exemple les empreintes). - - - - - Part-DB1\src\Form\AttachmentFormType.php:82 - Part-DB1\src\Form\AttachmentFormType.php:79 - - - attachment.edit.name - Nom - - - - - Part-DB1\src\Form\AttachmentFormType.php:85 - Part-DB1\src\Form\AttachmentFormType.php:82 - - - attachment.edit.attachment_type - Type de fichier joint - - - - - Part-DB1\src\Form\AttachmentFormType.php:94 - Part-DB1\src\Form\AttachmentFormType.php:91 - - - attachment.edit.show_in_table - Voir dans le tableau - - - - - Part-DB1\src\Form\AttachmentFormType.php:105 - Part-DB1\src\Form\AttachmentFormType.php:102 - - - attachment.edit.secure_file - Fichier joint privé - - - - - Part-DB1\src\Form\AttachmentFormType.php:119 - Part-DB1\src\Form\AttachmentFormType.php:115 - - - attachment.edit.url - URL - - - - - Part-DB1\src\Form\AttachmentFormType.php:133 - Part-DB1\src\Form\AttachmentFormType.php:129 - - - attachment.edit.download_url - Télécharger un fichier externe - - - - - Part-DB1\src\Form\AttachmentFormType.php:146 - Part-DB1\src\Form\AttachmentFormType.php:142 - - - attachment.edit.file - Télécharger le fichier - - - - - Part-DB1\src\Form\LabelOptionsType.php:68 - Part-DB1\src\Services\ElementTypeNameGenerator.php:86 - - - part.label - Composant - - - - - Part-DB1\src\Form\LabelOptionsType.php:68 - Part-DB1\src\Services\ElementTypeNameGenerator.php:87 - - - part_lot.label - Lot de composant - - - - - Part-DB1\src\Form\LabelOptionsType.php:78 - - - label_options.barcode_type.none - Aucun - - - - - Part-DB1\src\Form\LabelOptionsType.php:78 - - - label_options.barcode_type.qr - QR Code (recommandé) - - - - - Part-DB1\src\Form\LabelOptionsType.php:78 - - - label_options.barcode_type.code128 - Code 128 (recommandé) - - - - - Part-DB1\src\Form\LabelOptionsType.php:78 - - - label_options.barcode_type.code39 - Code 39 (recommandé) - - - - - Part-DB1\src\Form\LabelOptionsType.php:78 - - - label_options.barcode_type.code93 - Code 93 - - - - - Part-DB1\src\Form\LabelOptionsType.php:78 - - - label_options.barcode_type.datamatrix - Datamatrix - - - - - Part-DB1\src\Form\LabelOptionsType.php:122 - - - label_options.lines_mode.html - Placeholders - - - - - Part-DB1\src\Form\LabelOptionsType.php:122 - - - label.options.lines_mode.twig - Twig - - - - - Part-DB1\src\Form\LabelOptionsType.php:126 - - - label_options.lines_mode.help - Si vous sélectionnez Twig ici, le champ de contenu est interprété comme un modèle Twig. Voir <a href="https://twig.symfony.com/doc/3.x/templates.html">Documentation de Twig</a> et <a href="https://github.com/Part-DB/Part-DB-symfony/wiki/Labels#twig-mode">Wiki</a> pour plus d'informations. - - - - - Part-DB1\src\Form\LabelOptionsType.php:47 - - - label_options.page_size.label - Taille de l'étiquette - - - - - Part-DB1\src\Form\LabelOptionsType.php:66 - - - label_options.supported_elements.label - Type de cible - - - - - Part-DB1\src\Form\LabelOptionsType.php:75 - - - label_options.barcode_type.label - Code barre - - - - - Part-DB1\src\Form\LabelOptionsType.php:102 - - - label_profile.lines.label - Contenu - - - - - Part-DB1\src\Form\LabelOptionsType.php:111 - - - label_options.additional_css.label - Styles supplémentaires (CSS) - - - - - Part-DB1\src\Form\LabelOptionsType.php:120 - - - label_options.lines_mode.label - Parser mode - - - - - Part-DB1\src\Form\LabelOptionsType.php:51 - - - label_options.width.placeholder - Largeur - - - - - Part-DB1\src\Form\LabelOptionsType.php:60 - - - label_options.height.placeholder - Hauteur - - - - - Part-DB1\src\Form\LabelSystem\LabelDialogType.php:49 - - - label_generator.target_id.range_hint - Vous pouvez spécifier ici plusieurs ID (par exemple 1,2,3) et/ou une plage (1-3) pour générer des étiquettes pour plusieurs éléments à la fois. - - - - - Part-DB1\src\Form\LabelSystem\LabelDialogType.php:46 - - - label_generator.target_id.label - ID des cibles - - - - - Part-DB1\src\Form\LabelSystem\LabelDialogType.php:59 - - - label_generator.update - Actualisation - - - - - Part-DB1\src\Form\LabelSystem\ScanDialogType.php:36 - - - scan_dialog.input - Saisie - - - - - Part-DB1\src\Form\LabelSystem\ScanDialogType.php:44 - - - scan_dialog.submit - Soumettre - - - - - Part-DB1\src\Form\ParameterType.php:41 - - - parameters.name.placeholder - ex. Gain de courant DC - - - - - Part-DB1\src\Form\ParameterType.php:50 - - - parameters.symbol.placeholder - ex. h_{FE} - - - - - Part-DB1\src\Form\ParameterType.php:60 - - - parameters.text.placeholder - ex. Test conditions - - - - - Part-DB1\src\Form\ParameterType.php:71 - - - parameters.max.placeholder - ex. 350 - - - - - Part-DB1\src\Form\ParameterType.php:82 - - - parameters.min.placeholder - ex. 100 - - - - - Part-DB1\src\Form\ParameterType.php:93 - - - parameters.typical.placeholder - ex. 200 - - - - - Part-DB1\src\Form\ParameterType.php:103 - - - parameters.unit.placeholder - ex. V - - - - - Part-DB1\src\Form\ParameterType.php:114 - - - parameter.group.placeholder - ex. Spécifications techniques - - - - - Part-DB1\src\Form\Part\OrderdetailType.php:72 - Part-DB1\src\Form\Part\OrderdetailType.php:75 - - - orderdetails.edit.supplierpartnr - Numéro de commande - - - - - Part-DB1\src\Form\Part\OrderdetailType.php:81 - Part-DB1\src\Form\Part\OrderdetailType.php:84 - - - orderdetails.edit.supplier - Fournisseur - - - - - Part-DB1\src\Form\Part\OrderdetailType.php:87 - Part-DB1\src\Form\Part\OrderdetailType.php:90 - - - orderdetails.edit.url - Lien vers l'offre - - - - - Part-DB1\src\Form\Part\OrderdetailType.php:93 - Part-DB1\src\Form\Part\OrderdetailType.php:96 - - - orderdetails.edit.obsolete - Plus disponible - - - - - Part-DB1\src\Form\Part\OrderdetailType.php:75 - Part-DB1\src\Form\Part\OrderdetailType.php:78 - - - orderdetails.edit.supplierpartnr.placeholder - Ex. BC 547C - - - - - Part-DB1\src\Form\Part\PartBaseType.php:101 - Part-DB1\src\Form\Part\PartBaseType.php:99 - - - part.edit.name - Nom - - - - - Part-DB1\src\Form\Part\PartBaseType.php:109 - Part-DB1\src\Form\Part\PartBaseType.php:107 - - - part.edit.description - Description - - - - - Part-DB1\src\Form\Part\PartBaseType.php:120 - Part-DB1\src\Form\Part\PartBaseType.php:118 - - - part.edit.mininstock - Stock minimum - - - - - Part-DB1\src\Form\Part\PartBaseType.php:129 - Part-DB1\src\Form\Part\PartBaseType.php:127 - - - part.edit.category - Catégories - - - - - Part-DB1\src\Form\Part\PartBaseType.php:135 - Part-DB1\src\Form\Part\PartBaseType.php:133 - - - part.edit.footprint - Empreinte - - - - - Part-DB1\src\Form\Part\PartBaseType.php:142 - Part-DB1\src\Form\Part\PartBaseType.php:140 - - - part.edit.tags - Tags - - - - - Part-DB1\src\Form\Part\PartBaseType.php:154 - Part-DB1\src\Form\Part\PartBaseType.php:152 - - - part.edit.manufacturer.label - Fabricant - - - - - Part-DB1\src\Form\Part\PartBaseType.php:161 - Part-DB1\src\Form\Part\PartBaseType.php:159 - - - part.edit.manufacturer_url.label - Lien vers la page du produit - - - - - Part-DB1\src\Form\Part\PartBaseType.php:167 - Part-DB1\src\Form\Part\PartBaseType.php:165 - - - part.edit.mpn - Numéro de pièce du fabricant - - - - - Part-DB1\src\Form\Part\PartBaseType.php:173 - Part-DB1\src\Form\Part\PartBaseType.php:171 - - - part.edit.manufacturing_status - État de la fabrication - - - - - Part-DB1\src\Form\Part\PartBaseType.php:181 - Part-DB1\src\Form\Part\PartBaseType.php:179 - - - part.edit.needs_review - Révision nécessaire - - - - - Part-DB1\src\Form\Part\PartBaseType.php:189 - Part-DB1\src\Form\Part\PartBaseType.php:187 - - - part.edit.is_favorite - Favoris - - - - - Part-DB1\src\Form\Part\PartBaseType.php:197 - Part-DB1\src\Form\Part\PartBaseType.php:195 - - - part.edit.mass - Poids - - - - - Part-DB1\src\Form\Part\PartBaseType.php:203 - Part-DB1\src\Form\Part\PartBaseType.php:201 - - - part.edit.partUnit - Unité de mesure - - - - - Part-DB1\src\Form\Part\PartBaseType.php:212 - Part-DB1\src\Form\Part\PartBaseType.php:210 - - - part.edit.comment - Commentaire - - - - - Part-DB1\src\Form\Part\PartBaseType.php:250 - Part-DB1\src\Form\Part\PartBaseType.php:246 - - - part.edit.master_attachment - Miniature - - - - - Part-DB1\src\Form\Part\PartBaseType.php:295 - Part-DB1\src\Form\Part\PartBaseType.php:276 - src\Form\PartType.php:91 - - - part.edit.save - Sauvegarder les modifications - - - - - Part-DB1\src\Form\Part\PartBaseType.php:296 - Part-DB1\src\Form\Part\PartBaseType.php:277 - src\Form\PartType.php:92 - - - part.edit.reset - rejeter les modifications - - - - - Part-DB1\src\Form\Part\PartBaseType.php:105 - Part-DB1\src\Form\Part\PartBaseType.php:103 - - - part.edit.name.placeholder - Ex. BC547 - - - - - Part-DB1\src\Form\Part\PartBaseType.php:115 - Part-DB1\src\Form\Part\PartBaseType.php:113 - - - part.edit.description.placeholder - Ex. NPN 45V, 0,1A, 0,5W - - - - - Part-DB1\src\Form\Part\PartBaseType.php:123 - Part-DB1\src\Form\Part\PartBaseType.php:121 - - - part.editmininstock.placeholder - Ex. 1 - - - - - Part-DB1\src\Form\Part\PartLotType.php:69 - Part-DB1\src\Form\Part\PartLotType.php:69 - - - part_lot.edit.description - Description - - - - - Part-DB1\src\Form\Part\PartLotType.php:78 - Part-DB1\src\Form\Part\PartLotType.php:78 - - - part_lot.edit.location - Emplacement de stockage - - - - - Part-DB1\src\Form\Part\PartLotType.php:89 - Part-DB1\src\Form\Part\PartLotType.php:89 - - - part_lot.edit.amount - Quantité - - - - - Part-DB1\src\Form\Part\PartLotType.php:98 - Part-DB1\src\Form\Part\PartLotType.php:97 - - - part_lot.edit.instock_unknown - Quantité inconnue - - - - - Part-DB1\src\Form\Part\PartLotType.php:109 - Part-DB1\src\Form\Part\PartLotType.php:108 - - - part_lot.edit.needs_refill - Doit être rempli - - - - - Part-DB1\src\Form\Part\PartLotType.php:120 - Part-DB1\src\Form\Part\PartLotType.php:119 - - - part_lot.edit.expiration_date - Date d'expiration - - - - - Part-DB1\src\Form\Part\PartLotType.php:128 - Part-DB1\src\Form\Part\PartLotType.php:125 - - - part_lot.edit.comment - Commentaire - - - - - Part-DB1\src\Form\Permissions\PermissionsType.php:99 - Part-DB1\src\Form\Permissions\PermissionsType.php:99 - - - perm.group.other - Divers - - - - - Part-DB1\src\Form\TFAGoogleSettingsType.php:97 - Part-DB1\src\Form\TFAGoogleSettingsType.php:97 - - - tfa_google.enable - Activer l'application d'authentification - - - - - Part-DB1\src\Form\TFAGoogleSettingsType.php:101 - Part-DB1\src\Form\TFAGoogleSettingsType.php:101 - - - tfa_google.disable - Désactiver l'application d'authentification - - - - - Part-DB1\src\Form\TFAGoogleSettingsType.php:74 - Part-DB1\src\Form\TFAGoogleSettingsType.php:74 - - - google_confirmation - Code de confirmation - - - - - Part-DB1\src\Form\UserSettingsType.php:108 - Part-DB1\src\Form\UserSettingsType.php:108 - src\Form\UserSettingsType.php:46 - - - user.timezone.label - Fuseau horaire - - - - - Part-DB1\src\Form\UserSettingsType.php:133 - Part-DB1\src\Form\UserSettingsType.php:132 - - - user.currency.label - Devise préférée - - - - - Part-DB1\src\Form\UserSettingsType.php:140 - Part-DB1\src\Form\UserSettingsType.php:139 - src\Form\UserSettingsType.php:53 - - - save - Appliquer les modifications - - - - - Part-DB1\src\Form\UserSettingsType.php:141 - Part-DB1\src\Form\UserSettingsType.php:140 - src\Form\UserSettingsType.php:54 - - - reset - Rejeter les modifications - - - - - Part-DB1\src\Form\UserSettingsType.php:104 - Part-DB1\src\Form\UserSettingsType.php:104 - src\Form\UserSettingsType.php:45 - - - user_settings.language.placeholder - Langue du serveur - - - - - Part-DB1\src\Form\UserSettingsType.php:115 - Part-DB1\src\Form\UserSettingsType.php:115 - src\Form\UserSettingsType.php:48 - - - user_settings.timezone.placeholder - Fuseau horaire du serveur - - - - - Part-DB1\src\Services\ElementTypeNameGenerator.php:79 - Part-DB1\src\Services\ElementTypeNameGenerator.php:79 - - - attachment.label - Fichier joint - - - - - Part-DB1\src\Services\ElementTypeNameGenerator.php:81 - Part-DB1\src\Services\ElementTypeNameGenerator.php:81 - - - attachment_type.label - Type de fichier joint - - - - - Part-DB1\src\Services\ElementTypeNameGenerator.php:85 - Part-DB1\src\Services\ElementTypeNameGenerator.php:85 - - - measurement_unit.label - Unité de mesure - - - - - Part-DB1\src\Services\ElementTypeNameGenerator.php:90 - Part-DB1\src\Services\ElementTypeNameGenerator.php:90 - - - currency.label - Devise - - - - - Part-DB1\src\Services\ElementTypeNameGenerator.php:91 - Part-DB1\src\Services\ElementTypeNameGenerator.php:91 - - - orderdetail.label - Informations de commande - - - - - Part-DB1\src\Services\ElementTypeNameGenerator.php:92 - Part-DB1\src\Services\ElementTypeNameGenerator.php:92 - - - pricedetail.label - Informations sur les prix - - - - - Part-DB1\src\Services\ElementTypeNameGenerator.php:94 - Part-DB1\src\Services\ElementTypeNameGenerator.php:94 - - - user.label - Utilisateur - - - - - Part-DB1\src\Services\ElementTypeNameGenerator.php:95 - - - parameter.label - Caractéristique - - - - - Part-DB1\src\Services\ElementTypeNameGenerator.php:96 - - - label_profile.label - Profil d'étiquette - - - - - Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:176 - Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:161 - new - - - log.element_deleted.old_name.unknown - Inconnu - - - - - Part-DB1\src\Services\MarkdownParser.php:73 - Part-DB1\src\Services\MarkdownParser.php:73 - - - markdown.loading - Chargement de la remise. Si ce message ne disparaît pas, essayez de recharger la page. - - - - - Part-DB1\src\Services\PasswordResetManager.php:98 - Part-DB1\src\Services\PasswordResetManager.php:98 - - - pw_reset.email.subject - Réinitialisation du mot de passe de votre compte Part-DB - - - - - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:108 - - - tree.tools.tools - Outils - - - - - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:109 - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:107 - src\Services\ToolsTreeBuilder.php:74 - - - tree.tools.edit - Éditer - - - - - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:110 - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:108 - src\Services\ToolsTreeBuilder.php:81 - - - tree.tools.show - Afficher - - - - - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:111 - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:109 - - - tree.tools.system - Système - - - - - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:123 - - - tree.tools.tools.label_dialog - Générateur d'étiquettes - - - - - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:130 - - - tree.tools.tools.label_scanner - Scanner - - - - - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:149 - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:126 - src\Services\ToolsTreeBuilder.php:62 - - - tree.tools.edit.attachment_types - Types de fichier joint - - - - - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:155 - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:132 - src\Services\ToolsTreeBuilder.php:64 - - - tree.tools.edit.categories - Catégories - - - - - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:167 - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:144 - src\Services\ToolsTreeBuilder.php:68 - - - tree.tools.edit.suppliers - Fournisseurs - - - - - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:173 - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:150 - src\Services\ToolsTreeBuilder.php:70 - - - tree.tools.edit.manufacturer - Fabricants - - - - - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:179 - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:156 - - - tree.tools.edit.storelocation - Emplacements de stockage - - - - - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:185 - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:162 - - - tree.tools.edit.footprint - Empreintes - - - - - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:191 - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:168 - - - tree.tools.edit.currency - Devises - - - - - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:197 - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:174 - - - tree.tools.edit.measurement_unit - Unité de mesure - - - - - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:203 - - - tree.tools.edit.label_profile - Profils d'étiquettes - - - - - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:209 - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:180 - - - tree.tools.edit.part - Composant - - - - - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:226 - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:197 - src\Services\ToolsTreeBuilder.php:77 - - - tree.tools.show.all_parts - Voir tous les composants - - - - - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:232 - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:203 - - - tree.tools.show.all_attachments - Fichiers joints - - - - - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:239 - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:210 - new - - - tree.tools.show.statistics - Statistiques - - - - - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:258 - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:229 - - - tree.tools.system.users - Utilisateurs - - - - - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:264 - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:235 - - - tree.tools.system.groups - Groupes - - - - - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:271 - Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:242 - new - - - tree.tools.system.event_log - Système d'événements - - - - - Part-DB1\src\Services\Trees\TreeViewGenerator.php:95 - Part-DB1\src\Services\Trees\TreeViewGenerator.php:95 - src\Services\TreeBuilder.php:124 - - - entity.tree.new - Nouvel élément - - - - - Part-DB1\templates\Parts\info\_attachments_info.html.twig:34 - obsolete - - - attachment.external_file - Fichier extérieur - - - - - Part-DB1\templates\Parts\info\_attachments_info.html.twig:62 - obsolete - - - attachment.edit - Éditer - - - - - Part-DB1\templates\_navbar.html.twig:27 - templates\base.html.twig:88 - obsolete - - - barcode.scan - Scanner un code-barres - - - - - Part-DB1\src\Form\UserSettingsType.php:119 - src\Form\UserSettingsType.php:49 - obsolete - - - user.theme.label - Thème - - - - - Part-DB1\src\Form\UserSettingsType.php:129 - src\Form\UserSettingsType.php:50 - obsolete - - - user_settings.theme.placeholder - Thème du serveur - - - - - Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:100 - new - obsolete - - - log.user_login.ip - IP - - - - - Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:128 - Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:150 - Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:169 - Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:207 - new - obsolete - - - log.undo_mode.undo - Modification annulée - - - - - Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:130 - Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:152 - Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:171 - Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:209 - new - obsolete - - - log.undo_mode.revert - Élément restauré - - - - - Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:139 - new - obsolete - - - log.element_created.original_instock - Ancien stock - - - - - Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:160 - new - obsolete - - - log.element_deleted.old_name - Ancien nom - - - - - Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:184 - new - obsolete - - - log.element_edited.changed_fields - Champs modifiés - - - - - Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:198 - new - obsolete - - - log.instock_changed.comment - Commentaire - - - - - Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:214 - new - obsolete - - - log.collection_deleted.deleted - Élément supprimé : - - - - - templates\base.html.twig:81 - obsolete - obsolete - - - go.exclamation - Allez! - - - - - templates\base.html.twig:109 - obsolete - obsolete - - - language.english - Anglais - - - - - templates\base.html.twig:112 - obsolete - obsolete - - - language.german - Allemand - - - - - obsolete - obsolete - - - flash.password_change_needed - Votre mot de passe doit être changé ! - - - - - obsolete - obsolete - - - attachment.table.type - Type de fichier joint - - - - - obsolete - obsolete - - - attachment.table.element - élément lié - - - - - obsolete - obsolete - - - attachment.edit.isPicture - Image? - - - - - obsolete - obsolete - - - attachment.edit.is3DModel - Modèle 3D? - - - - - obsolete - obsolete - - - attachment.edit.isBuiltin - Intégré? - - - - - obsolete - obsolete - - - category.edit.default_comment.placeholder - Ex. utilisé pour les alimentations à découpage - - - - - obsolete - obsolete - - - tfa_backup.regenerate_codes - Créer de nouveaux codes de secours - - - - - obsolete - obsolete - - - validator.noneofitschild.self - Un élément ne peut pas être son propre parent. - - - - - obsolete - obsolete - - - validator.noneofitschild.children - Le parent ne peut pas être un de ses propres enfants. - - - - - obsolete - obsolete - - - validator.part_lot.location_full.no_increasment - Le lieu de stockage utilisé a été marqué comme étant plein, le stock ne peut donc pas être augmenté. (Nouveau stock maximum {{old_amount}}) - - - - - obsolete - obsolete - - - validator.part_lot.location_full - L'emplacement de stockage est plein, c'est pourquoi aucun nouveau composant ne peut être ajouté. - - - - - obsolete - obsolete - - - validator.part_lot.only_existing - L'emplacement de stockage a été marqué comme "uniquement existant", donc aucun nouveau composant ne peut être ajouté. - - - - - obsolete - obsolete - - - validator.part_lot.single_part - L'emplacement de stockage a été marqué comme "Composant seul", par conséquent aucun nouveau composant ne peut être ajouté. - - - - - obsolete - obsolete - - - m_status.active.help - Le composant est actuellement en cours de production et sera produit dans un avenir proche. - - - - - obsolete - obsolete - - - m_status.announced.help - Le composant a été annoncé, mais n'est pas encore disponible. - - - - - obsolete - obsolete - - - m_status.discontinued.help - Le composant n'est plus fabriqué. - - - - - obsolete - obsolete - - - m_status.eol.help - La production de ce composant sera bientôt arrêtée. - - - - - obsolete - obsolete - - - m_status.nrfnd.help - Ce composant est actuellement en production mais n'est pas recommandé pour les nouvelles conceptions. - - - - - obsolete - obsolete - - - m_status.unknown.help - L'état de la production n'est pas connu. - - - - - obsolete - obsolete - - - flash.success - Succès - - - - - obsolete - obsolete - - - flash.error - Erreur - - - - - obsolete - obsolete - - - flash.warning - Attention - - - - - obsolete - obsolete - - - flash.notice - Remarque - - - - - obsolete - obsolete - - - flash.info - Info - - - - - obsolete - obsolete - - - validator.noLockout - Vous ne pouvez pas révoquer vous-même l'autorisation de "modifier les autorisations" pour éviter de vous verrouiller accidentellement ! - - - - - obsolete - obsolete - - - attachment_type.edit.filetype_filter - Types de fichiers autorisés - - - - - obsolete - obsolete - - - attachment_type.edit.filetype_filter.help - Vous pouvez spécifier ici une liste, séparée par des virgules, des extensions de fichiers ou des mimétapes qu'un fichier téléchargé avec ce type de pièce jointe doit avoir. Pour autoriser tous les fichiers d'images pris en charge, utilisez image/*. - - - - - obsolete - obsolete - - - attachment_type.edit.filetype_filter.placeholder - Ex. .txt, application/pdf, image/* - - - - - src\Form\PartType.php:63 - obsolete - obsolete - - - part.name.placeholder - Ex. BC547 - - - - - obsolete - obsolete - - - entity.edit.not_selectable - Non sélectionnable - - - - - obsolete - obsolete - - - entity.edit.not_selectable.help - Si cette option est activée, alors cet élément ne peut être attribué à aucun composant en tant que propriété. Utile, par exemple si cet élément doit être utilisé uniquement pour le tri. - - - - - obsolete - obsolete - - - bbcode.hint - Le BBCode peut être utilisé ici (par exemple [b]Bold[/b]) - - - - - obsolete - obsolete - - - entity.create - Créer un élément - - - - - obsolete - obsolete - - - entity.edit.save - Sauvegarder - - - - - obsolete - obsolete - - - category.edit.disable_footprints - Désactiver les empreintes - - - - - obsolete - obsolete - - - category.edit.disable_footprints.help - Si cette option est activée, la propriété Empreinte est désactivée pour tous les composants de cette catégorie. - - - - - obsolete - obsolete - - - category.edit.disable_manufacturers - Désactiver les fabricants - - - - - obsolete - obsolete - - - category.edit.disable_manufacturers.help - Si cette option est activée, la propriété fabricant est désactivée pour tous les composants de cette catégorie. - - - - - obsolete - obsolete - - - category.edit.disable_autodatasheets - Désactiver les liens automatiques des fiches techniques - - - - - obsolete - obsolete - - - category.edit.disable_autodatasheets.help - Si cette option est activée, aucun lien automatique avec la fiche technique n'est généré pour les pièces de cette catégorie. - - - - - obsolete - obsolete - - - category.edit.disable_properties - Désactiver les propriétés - - - - - obsolete - obsolete - - - category.edit.disable_properties.help - Si cette option est activée, les propriétés des composants pour tous les composants de cette catégorie sont désactivées. - - - - - obsolete - obsolete - - - category.edit.partname_hint - Indication du nom du composant - - - - - obsolete - obsolete - - - category.edit.partname_hint.placeholder - Ex. 100nF - - - - - obsolete - obsolete - - - category.edit.partname_regex - Filtre de nom - - - - - obsolete - obsolete - - - category.edit.default_description - Description par défaut - - - - - obsolete - obsolete - - - category.edit.default_description.placeholder - Ex. Condensateur, 10mmx10mm, CMS - - - - - obsolete - obsolete - - - category.edit.default_comment - Commentaire par défaut - - - - - obsolete - obsolete - - - company.edit.address - Adresse - - - - - obsolete - obsolete - - - company.edit.address.placeholder - Ex. 99 exemple de rue -exemple de ville - - - - - obsolete - obsolete - - - company.edit.phone_number - Numéro de téléphone - - - - - obsolete - obsolete - - - company.edit.phone_number.placeholder - +33 1 23 45 67 89 - - - - - obsolete - obsolete - - - company.edit.fax_number - Numéro de fax - - - - - obsolete - obsolete - - - company.edit.email - Email - - - - - obsolete - obsolete - - - company.edit.email.placeholder - Ex. contact@foo.bar - - - - - obsolete - obsolete - - - company.edit.website - Site internet - - - - - obsolete - obsolete - - - company.edit.website.placeholder - https://www.foo.bar - - - - - obsolete - obsolete - - - company.edit.auto_product_url - URL du produit - - - - - obsolete - obsolete - - - company.edit.auto_product_url.help - Si cette URL est définie, elle est utilisée pour générer l'URL d'un composant sur le site web du fabricant. Dans ce cas, %PARTNUMBER% sera remplacé par le numéro de commande. - - - - - obsolete - obsolete - - - company.edit.auto_product_url.placeholder - https://foo.bar/product/%PARTNUMBER% - - - - - obsolete - obsolete - - - currency.edit.iso_code - Code ISO - - - - - obsolete - obsolete - - - currency.edit.exchange_rate - Taux de change - - - - - obsolete - obsolete - - - footprint.edit.3d_model - Modèle 3D - - - - - obsolete - obsolete - - - mass_creation.lines - Saisie - - - - - obsolete - obsolete - - - mass_creation.lines.placeholder - Élément 1 -Élément 2 -Élément 3 - - - - - obsolete - obsolete - - - entity.mass_creation.btn - Créer - - - - - obsolete - obsolete - - - measurement_unit.edit.is_integer - Nombre entier - - - - - obsolete - obsolete - - - measurement_unit.edit.is_integer.help - Si cette option est activée, toutes les quantités dans cette unité sont arrondies à des nombres entiers. - - - - - obsolete - obsolete - - - measurement_unit.edit.use_si_prefix - Utiliser les préfixes SI - - - - - obsolete - obsolete - - - measurement_unit.edit.use_si_prefix.help - Si cette option est activée, les préfixes SI sont utilisés lors de la génération des nombres (par exemple 1,2 kg au lieu de 1200 g) - - - - - obsolete - obsolete - - - measurement_unit.edit.unit_symbol - Symbole de l'unité - - - - - obsolete - obsolete - - - measurement_unit.edit.unit_symbol.placeholder - Ex. m - - - - - obsolete - obsolete - - - storelocation.edit.is_full.label - Emplacement de stockage plein - - - - - obsolete - obsolete - - - storelocation.edit.is_full.help - Si cette option est activée, il n'est pas possible d'ajouter de nouveaux composants à ce lieu de stockage ni d'augmenter le nombre de composants existants. - - - - - obsolete - obsolete - - - storelocation.limit_to_existing.label - Limiter aux composants existants - - - - - obsolete - obsolete - - - storelocation.limit_to_existing.help - Si cette option est active, il n'est pas possible d'ajouter de nouveaux composants à ce lieu de stockage, mais il est possible d'augmenter le nombre de composants existants. - - - - - obsolete - obsolete - - - storelocation.only_single_part.label - Seulement un composant - - - - - obsolete - obsolete - - - storelocation.only_single_part.help - Si cette option est activée, cet emplacement de stockage ne peut contenir qu'un seul composant (mais une quantité quelconque). Utile pour les petits compartiments ou les distributeurs de CMS. - - - - - obsolete - obsolete - - - storelocation.storage_type.label - Type de stockage - - - - - obsolete - obsolete - - - storelocation.storage_type.help - Ici, vous pouvez sélectionner une unité de mesure qu'un composant doit avoir pour être stocké dans ce lieu de stockage. - - - - - obsolete - obsolete - - - supplier.edit.default_currency - Devise par défaut - - - - - obsolete - obsolete - - - supplier.shipping_costs.label - Frais de port - - - - - obsolete - obsolete - - - user.username.placeholder - Ex. j.doe - - - - - obsolete - obsolete - - - user.firstName.placeholder - Ex. John - - - - - obsolete - obsolete - - - user.lastName.placeholder - Ex. Doe - - - - - obsolete - obsolete - - - user.email.placeholder - j.doe@ecorp.com - - - - - obsolete - obsolete - - - user.department.placeholder - Ex. Development - - - - - obsolete - obsolete - - - user.settings.pw_new.label - Nouveau mot de passe - - - - - obsolete - obsolete - - - user.settings.pw_confirm.label - Confirmer le nouveau mot de passe - - - - - obsolete - obsolete - - - user.edit.needs_pw_change - L'utilisateur doit changer de mot de passe - - - - - obsolete - obsolete - - - user.edit.user_disabled - Utilisateur désactivé (connexion impossible) - - - - - obsolete - obsolete - - - user.create - Créer l'utilisateur - - - - - obsolete - obsolete - - - user.edit.save - Enregistrer - - - - - obsolete - obsolete - - - entity.edit.reset - Rejeter les modifications - - - - - templates\Parts\show_part_info.html.twig:166 - obsolete - obsolete - - - part.withdraw.btn - Retrait - - - - - templates\Parts\show_part_info.html.twig:171 - obsolete - obsolete - - - part.withdraw.comment: - Commentaire/objet - - - - - templates\Parts\show_part_info.html.twig:189 - obsolete - obsolete - - - part.add.caption - Ajouter composants - - - - - templates\Parts\show_part_info.html.twig:194 - obsolete - obsolete - - - part.add.btn - Ajouter - - - - - templates\Parts\show_part_info.html.twig:199 - obsolete - obsolete - - - part.add.comment - Commentaire/objet - - - - - templates\AdminPages\CompanyAdminBase.html.twig:15 - obsolete - obsolete - - - admin.comment - Commentaire - - - - - src\Form\PartType.php:83 - obsolete - obsolete - - - manufacturer_url.label - Lien vers le site du fabricant - - - - - src\Form\PartType.php:66 - obsolete - obsolete - - - part.description.placeholder - Ex. NPN 45V 0,1A 0,5W - - - - - src\Form\PartType.php:69 - obsolete - obsolete - - - part.instock.placeholder - Ex. 10 - - - - - src\Form\PartType.php:72 - obsolete - obsolete - - - part.mininstock.placeholder - Ex. 10 - - - - - obsolete - obsolete - - - part.order.price_per - Prix par - - - - - obsolete - obsolete - - - part.withdraw.caption - Retrait de composants - - - - - obsolete - obsolete - - - datatable.datatable.lengthMenu - _MENU_ - - - - - obsolete - obsolete - - - perm.group.parts - Composants - - - - - obsolete - obsolete - - - perm.group.structures - Structures des données - - - - - obsolete - obsolete - - - perm.group.system - Système - - - - - obsolete - obsolete - - - perm.parts - Général - - - - - obsolete - obsolete - - - perm.read - Afficher - - - - - obsolete - obsolete - - - perm.edit - Éditer - - - - - obsolete - obsolete - - - perm.create - Créer - - - - - obsolete - obsolete - - - perm.part.move - Changer de catégorie - - - - - obsolete - obsolete - - - perm.delete - Supprimer - - - - - obsolete - obsolete - - - perm.part.search - Rechercher - - - - - obsolete - obsolete - - - perm.part.all_parts - Liste de tous les composants - - - - - obsolete - obsolete - - - perm.part.no_price_parts - Liste des composants sans prix - - - - - obsolete - obsolete - - - perm.part.obsolete_parts - Liste des composants obsolètes - - - - - obsolete - obsolete - - - perm.part.unknown_instock_parts - Liste des composants dont le stock est inconnu - - - - - obsolete - obsolete - - - perm.part.change_favorite - Changer le statut de favori - - - - - obsolete - obsolete - - - perm.part.show_favorite - Afficher les favoris - - - - - obsolete - obsolete - - - perm.part.show_last_edit_parts - Afficher les derniers composants modifiés/ajoutés - - - - - obsolete - obsolete - - - perm.part.show_users - Afficher le dernier utilisateur ayant apporté des modifications - - - - - obsolete - obsolete - - - perm.part.show_history - Afficher l'historique - - - - - obsolete - obsolete - - - perm.part.name - Nom - - - - - obsolete - obsolete - - - perm.part.description - Description - - - - - obsolete - obsolete - - - perm.part.instock - En stock - - - - - obsolete - obsolete - - - perm.part.mininstock - Stock minimum - - - - - obsolete - obsolete - - - perm.part.comment - Commentaire - - - - - obsolete - obsolete - - - perm.part.storelocation - Emplacement de stockage - - - - - obsolete - obsolete - - - perm.part.manufacturer - Fabricant - - - - - obsolete - obsolete - - - perm.part.orderdetails - Informations pour la commande - - - - - obsolete - obsolete - - - perm.part.prices - Prix - - - - - obsolete - obsolete - - - perm.part.attachments - Fichiers joints - - - - - obsolete - obsolete - - - perm.part.order - Commandes - - - - - obsolete - obsolete - - - perm.storelocations - Emplacements de stockage - - - - - obsolete - obsolete - - - perm.move - Déplacer - - - - - obsolete - obsolete - - - perm.list_parts - Liste des composants - - - - - obsolete - obsolete - - - perm.part.footprints - Empreintes - - - - - obsolete - obsolete - - - perm.part.categories - Catégories - - - - - obsolete - obsolete - - - perm.part.supplier - Fournisseurs - - - - - obsolete - obsolete - - - perm.part.manufacturers - Fabricants - - - - - obsolete - obsolete - - - perm.part.attachment_types - Types de fichiers joints - - - - - obsolete - obsolete - - - perm.tools.import - Importer - - - - - obsolete - obsolete - - - perm.tools.labels - Étiquettes - - - - - obsolete - obsolete - - - perm.tools.calculator - Calculateur de résistance - - - - - obsolete - obsolete - - - perm.tools.footprints - Empreintes - - - - - obsolete - obsolete - - - perm.tools.ic_logos - Logos CI - - - - - obsolete - obsolete - - - perm.tools.statistics - Statistiques - - - - - obsolete - obsolete - - - perm.edit_permissions - Éditer les autorisations - - - - - obsolete - obsolete - - - perm.users.edit_user_name - Modifier le nom d'utilisateur - - - - - obsolete - obsolete - - - perm.users.edit_change_group - Modifier le groupe - - - - - obsolete - obsolete - - - perm.users.edit_infos - Editer les informations - - - - - obsolete - obsolete - - - perm.users.edit_permissions - Modifier les autorisations - - - - - obsolete - obsolete - - - perm.users.set_password - Définir le mot de passe - - - - - obsolete - obsolete - - - perm.users.change_user_settings - Changer les paramètres utilisateur - - - - - obsolete - obsolete - - - perm.database.see_status - Afficher l’état - - - - - obsolete - obsolete - - - perm.database.update_db - Actualiser la base de données - - - - - obsolete - obsolete - - - perm.database.read_db_settings - Lecture des paramètres de la base de donnée - - - - - obsolete - obsolete - - - perm.database.write_db_settings - Modifier les paramètres de la base de données - - - - - obsolete - obsolete - - - perm.config.read_config - Lecture de la configuration - - - - - obsolete - obsolete - - - perm.config.edit_config - Modifier la configuration - - - - - obsolete - obsolete - - - perm.config.server_info - Informations sur le serveur - - - - - obsolete - obsolete - - - perm.config.use_debug - Utiliser les outils de débogage - - - - - obsolete - obsolete - - - perm.show_logs - Afficher les logs - - - - - obsolete - obsolete - - - perm.delete_logs - Supprimer les logs - - - - - obsolete - obsolete - - - perm.self.edit_infos - Modifier les informations - - - - - obsolete - obsolete - - - perm.self.edit_username - Modifier le nom d'utilisateur - - - - - obsolete - obsolete - - - perm.self.show_permissions - Voir les autorisations - - - - - obsolete - obsolete - - - perm.self.show_logs - Afficher ses propres logs - - - - - obsolete - obsolete - - - perm.self.create_labels - Créer des étiquettes - - - - - obsolete - obsolete - - - perm.self.edit_options - Modifier les options - - - - - obsolete - obsolete - - - perm.self.delete_profiles - Supprimer les profils - - - - - obsolete - obsolete - - - perm.self.edit_profiles - Modifier les profils - - - - - obsolete - obsolete - - - perm.part.tools - Outils - - - - - obsolete - obsolete - - - perm.groups - Groupes - - - - - obsolete - obsolete - - - perm.users - Utilisateurs - - - - - obsolete - obsolete - - - perm.database - Base de données - - - - - obsolete - obsolete - - - perm.config - Configuration - - - - - obsolete - obsolete - - - perm.system - Système - - - - - obsolete - obsolete - - - perm.self - Propre utilisateur - - - - - obsolete - obsolete - - - perm.labels - Étiquettes - - - - - obsolete - obsolete - - - perm.part.category - Catégorie - - - - - obsolete - obsolete - - - perm.part.minamount - Quantité minimum - - - - - obsolete - obsolete - - - perm.part.footprint - Empreinte - - - - - obsolete - obsolete - - - perm.part.mpn - MPN - - - - - obsolete - obsolete - - - perm.part.status - État de la fabrication - - - - - obsolete - obsolete - - - perm.part.tags - Tags - - - - - obsolete - obsolete - - - perm.part.unit - Unité - - - - - obsolete - obsolete - - - perm.part.mass - Poids - - - - - obsolete - obsolete - - - perm.part.lots - Lots de composants - - - - - obsolete - obsolete - - - perm.show_users - Afficher le dernier utilisateur ayant apporté des modifications - - - - - obsolete - obsolete - - - perm.currencies - Devises - - - - - obsolete - obsolete - - - perm.measurement_units - Unités de mesure - - - - - obsolete - obsolete - - - user.settings.pw_old.label - Ancien mot de passe - - - - - obsolete - obsolete - - - pw_reset.submit - Réinitialiser le mot de passe - - - - - obsolete - obsolete - - - u2f_two_factor - Clé de sécurité (U2F) - - - - - obsolete - obsolete - - - google - google - - - - - obsolete - obsolete - - - tfa.provider.google - Application d'authentification - - - - - obsolete - obsolete - - - Login successful - Connexion réussie - - - - - obsolete - obsolete - - - log.type.exception - Exception - - - - - obsolete - obsolete - - - log.type.user_login - Connexion utilisateur - - - - - obsolete - obsolete - - - log.type.user_logout - Déconnexion de l’utilisateur - - - - - obsolete - obsolete - - - log.type.unknown - Inconnu - - - - - obsolete - obsolete - - - log.type.element_created - Élément créé - - - - - obsolete - obsolete - - - log.type.element_edited - Élément modifié - - - - - obsolete - obsolete - - - log.type.element_deleted - Élément supprimé - - - - - obsolete - obsolete - - - log.type.database_updated - Base de données mise à jour - - - - - obsolete - - - perm.revert_elements - Restaurer les éléments - - - - - obsolete - - - perm.show_history - Afficher l'historique - - - - - obsolete - - - perm.tools.lastActivity - Afficher l'activité récente - - - - - obsolete - - - perm.tools.timeTravel - Afficher les anciennes versions des éléments (Time travel) - - - - - obsolete - - - tfa_u2f.key_added_successful - Clé de sécurité ajoutée avec succès. - - - - - obsolete - - - Username - Nom d'utilisateur - - - - - obsolete - - - log.type.security.google_disabled - Application d'authentification désactivée - - - - - obsolete - - - log.type.security.u2f_removed - Clé de sécurité enlevée - - - - - obsolete - - - log.type.security.u2f_added - Clé de sécurité ajoutée - - - - - obsolete - - - log.type.security.backup_keys_reset - Clés de sauvegarde régénérées - - - - - obsolete - - - log.type.security.google_enabled - Application Authenticator activée - - - - - obsolete - - - log.type.security.password_changed - Mot de passe modifié - - - - - obsolete - - - log.type.security.trusted_device_reset - Appareils de confiance réinitialisés - - - - - obsolete - - - log.type.collection_element_deleted - Élément de collecte supprimé - - - - - obsolete - - - log.type.security.password_reset - Réinitialisation du mot de passe - - - - - obsolete - - - log.type.security.2fa_admin_reset - Réinitialisation à deux facteurs par l'administrateur - - - - - obsolete - - - log.type.user_not_allowed - Tentative d'accès non autorisé - - - - - obsolete - - - log.database_updated.success - Succès - - - - - obsolete - - - label_options.barcode_type.2D - 2D - - - - - obsolete - - - label_options.barcode_type.1D - 1D - - - - - obsolete - - - perm.part.parameters - Caractéristiques - - - - - obsolete - - - perm.attachment_show_private - Voir les pièces jointes privées - - - - - obsolete - - - perm.tools.label_scanner - Lecteur d'étiquettes - - - - - obsolete - - - perm.self.read_profiles - Lire les profils - - - - - obsolete - - - perm.self.create_profiles - Créer des profils - - - - - obsolete - - - perm.labels.use_twig - Utiliser le mode twig - - - - - label_profile.showInDropdown - Afficher en sélection rapide - - - - - group.edit.enforce_2fa - Imposer l'authentification à deux facteurs (2FA) - - - - - group.edit.enforce_2fa.help - Si cette option est activée, chaque membre direct de ce groupe doit configurer au moins un deuxième facteur d'authentification. Recommandé pour les groupes administratifs ayant beaucoup de permissions. - - - - - selectpicker.empty - Rien n'est sélectionné - - - - - selectpicker.nothing_selected - Rien n'est sélectionné - - - - - entity.delete.must_not_contain_parts - L'élement contient encore des parties ! Vous devez déplacer les parties pour pouvoir supprimer cet élément. - - - - - entity.delete.must_not_contain_attachments - Le type de pièce jointe contient toujours des pièces jointes. Changez leur type, pour pouvoir supprimer ce type de pièce jointe. - - - - - entity.delete.must_not_contain_prices - La devise contient encore des prix. Vous devez changer leur devise pour pouvoir supprimer cet élément. - - - - - entity.delete.must_not_contain_users - Des utilisateurs utilisent toujours ce groupe ! Changez les de groupe pour pouvoir supprimer ce groupe. - - - - - part.table.edit - Modifier - - - - - part.table.edit.title - Modifier composant - - - - - part_list.action.action.title - Sélectionnez une action - - - - - part_list.action.action.group.favorite - Statut favori - - - - - part_list.action.action.favorite - Favorable - - - - - part_list.action.action.unfavorite - Défavorable - - - - - part_list.action.action.group.change_field - Modifier le champ - - - - - part_list.action.action.change_category - Modifier la catégorie - - - - - part_list.action.action.change_footprint - Modifier l'empreinte - - - - - part_list.action.action.change_manufacturer - Modifier le fabricant - - - - - part_list.action.action.change_unit - Modifier l'unité - - - - - part_list.action.action.delete - Supprimer - - - - - part_list.action.submit - Soumettre - - - - - part_list.action.part_count - %count% composants sélectionnés - - - - - company.edit.quick.website - Ouvrir le site web - - - - - company.edit.quick.email - Envoyer un e-mail - - - - - company.edit.quick.phone - Téléphoner - - - - - company.edit.quick.fax - Envoyer une télécopie - - - - - company.fax_number.placeholder - ex. +33 12 34 56 78 90 - - - - - part.edit.save_and_clone - Sauvegarder et dupliquer - - - - - validator.file_ext_not_allowed - L'extension de fichier n'est pas autorisée pour ce type de pièce jointe. - - - - - tools.reel_calc.title - Calculateur de bobines CMS - - - - - tools.reel_calc.inner_dia - Diamètre intérieur - - - - - tools.reel_calc.outer_dia - Diamètre extérieur - - - - - tools.reel_calc.tape_thick - Épaisseur du ruban - - - - - tools.reel_calc.part_distance - Distance entre les composants - - - - - tools.reel_calc.update - Actualiser - - - - - tools.reel_calc.parts_per_meter - Composants par mètre - - - - - tools.reel_calc.result_length - Longueur de la bande - - - - - tools.reel_calc.result_amount - Nbre approximatif de composants - - - - - tools.reel_calc.outer_greater_inner_error - Erreur : Le diamètre extérieur doit être supérieur au diamètre intérieur ! - - - - - tools.reel_calc.missing_values.error - Veuillez remplir toutes les valeurs ! - - - - - tools.reel_calc.load_preset - Charger la présélection - - - - - tools.reel_calc.explanation - Ce calculateur vous donne une estimation du nombre de pièces qui restent sur une bobine de CMS. Mesurez les dimensions notées sur la bobine (ou utilisez certains des préréglages) et cliquez sur "Actualiser" pour obtenir un résultat. - - - - - perm.tools.reel_calculator - Calculateur de bobines CMS - - - - - tree.tools.tools.reel_calculator - Calculateur de bobines CMS - - - - - currency.edit.update_rate - Taux de rafraîchissement - - - - - currency.edit.exchange_rate_update.unsupported_currency - Devise non prise en charge - - - - - currency.edit.exchange_rate_update.generic_error - Erreur générique - - - - - currency.edit.exchange_rate_updated.success - Succès - - - - - homepage.forum.text - Si vous avez des questions à propos de Part-DB , rendez vous sur <a href="%href%" class="link-external" target="_blank">Github</a> - - - - + + + + + + Part-DB1\templates\AdminPages\AttachmentTypeAdmin.html.twig:4 + Part-DB1\templates\AdminPages\AttachmentTypeAdmin.html.twig:4 + templates\AdminPages\AttachmentTypeAdmin.html.twig:4 + + + attachment_type.caption + Types pour fichiers joints + + + + + Part-DB1\templates\AdminPages\AttachmentTypeAdmin.html.twig:12 + new + + + attachment_type.edit + Modifier le type de pièce jointe + + + + + Part-DB1\templates\AdminPages\AttachmentTypeAdmin.html.twig:16 + new + + + attachment_type.new + Nouveau type de pièce jointe + + + + + Part-DB1\templates\AdminPages\CategoryAdmin.html.twig:4 + Part-DB1\templates\_sidebar.html.twig:22 + Part-DB1\templates\_sidebar.html.twig:7 + Part-DB1\templates\AdminPages\CategoryAdmin.html.twig:4 + Part-DB1\templates\_sidebar.html.twig:22 + Part-DB1\templates\_sidebar.html.twig:7 + templates\AdminPages\CategoryAdmin.html.twig:4 + templates\base.html.twig:163 + templates\base.html.twig:170 + templates\base.html.twig:197 + templates\base.html.twig:225 + + + category.labelp + Catégories + + + + + Part-DB1\templates\AdminPages\CategoryAdmin.html.twig:8 + Part-DB1\templates\AdminPages\StorelocationAdmin.html.twig:19 + Part-DB1\templates\AdminPages\CategoryAdmin.html.twig:8 + Part-DB1\templates\AdminPages\StorelocationAdmin.html.twig:11 + templates\AdminPages\CategoryAdmin.html.twig:8 + + + admin.options + Options + + + + + Part-DB1\templates\AdminPages\CategoryAdmin.html.twig:9 + Part-DB1\templates\AdminPages\CompanyAdminBase.html.twig:15 + Part-DB1\templates\AdminPages\CategoryAdmin.html.twig:9 + Part-DB1\templates\AdminPages\CompanyAdminBase.html.twig:15 + templates\AdminPages\CategoryAdmin.html.twig:9 + + + admin.advanced + Avancé + + + + + Part-DB1\templates\AdminPages\CategoryAdmin.html.twig:13 + new + + + category.edit + Éditer la catégorie + + + + + Part-DB1\templates\AdminPages\CategoryAdmin.html.twig:17 + new + + + category.new + Nouvelle catégorie + + + + + Part-DB1\templates\AdminPages\CurrencyAdmin.html.twig:4 + Part-DB1\templates\AdminPages\CurrencyAdmin.html.twig:4 + + + currency.caption + Devise + + + + + Part-DB1\templates\AdminPages\CurrencyAdmin.html.twig:12 + Part-DB1\templates\AdminPages\CurrencyAdmin.html.twig:12 + + + currency.iso_code.caption + Code ISO + + + + + Part-DB1\templates\AdminPages\CurrencyAdmin.html.twig:15 + Part-DB1\templates\AdminPages\CurrencyAdmin.html.twig:15 + + + currency.symbol.caption + Symbole de la devise + + + + + Part-DB1\templates\AdminPages\CurrencyAdmin.html.twig:29 + new + + + currency.edit + Editer la devise + + + + + Part-DB1\templates\AdminPages\CurrencyAdmin.html.twig:33 + new + + + currency.new + Nouvelle devise + + + + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:19 + Part-DB1\templates\_navbar_search.html.twig:67 + Part-DB1\templates\_sidebar.html.twig:27 + Part-DB1\templates\_sidebar.html.twig:43 + Part-DB1\templates\_sidebar.html.twig:63 + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:19 + Part-DB1\templates\_navbar_search.html.twig:61 + Part-DB1\templates\_sidebar.html.twig:27 + Part-DB1\templates\_sidebar.html.twig:43 + Part-DB1\templates\_sidebar.html.twig:63 + templates\AdminPages\EntityAdminBase.html.twig:9 + templates\base.html.twig:80 + templates\base.html.twig:179 + templates\base.html.twig:206 + templates\base.html.twig:237 + + + search.placeholder + Recherche + + + + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:23 + Part-DB1\templates\_sidebar.html.twig:3 + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:23 + Part-DB1\templates\_sidebar.html.twig:3 + templates\AdminPages\EntityAdminBase.html.twig:13 + templates\base.html.twig:166 + templates\base.html.twig:193 + templates\base.html.twig:221 + + + expandAll + Agrandir tout + + + + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:27 + Part-DB1\templates\_sidebar.html.twig:4 + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:27 + Part-DB1\templates\_sidebar.html.twig:4 + templates\AdminPages\EntityAdminBase.html.twig:17 + templates\base.html.twig:167 + templates\base.html.twig:194 + templates\base.html.twig:222 + + + reduceAll + Réduire tout + + + + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:54 + Part-DB1\templates\Parts\info\_sidebar.html.twig:4 + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:54 + Part-DB1\templates\Parts\info\_sidebar.html.twig:4 + + + part.info.timetravel_hint + C'est ainsi que le composant apparaissait avant le %timestamp%. <i>Veuillez noter que cette fonctionnalité est expérimentale, donc les infos ne sont peut-être pas correctes. </i> + + + + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:60 + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:60 + templates\AdminPages\EntityAdminBase.html.twig:42 + + + standard.label + Propriétés + + + + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:61 + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:61 + templates\AdminPages\EntityAdminBase.html.twig:43 + + + infos.label + Informations + + + + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:63 + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:63 + new + + + history.label + Historique + + + + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:66 + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:66 + templates\AdminPages\EntityAdminBase.html.twig:45 + + + export.label + Exporter + + + + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:68 + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:68 + templates\AdminPages\EntityAdminBase.html.twig:47 + + + import_export.label + Importer exporter + + + + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:69 + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:69 + + + mass_creation.label + Création multiple + + + + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:82 + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:82 + templates\AdminPages\EntityAdminBase.html.twig:59 + + + admin.common + Commun + + + + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:86 + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:86 + + + admin.attachments + Fichiers joints + + + + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:90 + + + admin.parameters + Paramètres + + + + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:179 + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:167 + templates\AdminPages\EntityAdminBase.html.twig:142 + + + export_all.label + Exporter tous les éléments + + + + + export.readable.label + Export lisible + + + + + export.readable + CSV + + + + + export.readable_bom + PDF + + + + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:185 + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:173 + + + mass_creation.help + Chaque ligne sera interprétée comme le nom d'un élément qui sera créé. + + + + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:45 + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:45 + templates\AdminPages\EntityAdminBase.html.twig:35 + + + edit.caption + Éditer l'élément "%name" + + + + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:50 + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:50 + templates\AdminPages\EntityAdminBase.html.twig:37 + + + new.caption + Nouvel élément + + + + + Part-DB1\templates\AdminPages\FootprintAdmin.html.twig:4 + Part-DB1\templates\_sidebar.html.twig:9 + Part-DB1\templates\AdminPages\FootprintAdmin.html.twig:4 + Part-DB1\templates\_sidebar.html.twig:9 + templates\base.html.twig:172 + templates\base.html.twig:199 + templates\base.html.twig:227 + + + footprint.labelp + Empreintes + + + + + Part-DB1\templates\AdminPages\FootprintAdmin.html.twig:13 + new + + + footprint.edit + Editer l'empreinte + + + + + Part-DB1\templates\AdminPages\FootprintAdmin.html.twig:17 + new + + + footprint.new + Nouvelle empreinte + + + + + Part-DB1\templates\AdminPages\GroupAdmin.html.twig:4 + Part-DB1\templates\AdminPages\GroupAdmin.html.twig:4 + + + group.edit.caption + Groupes + + + + + Part-DB1\templates\AdminPages\GroupAdmin.html.twig:9 + Part-DB1\templates\AdminPages\UserAdmin.html.twig:16 + Part-DB1\templates\AdminPages\GroupAdmin.html.twig:9 + Part-DB1\templates\AdminPages\UserAdmin.html.twig:16 + + + user.edit.permissions + Permissions + + + + + Part-DB1\templates\AdminPages\GroupAdmin.html.twig:24 + new + + + group.edit + Editer le groupe + + + + + Part-DB1\templates\AdminPages\GroupAdmin.html.twig:28 + new + + + group.new + Nouveau groupe + + + + + Part-DB1\templates\AdminPages\LabelProfileAdmin.html.twig:4 + + + label_profile.caption + Profil des étiquettes + + + + + Part-DB1\templates\AdminPages\LabelProfileAdmin.html.twig:8 + + + label_profile.advanced + Avancé + + + + + Part-DB1\templates\AdminPages\LabelProfileAdmin.html.twig:9 + + + label_profile.comment + Commentaire + + + + + Part-DB1\templates\AdminPages\LabelProfileAdmin.html.twig:55 + new + + + label_profile.edit + Editer profil d'étiquette + + + + + Part-DB1\templates\AdminPages\LabelProfileAdmin.html.twig:59 + new + + + label_profile.new + Nouveau profil d'étiquette + + + + + Part-DB1\templates\AdminPages\ManufacturerAdmin.html.twig:4 + Part-DB1\templates\AdminPages\ManufacturerAdmin.html.twig:4 + templates\AdminPages\ManufacturerAdmin.html.twig:4 + + + manufacturer.caption + Fabricants + + + + + Part-DB1\templates\AdminPages\ManufacturerAdmin.html.twig:8 + new + + + manufacturer.edit + Modifiez le fabricant + + + + + Part-DB1\templates\AdminPages\ManufacturerAdmin.html.twig:12 + new + + + manufacturer.new + Nouveau fabricant + + + + + Part-DB1\templates\AdminPages\MeasurementUnitAdmin.html.twig:4 + Part-DB1\templates\AdminPages\MeasurementUnitAdmin.html.twig:4 + + + measurement_unit.caption + Unité de mesure + + + + + Part-DB1\templates\AdminPages\StorelocationAdmin.html.twig:5 + Part-DB1\templates\_sidebar.html.twig:8 + Part-DB1\templates\AdminPages\StorelocationAdmin.html.twig:4 + Part-DB1\templates\_sidebar.html.twig:8 + templates\base.html.twig:171 + templates\base.html.twig:198 + templates\base.html.twig:226 + + + storelocation.labelp + Emplacement de stockage + + + + + Part-DB1\templates\AdminPages\StorelocationAdmin.html.twig:32 + new + + + storelocation.edit + Modifier l'emplacement de stockage + + + + + Part-DB1\templates\AdminPages\StorelocationAdmin.html.twig:36 + new + + + storelocation.new + Nouvel emplacement de stockage + + + + + Part-DB1\templates\AdminPages\SupplierAdmin.html.twig:4 + Part-DB1\templates\AdminPages\SupplierAdmin.html.twig:4 + templates\AdminPages\SupplierAdmin.html.twig:4 + + + supplier.caption + Fournisseurs + + + + + Part-DB1\templates\AdminPages\SupplierAdmin.html.twig:16 + new + + + supplier.edit + Modifier le fournisseur + + + + + Part-DB1\templates\AdminPages\SupplierAdmin.html.twig:20 + new + + + supplier.new + Nouveau fournisseur + + + + + Part-DB1\templates\AdminPages\UserAdmin.html.twig:8 + Part-DB1\templates\AdminPages\UserAdmin.html.twig:8 + + + user.edit.caption + Utilisateurs + + + + + Part-DB1\templates\AdminPages\UserAdmin.html.twig:14 + Part-DB1\templates\AdminPages\UserAdmin.html.twig:14 + + + user.edit.configuration + Configuration + + + + + Part-DB1\templates\AdminPages\UserAdmin.html.twig:15 + Part-DB1\templates\AdminPages\UserAdmin.html.twig:15 + + + user.edit.password + Mot de passe + + + + + Part-DB1\templates\AdminPages\UserAdmin.html.twig:45 + Part-DB1\templates\AdminPages\UserAdmin.html.twig:45 + + + user.edit.tfa.caption + Authentification à deux facteurs + + + + + Part-DB1\templates\AdminPages\UserAdmin.html.twig:47 + Part-DB1\templates\AdminPages\UserAdmin.html.twig:47 + + + user.edit.tfa.google_active + Application d'authentification active + + + + + Part-DB1\templates\AdminPages\UserAdmin.html.twig:48 + Part-DB1\templates\Users\backup_codes.html.twig:15 + Part-DB1\templates\Users\_2fa_settings.html.twig:95 + Part-DB1\templates\AdminPages\UserAdmin.html.twig:48 + Part-DB1\templates\Users\backup_codes.html.twig:15 + Part-DB1\templates\Users\_2fa_settings.html.twig:95 + + + tfa_backup.remaining_tokens + Nombre de codes de secours restant + + + + + Part-DB1\templates\AdminPages\UserAdmin.html.twig:49 + Part-DB1\templates\Users\backup_codes.html.twig:17 + Part-DB1\templates\Users\_2fa_settings.html.twig:96 + Part-DB1\templates\AdminPages\UserAdmin.html.twig:49 + Part-DB1\templates\Users\backup_codes.html.twig:17 + Part-DB1\templates\Users\_2fa_settings.html.twig:96 + + + tfa_backup.generation_date + Date de génération des codes de secours + + + + + Part-DB1\templates\AdminPages\UserAdmin.html.twig:53 + Part-DB1\templates\AdminPages\UserAdmin.html.twig:60 + Part-DB1\templates\AdminPages\UserAdmin.html.twig:53 + Part-DB1\templates\AdminPages\UserAdmin.html.twig:60 + + + user.edit.tfa.disabled + Méthode désactivée + + + + + Part-DB1\templates\AdminPages\UserAdmin.html.twig:56 + Part-DB1\templates\AdminPages\UserAdmin.html.twig:56 + + + user.edit.tfa.u2f_keys_count + Clés de sécurité actives + + + + + Part-DB1\templates\AdminPages\UserAdmin.html.twig:72 + Part-DB1\templates\AdminPages\UserAdmin.html.twig:72 + + + user.edit.tfa.disable_tfa_title + Voulez vous vraiment poursuivre ? + + + + + Part-DB1\templates\AdminPages\UserAdmin.html.twig:72 + Part-DB1\templates\AdminPages\UserAdmin.html.twig:72 + + + user.edit.tfa.disable_tfa_message + Cela désactivera <b> toutes les méthodes d'authentification à deux facteurs de l'utilisateur</b> et supprimera <b>les codes de secours</b>! +<br> +L'utilisateur devra configurer à nouveau toutes les méthodes d'authentification à deux facteurs et créer de nouveaux codes de secours!<br><br> +<b>Ne faites ceci qu'en étant sûr de l'identité de l'utilisateur (ayant besoin d'aide),autrement le compte pourrai être compromis!</b> + + + + + Part-DB1\templates\AdminPages\UserAdmin.html.twig:73 + Part-DB1\templates\AdminPages\UserAdmin.html.twig:73 + + + user.edit.tfa.disable_tfa.btn + Désactiver toutes les méthodes d'authentification à deux facteurs + + + + + Part-DB1\templates\AdminPages\UserAdmin.html.twig:85 + new + + + user.edit + Modifier l'utilisateur + + + + + Part-DB1\templates\AdminPages\UserAdmin.html.twig:89 + new + + + user.new + Nouvel utilisateur + + + + + Part-DB1\templates\AdminPages\_attachments.html.twig:4 + Part-DB1\templates\Parts\edit\_attachments.html.twig:4 + Part-DB1\templates\AdminPages\_attachments.html.twig:4 + Part-DB1\templates\Parts\edit\_attachments.html.twig:4 + Part-DB1\templates\Parts\info\_attachments_info.html.twig:63 + + + attachment.delete + Supprimer + + + + + Part-DB1\templates\AdminPages\_attachments.html.twig:41 + Part-DB1\templates\Parts\edit\_attachments.html.twig:38 + Part-DB1\templates\Parts\info\_attachments_info.html.twig:35 + Part-DB1\src\DataTables\AttachmentDataTable.php:159 + Part-DB1\templates\Parts\edit\_attachments.html.twig:38 + Part-DB1\src\DataTables\AttachmentDataTable.php:159 + + + attachment.external + Externe + + + + + Part-DB1\templates\AdminPages\_attachments.html.twig:49 + Part-DB1\templates\Parts\edit\_attachments.html.twig:47 + Part-DB1\templates\AdminPages\_attachments.html.twig:47 + Part-DB1\templates\Parts\edit\_attachments.html.twig:45 + + + attachment.preview.alt + Miniature du fichier joint + + + + + Part-DB1\templates\AdminPages\_attachments.html.twig:52 + Part-DB1\templates\Parts\edit\_attachments.html.twig:50 + Part-DB1\templates\Parts\info\_attachments_info.html.twig:62 + Part-DB1\templates\AdminPages\_attachments.html.twig:50 + Part-DB1\templates\Parts\edit\_attachments.html.twig:48 + Part-DB1\templates\Parts\info\_attachments_info.html.twig:45 + + + attachment.view + Afficher + + + + + Part-DB1\templates\AdminPages\_attachments.html.twig:58 + Part-DB1\templates\Parts\edit\_attachments.html.twig:56 + Part-DB1\templates\Parts\info\_attachments_info.html.twig:43 + Part-DB1\src\DataTables\AttachmentDataTable.php:166 + Part-DB1\templates\AdminPages\_attachments.html.twig:56 + Part-DB1\templates\Parts\edit\_attachments.html.twig:54 + Part-DB1\templates\Parts\info\_attachments_info.html.twig:38 + Part-DB1\src\DataTables\AttachmentDataTable.php:166 + + + attachment.file_not_found + Fichier introuvable + + + + + Part-DB1\templates\AdminPages\_attachments.html.twig:66 + Part-DB1\templates\Parts\edit\_attachments.html.twig:64 + Part-DB1\templates\Parts\info\_attachments_info.html.twig:48 + Part-DB1\templates\Parts\edit\_attachments.html.twig:62 + + + attachment.secure + Fichier joint privé + + + + + Part-DB1\templates\AdminPages\_attachments.html.twig:79 + Part-DB1\templates\Parts\edit\_attachments.html.twig:77 + Part-DB1\templates\AdminPages\_attachments.html.twig:77 + Part-DB1\templates\Parts\edit\_attachments.html.twig:75 + + + attachment.create + Ajouter un fichier joint + + + + + Part-DB1\templates\AdminPages\_attachments.html.twig:84 + Part-DB1\templates\Parts\edit\_attachments.html.twig:82 + Part-DB1\templates\Parts\edit\_lots.html.twig:33 + Part-DB1\templates\AdminPages\_attachments.html.twig:82 + Part-DB1\templates\Parts\edit\_attachments.html.twig:80 + Part-DB1\templates\Parts\edit\_lots.html.twig:33 + + + part_lot.edit.delete.confirm + Voulez vous vraiment supprimer ce stock ? Cette action ne pourra pas être annulée! + + + + + Part-DB1\templates\AdminPages\_delete_form.html.twig:2 + Part-DB1\templates\AdminPages\_delete_form.html.twig:2 + templates\AdminPages\_delete_form.html.twig:2 + + + entity.delete.confirm_title + Voulez vous vraiment supprimer %name%? + + + + + Part-DB1\templates\AdminPages\_delete_form.html.twig:3 + Part-DB1\templates\AdminPages\_delete_form.html.twig:3 + templates\AdminPages\_delete_form.html.twig:3 + + + entity.delete.message + Cette action ne pourra pas être annulée! +<br> +Les sous éléments seront déplacés vers le haut. + + + + + Part-DB1\templates\AdminPages\_delete_form.html.twig:11 + Part-DB1\templates\AdminPages\_delete_form.html.twig:11 + templates\AdminPages\_delete_form.html.twig:9 + + + entity.delete + Supprimer l'élément + + + + + Part-DB1\templates\AdminPages\_delete_form.html.twig:16 + Part-DB1\templates\Parts\info\_tools.html.twig:45 + Part-DB1\src\Form\Part\PartBaseType.php:286 + Part-DB1\templates\AdminPages\_delete_form.html.twig:16 + Part-DB1\templates\Parts\info\_tools.html.twig:43 + Part-DB1\src\Form\Part\PartBaseType.php:267 + new + + + edit.log_comment + Éditer le commentaire + + + + + Part-DB1\templates\AdminPages\_delete_form.html.twig:24 + Part-DB1\templates\AdminPages\_delete_form.html.twig:24 + templates\AdminPages\_delete_form.html.twig:12 + + + entity.delete.recursive + Suppression récursive (tous les sous éléments) + + + + + Part-DB1\templates\AdminPages\_duplicate.html.twig:3 + + + entity.duplicate + Dupliquer l’élément + + + + + Part-DB1\templates\AdminPages\_export_form.html.twig:4 + Part-DB1\src\Form\AdminPages\ImportType.php:76 + Part-DB1\templates\AdminPages\_export_form.html.twig:4 + Part-DB1\src\Form\AdminPages\ImportType.php:76 + templates\AdminPages\_export_form.html.twig:4 + src\Form\ImportType.php:67 + + + export.format + Format de fichier + + + + + Part-DB1\templates\AdminPages\_export_form.html.twig:16 + Part-DB1\templates\AdminPages\_export_form.html.twig:16 + templates\AdminPages\_export_form.html.twig:16 + + + export.level + Niveau de verbosité + + + + + Part-DB1\templates\AdminPages\_export_form.html.twig:19 + Part-DB1\templates\AdminPages\_export_form.html.twig:19 + templates\AdminPages\_export_form.html.twig:19 + + + export.level.simple + Simple + + + + + Part-DB1\templates\AdminPages\_export_form.html.twig:20 + Part-DB1\templates\AdminPages\_export_form.html.twig:20 + templates\AdminPages\_export_form.html.twig:20 + + + export.level.extended + Étendu + + + + + Part-DB1\templates\AdminPages\_export_form.html.twig:21 + Part-DB1\templates\AdminPages\_export_form.html.twig:21 + templates\AdminPages\_export_form.html.twig:21 + + + export.level.full + Complet + + + + + Part-DB1\templates\AdminPages\_export_form.html.twig:31 + Part-DB1\templates\AdminPages\_export_form.html.twig:31 + templates\AdminPages\_export_form.html.twig:31 + + + export.include_children + Exporter également les sous éléments + + + + + Part-DB1\templates\AdminPages\_export_form.html.twig:39 + Part-DB1\templates\AdminPages\_export_form.html.twig:39 + templates\AdminPages\_export_form.html.twig:39 + + + export.btn + Exporter + + + + + Part-DB1\templates\AdminPages\_info.html.twig:4 + Part-DB1\templates\Parts\edit\edit_part_info.html.twig:12 + Part-DB1\templates\Parts\info\show_part_info.html.twig:24 + Part-DB1\templates\Parts\info\_extended_infos.html.twig:36 + Part-DB1\templates\AdminPages\_info.html.twig:4 + Part-DB1\templates\Parts\edit\edit_part_info.html.twig:12 + Part-DB1\templates\Parts\info\show_part_info.html.twig:24 + Part-DB1\templates\Parts\info\_extended_infos.html.twig:36 + templates\AdminPages\EntityAdminBase.html.twig:94 + templates\Parts\edit_part_info.html.twig:12 + templates\Parts\show_part_info.html.twig:11 + + + id.label + ID + + + + + Part-DB1\templates\AdminPages\_info.html.twig:11 + Part-DB1\templates\Parts\info\_attachments_info.html.twig:76 + Part-DB1\templates\Parts\info\_attachments_info.html.twig:77 + Part-DB1\templates\Parts\info\_extended_infos.html.twig:6 + Part-DB1\templates\Parts\info\_order_infos.html.twig:69 + Part-DB1\templates\Parts\info\_sidebar.html.twig:12 + Part-DB1\templates\Parts\lists\_info_card.html.twig:77 + Part-DB1\templates\AdminPages\_info.html.twig:11 + Part-DB1\templates\Parts\info\_attachments_info.html.twig:59 + Part-DB1\templates\Parts\info\_attachments_info.html.twig:60 + Part-DB1\templates\Parts\info\_extended_infos.html.twig:6 + Part-DB1\templates\Parts\info\_order_infos.html.twig:69 + Part-DB1\templates\Parts\info\_sidebar.html.twig:12 + Part-DB1\templates\Parts\lists\_info_card.html.twig:53 + templates\AdminPages\EntityAdminBase.html.twig:101 + templates\Parts\show_part_info.html.twig:248 + + + createdAt + Créé le + + + + + Part-DB1\templates\AdminPages\_info.html.twig:25 + Part-DB1\templates\Parts\info\_extended_infos.html.twig:21 + Part-DB1\templates\Parts\info\_sidebar.html.twig:8 + Part-DB1\templates\Parts\lists\_info_card.html.twig:73 + Part-DB1\templates\AdminPages\_info.html.twig:25 + Part-DB1\templates\Parts\info\_extended_infos.html.twig:21 + Part-DB1\templates\Parts\info\_sidebar.html.twig:8 + Part-DB1\templates\Parts\lists\_info_card.html.twig:49 + templates\AdminPages\EntityAdminBase.html.twig:114 + templates\Parts\show_part_info.html.twig:263 + + + lastModified + Dernière modification + + + + + Part-DB1\templates\AdminPages\_info.html.twig:38 + Part-DB1\templates\AdminPages\_info.html.twig:38 + + + entity.info.parts_count + Nombre de composants avec cet élément + + + + + Part-DB1\templates\AdminPages\_parameters.html.twig:6 + Part-DB1\templates\helper.twig:125 + Part-DB1\templates\Parts\edit\_specifications.html.twig:6 + + + specifications.property + Paramètre + + + + + Part-DB1\templates\AdminPages\_parameters.html.twig:7 + Part-DB1\templates\Parts\edit\_specifications.html.twig:7 + + + specifications.symbol + Symbole + + + + + Part-DB1\templates\AdminPages\_parameters.html.twig:8 + Part-DB1\templates\Parts\edit\_specifications.html.twig:8 + + + specifications.value_min + Min. + + + + + Part-DB1\templates\AdminPages\_parameters.html.twig:9 + Part-DB1\templates\Parts\edit\_specifications.html.twig:9 + + + specifications.value_typ + Typ. + + + + + Part-DB1\templates\AdminPages\_parameters.html.twig:10 + Part-DB1\templates\Parts\edit\_specifications.html.twig:10 + + + specifications.value_max + Max. + + + + + Part-DB1\templates\AdminPages\_parameters.html.twig:11 + Part-DB1\templates\Parts\edit\_specifications.html.twig:11 + + + specifications.unit + Unité + + + + + Part-DB1\templates\AdminPages\_parameters.html.twig:12 + Part-DB1\templates\Parts\edit\_specifications.html.twig:12 + + + specifications.text + Texte + + + + + Part-DB1\templates\AdminPages\_parameters.html.twig:13 + Part-DB1\templates\Parts\edit\_specifications.html.twig:13 + + + specifications.group + Groupe + + + + + Part-DB1\templates\AdminPages\_parameters.html.twig:26 + Part-DB1\templates\Parts\edit\_specifications.html.twig:26 + + + specification.create + Nouveau paramètre + + + + + Part-DB1\templates\AdminPages\_parameters.html.twig:31 + Part-DB1\templates\Parts\edit\_specifications.html.twig:31 + + + parameter.delete.confirm + Souhaitez-vous vraiment supprimer ce paramètre ? + + + + + Part-DB1\templates\attachment_list.html.twig:3 + Part-DB1\templates\attachment_list.html.twig:3 + + + attachment.list.title + Liste des fichiers joints + + + + + Part-DB1\templates\attachment_list.html.twig:10 + Part-DB1\templates\LogSystem\_log_table.html.twig:8 + Part-DB1\templates\Parts\lists\_parts_list.html.twig:6 + Part-DB1\templates\attachment_list.html.twig:10 + Part-DB1\templates\LogSystem\_log_table.html.twig:8 + Part-DB1\templates\Parts\lists\_parts_list.html.twig:6 + + + part_list.loading.caption + Chargement + + + + + Part-DB1\templates\attachment_list.html.twig:11 + Part-DB1\templates\LogSystem\_log_table.html.twig:9 + Part-DB1\templates\Parts\lists\_parts_list.html.twig:7 + Part-DB1\templates\attachment_list.html.twig:11 + Part-DB1\templates\LogSystem\_log_table.html.twig:9 + Part-DB1\templates\Parts\lists\_parts_list.html.twig:7 + + + part_list.loading.message + Cela peut prendre un moment.Si ce message ne disparaît pas, essayez de recharger la page. + + + + + Part-DB1\templates\base.html.twig:68 + Part-DB1\templates\base.html.twig:68 + templates\base.html.twig:246 + + + vendor.base.javascript_hint + Activez Javascipt pour profiter de toutes les fonctionnalités! + + + + + Part-DB1\templates\base.html.twig:73 + Part-DB1\templates\base.html.twig:73 + + + sidebar.big.toggle + Afficher/Cacher le panneau latéral +Show/Hide sidebar + + + + + Part-DB1\templates\base.html.twig:95 + Part-DB1\templates\base.html.twig:95 + templates\base.html.twig:271 + + + loading.caption + Chargement: + + + + + Part-DB1\templates\base.html.twig:96 + Part-DB1\templates\base.html.twig:96 + templates\base.html.twig:272 + + + loading.message + Cela peut prendre un moment.Si ce message ne disparaît pas, essayez de recharger la page. + + + + + Part-DB1\templates\base.html.twig:101 + Part-DB1\templates\base.html.twig:101 + templates\base.html.twig:277 + + + loading.bar + Chargement... + + + + + Part-DB1\templates\base.html.twig:112 + Part-DB1\templates\base.html.twig:112 + templates\base.html.twig:288 + + + back_to_top + Retour en haut de page + + + + + Part-DB1\templates\Form\permissionLayout.html.twig:35 + Part-DB1\templates\Form\permissionLayout.html.twig:35 + + + permission.edit.permission + Permissions + + + + + Part-DB1\templates\Form\permissionLayout.html.twig:36 + Part-DB1\templates\Form\permissionLayout.html.twig:36 + + + permission.edit.value + Valeur + + + + + Part-DB1\templates\Form\permissionLayout.html.twig:53 + Part-DB1\templates\Form\permissionLayout.html.twig:53 + + + permission.legend.title + Explication des états: + + + + + Part-DB1\templates\Form\permissionLayout.html.twig:57 + Part-DB1\templates\Form\permissionLayout.html.twig:57 + + + permission.legend.disallow + Interdire + + + + + Part-DB1\templates\Form\permissionLayout.html.twig:61 + Part-DB1\templates\Form\permissionLayout.html.twig:61 + + + permission.legend.allow + Autoriser + + + + + Part-DB1\templates\Form\permissionLayout.html.twig:65 + Part-DB1\templates\Form\permissionLayout.html.twig:65 + + + permission.legend.inherit + Hériter du groupe (parent) + + + + + Part-DB1\templates\helper.twig:3 + Part-DB1\templates\helper.twig:3 + + + bool.true + Vrai + + + + + Part-DB1\templates\helper.twig:5 + Part-DB1\templates\helper.twig:5 + + + bool.false + Faux + + + + + Part-DB1\templates\helper.twig:92 + Part-DB1\templates\helper.twig:87 + + + Yes + Oui + + + + + Part-DB1\templates\helper.twig:94 + Part-DB1\templates\helper.twig:89 + + + No + Non + + + + + Part-DB1\templates\helper.twig:126 + + + specifications.value + Valeur + + + + + Part-DB1\templates\homepage.html.twig:7 + Part-DB1\templates\homepage.html.twig:7 + templates\homepage.html.twig:7 + + + version.caption + Version + + + + + Part-DB1\templates\homepage.html.twig:22 + Part-DB1\templates\homepage.html.twig:22 + templates\homepage.html.twig:19 + + + homepage.license + Information de license + + + + + Part-DB1\templates\homepage.html.twig:31 + Part-DB1\templates\homepage.html.twig:31 + templates\homepage.html.twig:28 + + + homepage.github.caption + Page du projet + + + + + Part-DB1\templates\homepage.html.twig:31 + Part-DB1\templates\homepage.html.twig:31 + templates\homepage.html.twig:28 + + + homepage.github.text + Retrouvez les téléchargements, report de bugs, to-do-list etc. sur <a href="%href%" class="link-external" target="_blank">la page du projet GitHub</a> + + + + + Part-DB1\templates\homepage.html.twig:32 + Part-DB1\templates\homepage.html.twig:32 + templates\homepage.html.twig:29 + + + homepage.help.caption + Aide + + + + + Part-DB1\templates\homepage.html.twig:32 + Part-DB1\templates\homepage.html.twig:32 + templates\homepage.html.twig:29 + + + homepage.help.text + De l'aide et des conseils sont disponibles sur le Wiki de la <a href="%href%" class="link-external" target="_blank">page GitHub</a> + + + + + Part-DB1\templates\homepage.html.twig:33 + Part-DB1\templates\homepage.html.twig:33 + templates\homepage.html.twig:30 + + + homepage.forum.caption + Forum + + + + + Part-DB1\templates\homepage.html.twig:45 + Part-DB1\templates\homepage.html.twig:45 + new + + + homepage.last_activity + Activité récente + + + + + Part-DB1\templates\LabelSystem\dialog.html.twig:3 + Part-DB1\templates\LabelSystem\dialog.html.twig:6 + + + label_generator.title + Générateur d'étiquettes + + + + + Part-DB1\templates\LabelSystem\dialog.html.twig:16 + + + label_generator.common + Commun + + + + + Part-DB1\templates\LabelSystem\dialog.html.twig:20 + + + label_generator.advanced + Avancé + + + + + Part-DB1\templates\LabelSystem\dialog.html.twig:24 + + + label_generator.profiles + Profils + + + + + Part-DB1\templates\LabelSystem\dialog.html.twig:58 + + + label_generator.selected_profile + Profil actuellement sélectionné + + + + + Part-DB1\templates\LabelSystem\dialog.html.twig:62 + + + label_generator.edit_profile + Modifier le profil + + + + + Part-DB1\templates\LabelSystem\dialog.html.twig:75 + + + label_generator.load_profile + Charger le profil + + + + + Part-DB1\templates\LabelSystem\dialog.html.twig:102 + + + label_generator.download + Télécharger + + + + + Part-DB1\templates\LabelSystem\dropdown_macro.html.twig:3 + Part-DB1\templates\LabelSystem\dropdown_macro.html.twig:5 + + + label_generator.label_btn + Générer une étiquette + + + + + Part-DB1\templates\LabelSystem\dropdown_macro.html.twig:20 + + + label_generator.label_empty + Nouvelle étiquette vide + + + + + Part-DB1\templates\LabelSystem\Scanner\dialog.html.twig:3 + + + label_scanner.title + Lecteur d'étiquettes + + + + + Part-DB1\templates\LabelSystem\Scanner\dialog.html.twig:7 + + + label_scanner.no_cam_found.title + Aucune webcam trouvée + + + + + Part-DB1\templates\LabelSystem\Scanner\dialog.html.twig:7 + + + label_scanner.no_cam_found.text + Vous devez disposer d'une webcam et donner l'autorisation d'utiliser la fonction de scanner. Vous pouvez entrer le code à barres manuellement ci-dessous. + + + + + Part-DB1\templates\LabelSystem\Scanner\dialog.html.twig:27 + + + label_scanner.source_select + Sélectionnez une source + + + + + Part-DB1\templates\LogSystem\log_list.html.twig:3 + Part-DB1\templates\LogSystem\log_list.html.twig:3 + + + log.list.title + Journal système + + + + + Part-DB1\templates\LogSystem\_log_table.html.twig:1 + Part-DB1\templates\LogSystem\_log_table.html.twig:1 + new + + + log.undo.confirm_title + Annuler le changement / revenir à une date antérieure ? + + + + + Part-DB1\templates\LogSystem\_log_table.html.twig:2 + Part-DB1\templates\LogSystem\_log_table.html.twig:2 + new + + + log.undo.confirm_message + Voulez-vous annuler la modification donnée / réinitialiser l'élément à une date donnée ? + + + + + Part-DB1\templates\mail\base.html.twig:24 + Part-DB1\templates\mail\base.html.twig:24 + + + mail.footer.email_sent_by + Cet email a été envoyé automatiquement par + + + + + Part-DB1\templates\mail\base.html.twig:24 + Part-DB1\templates\mail\base.html.twig:24 + + + mail.footer.dont_reply + Ne répondez pas à cet email. + + + + + Part-DB1\templates\mail\pw_reset.html.twig:6 + Part-DB1\templates\mail\pw_reset.html.twig:6 + + + email.hi %name% + Bonjour %name% + + + + + Part-DB1\templates\mail\pw_reset.html.twig:7 + Part-DB1\templates\mail\pw_reset.html.twig:7 + + + email.pw_reset.message + Quelqu’un (surement vous) a demandé une réinitialisation de votre mot de passe.Si ce n'est pas le cas, ignorez simplement cet email. + + + + + Part-DB1\templates\mail\pw_reset.html.twig:9 + Part-DB1\templates\mail\pw_reset.html.twig:9 + + + email.pw_reset.button + Cliquez ici pour réinitialiser votre mot de passe + + + + + Part-DB1\templates\mail\pw_reset.html.twig:11 + Part-DB1\templates\mail\pw_reset.html.twig:11 + + + email.pw_reset.fallback + Si cela ne fonctionne pas pour vous, allez à <a href="%url%">%url%</a> et entrez les informations suivantes + + + + + Part-DB1\templates\mail\pw_reset.html.twig:16 + Part-DB1\templates\mail\pw_reset.html.twig:16 + + + email.pw_reset.username + Nom d'utilisateur + + + + + Part-DB1\templates\mail\pw_reset.html.twig:19 + Part-DB1\templates\mail\pw_reset.html.twig:19 + + + email.pw_reset.token + Jeton + + + + + Part-DB1\templates\mail\pw_reset.html.twig:24 + Part-DB1\templates\mail\pw_reset.html.twig:24 + + + email.pw_reset.valid_unit %date% + Le jeton de réinitialisation sera valable jusqu'au <i>%date%</i>. + + + + + Part-DB1\templates\Parts\edit\edit_form_styles.html.twig:18 + Part-DB1\templates\Parts\edit\edit_form_styles.html.twig:58 + Part-DB1\templates\Parts\edit\edit_form_styles.html.twig:78 + Part-DB1\templates\Parts\edit\edit_form_styles.html.twig:58 + + + orderdetail.delete + Supprimer + + + + + Part-DB1\templates\Parts\edit\edit_form_styles.html.twig:39 + Part-DB1\templates\Parts\edit\edit_form_styles.html.twig:39 + + + pricedetails.edit.min_qty + Quantité minimale de commande + + + + + Part-DB1\templates\Parts\edit\edit_form_styles.html.twig:40 + Part-DB1\templates\Parts\edit\edit_form_styles.html.twig:40 + + + pricedetails.edit.price + Prix + + + + + Part-DB1\templates\Parts\edit\edit_form_styles.html.twig:41 + Part-DB1\templates\Parts\edit\edit_form_styles.html.twig:41 + + + pricedetails.edit.price_qty + Pour la quantité + + + + + Part-DB1\templates\Parts\edit\edit_form_styles.html.twig:54 + Part-DB1\templates\Parts\edit\edit_form_styles.html.twig:54 + + + pricedetail.create + Ajouter prix + + + + + Part-DB1\templates\Parts\edit\edit_part_info.html.twig:4 + Part-DB1\templates\Parts\edit\edit_part_info.html.twig:4 + templates\Parts\edit_part_info.html.twig:4 + + + part.edit.title + Éditer le composant + + + + + Part-DB1\templates\Parts\edit\edit_part_info.html.twig:9 + Part-DB1\templates\Parts\edit\edit_part_info.html.twig:9 + templates\Parts\edit_part_info.html.twig:9 + + + part.edit.card_title + Éditer le composant + + + + + Part-DB1\templates\Parts\edit\edit_part_info.html.twig:22 + Part-DB1\templates\Parts\edit\edit_part_info.html.twig:22 + + + part.edit.tab.common + Général + + + + + Part-DB1\templates\Parts\edit\edit_part_info.html.twig:28 + Part-DB1\templates\Parts\edit\edit_part_info.html.twig:28 + + + part.edit.tab.manufacturer + Fabricant + + + + + Part-DB1\templates\Parts\edit\edit_part_info.html.twig:34 + Part-DB1\templates\Parts\edit\edit_part_info.html.twig:34 + + + part.edit.tab.advanced + Avancé + + + + + Part-DB1\templates\Parts\edit\edit_part_info.html.twig:40 + Part-DB1\templates\Parts\edit\edit_part_info.html.twig:40 + + + part.edit.tab.part_lots + Stocks + + + + + Part-DB1\templates\Parts\edit\edit_part_info.html.twig:46 + Part-DB1\templates\Parts\edit\edit_part_info.html.twig:46 + + + part.edit.tab.attachments + Fichiers joints + + + + + Part-DB1\templates\Parts\edit\edit_part_info.html.twig:52 + Part-DB1\templates\Parts\edit\edit_part_info.html.twig:52 + + + part.edit.tab.orderdetails + Informations pour la commande + + + + + Part-DB1\templates\Parts\edit\edit_part_info.html.twig:58 + + + part.edit.tab.specifications + Caractéristiques + + + + + Part-DB1\templates\Parts\edit\edit_part_info.html.twig:64 + Part-DB1\templates\Parts\edit\edit_part_info.html.twig:58 + + + part.edit.tab.comment + Commentaire + + + + + Part-DB1\templates\Parts\edit\new_part.html.twig:8 + Part-DB1\templates\Parts\edit\new_part.html.twig:8 + templates\Parts\new_part.html.twig:8 + + + part.new.card_title + Créer un nouveau composant + + + + + Part-DB1\templates\Parts\edit\_lots.html.twig:5 + Part-DB1\templates\Parts\edit\_lots.html.twig:5 + + + part_lot.delete + Supprimer + + + + + Part-DB1\templates\Parts\edit\_lots.html.twig:28 + Part-DB1\templates\Parts\edit\_lots.html.twig:28 + + + part_lot.create + Créer un inventaire + + + + + Part-DB1\templates\Parts\edit\_orderdetails.html.twig:13 + Part-DB1\templates\Parts\edit\_orderdetails.html.twig:13 + + + orderdetail.create + Ajouter un fournisseur + + + + + Part-DB1\templates\Parts\edit\_orderdetails.html.twig:18 + Part-DB1\templates\Parts\edit\_orderdetails.html.twig:18 + + + pricedetails.edit.delete.confirm + Voulez-vous vraiment supprimer ce prix ? Cela ne peut pas être défait ! + + + + + Part-DB1\templates\Parts\edit\_orderdetails.html.twig:62 + Part-DB1\templates\Parts\edit\_orderdetails.html.twig:61 + + + orderdetails.edit.delete.confirm + Voulez-vous vraiment supprimer ce fournisseur ? Cela ne peut pas être défait ! + + + + + Part-DB1\templates\Parts\info\show_part_info.html.twig:4 + Part-DB1\templates\Parts\info\show_part_info.html.twig:19 + Part-DB1\templates\Parts\info\show_part_info.html.twig:4 + Part-DB1\templates\Parts\info\show_part_info.html.twig:19 + templates\Parts\show_part_info.html.twig:4 + templates\Parts\show_part_info.html.twig:9 + + + part.info.title + Informations détaillées pour + + + + + Part-DB1\templates\Parts\info\show_part_info.html.twig:47 + Part-DB1\templates\Parts\info\show_part_info.html.twig:47 + + + part.part_lots.label + Stocks + + + + + Part-DB1\templates\Parts\info\show_part_info.html.twig:56 + Part-DB1\templates\Parts\lists\_info_card.html.twig:43 + Part-DB1\templates\_navbar_search.html.twig:31 + Part-DB1\templates\_navbar_search.html.twig:26 + templates\base.html.twig:62 + templates\Parts\show_part_info.html.twig:74 + src\Form\PartType.php:86 + + + comment.label + Commentaire + + + + + Part-DB1\templates\Parts\info\show_part_info.html.twig:64 + + + part.info.specifications + Caractéristiques + + + + + Part-DB1\templates\Parts\info\show_part_info.html.twig:74 + Part-DB1\templates\Parts\info\show_part_info.html.twig:64 + templates\Parts\show_part_info.html.twig:82 + + + attachment.labelp + Fichiers joints + + + + + Part-DB1\templates\Parts\info\show_part_info.html.twig:83 + Part-DB1\templates\Parts\info\show_part_info.html.twig:71 + templates\Parts\show_part_info.html.twig:88 + + + vendor.partinfo.shopping_infos + Informations de commande + + + + + Part-DB1\templates\Parts\info\show_part_info.html.twig:91 + Part-DB1\templates\Parts\info\show_part_info.html.twig:78 + templates\Parts\show_part_info.html.twig:94 + + + vendor.partinfo.history + Historique + + + + + Part-DB1\templates\Parts\info\show_part_info.html.twig:97 + Part-DB1\templates\_sidebar.html.twig:54 + Part-DB1\templates\_sidebar.html.twig:13 + Part-DB1\templates\Parts\info\show_part_info.html.twig:84 + Part-DB1\templates\_sidebar.html.twig:54 + Part-DB1\templates\_sidebar.html.twig:13 + templates\base.html.twig:176 + templates\base.html.twig:203 + templates\base.html.twig:217 + templates\base.html.twig:231 + templates\Parts\show_part_info.html.twig:100 + + + tools.label + Outils + + + + + Part-DB1\templates\Parts\info\show_part_info.html.twig:103 + Part-DB1\templates\Parts\info\show_part_info.html.twig:90 + + + extended_info.label + Informations complémentaires + + + + + Part-DB1\templates\Parts\info\_attachments_info.html.twig:7 + Part-DB1\templates\Parts\info\_attachments_info.html.twig:7 + + + attachment.name + Nom + + + + + Part-DB1\templates\Parts\info\_attachments_info.html.twig:8 + Part-DB1\templates\Parts\info\_attachments_info.html.twig:8 + + + attachment.attachment_type + Type de fichier joint + + + + + Part-DB1\templates\Parts\info\_attachments_info.html.twig:9 + Part-DB1\templates\Parts\info\_attachments_info.html.twig:9 + + + attachment.file_name + Nom du fichier + + + + + Part-DB1\templates\Parts\info\_attachments_info.html.twig:10 + Part-DB1\templates\Parts\info\_attachments_info.html.twig:10 + + + attachment.file_size + Taille du fichier + + + + + Part-DB1\templates\Parts\info\_attachments_info.html.twig:54 + + + attachment.preview + Aperçu de l'image + + + + + Part-DB1\templates\Parts\info\_attachments_info.html.twig:67 + Part-DB1\templates\Parts\info\_attachments_info.html.twig:50 + + + attachment.download + Téléchargement + + + + + Part-DB1\templates\Parts\info\_extended_infos.html.twig:11 + Part-DB1\templates\Parts\info\_extended_infos.html.twig:11 + new + + + user.creating_user + Utilisateur qui a créé ce composant + + + + + Part-DB1\templates\Parts\info\_extended_infos.html.twig:13 + Part-DB1\templates\Parts\info\_extended_infos.html.twig:28 + Part-DB1\templates\Parts\info\_extended_infos.html.twig:50 + Part-DB1\templates\Parts\info\_extended_infos.html.twig:13 + Part-DB1\templates\Parts\info\_extended_infos.html.twig:28 + Part-DB1\templates\Parts\info\_extended_infos.html.twig:50 + + + Unknown + Inconnu + + + + + Part-DB1\templates\Parts\info\_extended_infos.html.twig:15 + Part-DB1\templates\Parts\info\_extended_infos.html.twig:30 + Part-DB1\templates\Parts\info\_extended_infos.html.twig:15 + Part-DB1\templates\Parts\info\_extended_infos.html.twig:30 + new + + + accessDenied + Accès refusé + + + + + Part-DB1\templates\Parts\info\_extended_infos.html.twig:26 + Part-DB1\templates\Parts\info\_extended_infos.html.twig:26 + new + + + user.last_editing_user + Utilisateur qui a édité ce composant en dernier + + + + + Part-DB1\templates\Parts\info\_extended_infos.html.twig:41 + Part-DB1\templates\Parts\info\_extended_infos.html.twig:41 + + + part.isFavorite + Favoris + + + + + Part-DB1\templates\Parts\info\_extended_infos.html.twig:46 + Part-DB1\templates\Parts\info\_extended_infos.html.twig:46 + + + part.minOrderAmount + Quantité minimale de commande + + + + + Part-DB1\templates\Parts\info\_main_infos.html.twig:8 + Part-DB1\templates\_navbar_search.html.twig:46 + Part-DB1\src\Services\ElementTypeNameGenerator.php:84 + Part-DB1\templates\Parts\info\_main_infos.html.twig:8 + Part-DB1\templates\_navbar_search.html.twig:41 + Part-DB1\src\Services\ElementTypeNameGenerator.php:84 + templates\base.html.twig:70 + templates\Parts\show_part_info.html.twig:24 + src\Form\PartType.php:80 + + + manufacturer.label + Fabricant + + + + + Part-DB1\templates\Parts\info\_main_infos.html.twig:24 + Part-DB1\templates\_navbar_search.html.twig:11 + templates\base.html.twig:54 + src\Form\PartType.php:62 + + + name.label + Nom + + + + + Part-DB1\templates\Parts\info\_main_infos.html.twig:27 + Part-DB1\templates\Parts\info\_main_infos.html.twig:27 + new + + + part.back_to_info + Retour à la version actuelle + + + + + Part-DB1\templates\Parts\info\_main_infos.html.twig:32 + Part-DB1\templates\_navbar_search.html.twig:19 + Part-DB1\templates\Parts\info\_main_infos.html.twig:32 + Part-DB1\templates\_navbar_search.html.twig:18 + templates\base.html.twig:58 + templates\Parts\show_part_info.html.twig:31 + src\Form\PartType.php:65 + + + description.label + Description + + + + + Part-DB1\templates\Parts\info\_main_infos.html.twig:34 + Part-DB1\templates\_navbar_search.html.twig:15 + Part-DB1\src\Services\ElementTypeNameGenerator.php:80 + Part-DB1\templates\Parts\info\_main_infos.html.twig:34 + Part-DB1\templates\_navbar_search.html.twig:14 + Part-DB1\src\Services\ElementTypeNameGenerator.php:80 + templates\base.html.twig:56 + templates\Parts\show_part_info.html.twig:32 + src\Form\PartType.php:74 + + + category.label + Catégorie + + + + + Part-DB1\templates\Parts\info\_main_infos.html.twig:39 + Part-DB1\templates\Parts\info\_main_infos.html.twig:39 + templates\Parts\show_part_info.html.twig:42 + src\Form\PartType.php:69 + + + instock.label + En stock + + + + + Part-DB1\templates\Parts\info\_main_infos.html.twig:41 + Part-DB1\templates\Parts\info\_main_infos.html.twig:41 + templates\Parts\show_part_info.html.twig:44 + src\Form\PartType.php:72 + + + mininstock.label + Stock minimum + + + + + Part-DB1\templates\Parts\info\_main_infos.html.twig:45 + Part-DB1\templates\_navbar_search.html.twig:52 + Part-DB1\src\Services\ElementTypeNameGenerator.php:83 + Part-DB1\templates\Parts\info\_main_infos.html.twig:45 + Part-DB1\templates\_navbar_search.html.twig:47 + Part-DB1\src\Services\ElementTypeNameGenerator.php:83 + templates\base.html.twig:73 + templates\Parts\show_part_info.html.twig:47 + + + footprint.label + Empreinte + + + + + Part-DB1\templates\Parts\info\_main_infos.html.twig:56 + Part-DB1\templates\Parts\info\_main_infos.html.twig:59 + Part-DB1\templates\Parts\info\_main_infos.html.twig:57 + Part-DB1\templates\Parts\info\_main_infos.html.twig:60 + templates\Parts\show_part_info.html.twig:51 + + + part.avg_price.label + Prix moyen + + + + + Part-DB1\templates\Parts\info\_order_infos.html.twig:5 + Part-DB1\templates\Parts\info\_order_infos.html.twig:5 + + + part.supplier.name + Nom + + + + + Part-DB1\templates\Parts\info\_order_infos.html.twig:6 + Part-DB1\templates\Parts\info\_order_infos.html.twig:6 + + + part.supplier.partnr + Lien/Code cmd. + + + + + Part-DB1\templates\Parts\info\_order_infos.html.twig:28 + Part-DB1\templates\Parts\info\_order_infos.html.twig:28 + + + part.order.minamount + Nombre minimum + + + + + Part-DB1\templates\Parts\info\_order_infos.html.twig:29 + Part-DB1\templates\Parts\info\_order_infos.html.twig:29 + + + part.order.price + Prix + + + + + Part-DB1\templates\Parts\info\_order_infos.html.twig:31 + Part-DB1\templates\Parts\info\_order_infos.html.twig:31 + + + part.order.single_price + Prix unitaire + + + + + Part-DB1\templates\Parts\info\_order_infos.html.twig:71 + Part-DB1\templates\Parts\info\_order_infos.html.twig:71 + + + edit.caption_short + Éditer + + + + + Part-DB1\templates\Parts\info\_order_infos.html.twig:72 + Part-DB1\templates\Parts\info\_order_infos.html.twig:72 + + + delete.caption + Supprimer + + + + + Part-DB1\templates\Parts\info\_part_lots.html.twig:7 + Part-DB1\templates\Parts\info\_part_lots.html.twig:6 + + + part_lots.description + Description + + + + + Part-DB1\templates\Parts\info\_part_lots.html.twig:8 + Part-DB1\templates\Parts\info\_part_lots.html.twig:7 + + + part_lots.storage_location + Emplacement de stockage + + + + + Part-DB1\templates\Parts\info\_part_lots.html.twig:9 + Part-DB1\templates\Parts\info\_part_lots.html.twig:8 + + + part_lots.amount + Quantité + + + + + Part-DB1\templates\Parts\info\_part_lots.html.twig:24 + Part-DB1\templates\Parts\info\_part_lots.html.twig:22 + + + part_lots.location_unknown + Emplacement de stockage inconnu + + + + + Part-DB1\templates\Parts\info\_part_lots.html.twig:31 + Part-DB1\templates\Parts\info\_part_lots.html.twig:29 + + + part_lots.instock_unknown + Quantité inconnue + + + + + Part-DB1\templates\Parts\info\_part_lots.html.twig:40 + Part-DB1\templates\Parts\info\_part_lots.html.twig:38 + + + part_lots.expiration_date + Date d'expiration + + + + + Part-DB1\templates\Parts\info\_part_lots.html.twig:48 + Part-DB1\templates\Parts\info\_part_lots.html.twig:46 + + + part_lots.is_expired + Expiré + + + + + Part-DB1\templates\Parts\info\_part_lots.html.twig:55 + Part-DB1\templates\Parts\info\_part_lots.html.twig:53 + + + part_lots.need_refill + Doit être rempli à nouveau + + + + + Part-DB1\templates\Parts\info\_picture.html.twig:15 + Part-DB1\templates\Parts\info\_picture.html.twig:15 + + + part.info.prev_picture + Image précédente + + + + + Part-DB1\templates\Parts\info\_picture.html.twig:19 + Part-DB1\templates\Parts\info\_picture.html.twig:19 + + + part.info.next_picture + Image suivante + + + + + Part-DB1\templates\Parts\info\_sidebar.html.twig:21 + Part-DB1\templates\Parts\info\_sidebar.html.twig:21 + + + part.mass.tooltip + Poids + + + + + Part-DB1\templates\Parts\info\_sidebar.html.twig:30 + Part-DB1\templates\Parts\info\_sidebar.html.twig:30 + + + part.needs_review.badge + Révision nécessaire + + + + + Part-DB1\templates\Parts\info\_sidebar.html.twig:39 + Part-DB1\templates\Parts\info\_sidebar.html.twig:39 + + + part.favorite.badge + Favoris + + + + + Part-DB1\templates\Parts\info\_sidebar.html.twig:47 + Part-DB1\templates\Parts\info\_sidebar.html.twig:47 + + + part.obsolete.badge + N'est plus disponible + + + + + Part-DB1\templates\Parts\info\_specifications.html.twig:10 + + + parameters.extracted_from_description + Automatiquement extrait de la description + + + + + Part-DB1\templates\Parts\info\_specifications.html.twig:15 + + + parameters.auto_extracted_from_comment + Automatiquement extrait du commentaire + + + + + Part-DB1\templates\Parts\info\_tools.html.twig:6 + Part-DB1\templates\Parts\info\_tools.html.twig:4 + templates\Parts\show_part_info.html.twig:125 + + + part.edit.btn + Éditer + + + + + Part-DB1\templates\Parts\info\_tools.html.twig:16 + Part-DB1\templates\Parts\info\_tools.html.twig:14 + templates\Parts\show_part_info.html.twig:135 + + + part.clone.btn + Duplication + + + + + Part-DB1\templates\Parts\info\_tools.html.twig:24 + Part-DB1\templates\Parts\lists\_action_bar.html.twig:4 + templates\Parts\show_part_info.html.twig:143 + + + part.create.btn + Créer un nouveau composant + + + + + Part-DB1\templates\Parts\info\_tools.html.twig:31 + Part-DB1\templates\Parts\info\_tools.html.twig:29 + + + part.delete.confirm_title + Voulez-vous vraiment supprimer ce composant ? + + + + + Part-DB1\templates\Parts\info\_tools.html.twig:32 + Part-DB1\templates\Parts\info\_tools.html.twig:30 + + + part.delete.message + Le composant et toutes les informations associées (stocks, fichiers joints, etc.) sont supprimés. Cela ne pourra pas être annulé. + + + + + Part-DB1\templates\Parts\info\_tools.html.twig:39 + Part-DB1\templates\Parts\info\_tools.html.twig:37 + + + part.delete + Supprimer le composant + + + + + Part-DB1\templates\Parts\lists\all_list.html.twig:4 + Part-DB1\templates\Parts\lists\all_list.html.twig:4 + + + parts_list.all.title + Tous les composants + + + + + Part-DB1\templates\Parts\lists\category_list.html.twig:4 + Part-DB1\templates\Parts\lists\category_list.html.twig:4 + + + parts_list.category.title + Composants avec catégorie + + + + + Part-DB1\templates\Parts\lists\footprint_list.html.twig:4 + Part-DB1\templates\Parts\lists\footprint_list.html.twig:4 + + + parts_list.footprint.title + Composants avec empreinte + + + + + Part-DB1\templates\Parts\lists\manufacturer_list.html.twig:4 + Part-DB1\templates\Parts\lists\manufacturer_list.html.twig:4 + + + parts_list.manufacturer.title + Composants avec fabricant + + + + + Part-DB1\templates\Parts\lists\search_list.html.twig:4 + Part-DB1\templates\Parts\lists\search_list.html.twig:4 + + + parts_list.search.title + Recherche de composants + + + + + Part-DB1\templates\Parts\lists\store_location_list.html.twig:4 + Part-DB1\templates\Parts\lists\store_location_list.html.twig:4 + + + parts_list.storelocation.title + Composants avec lieu de stockage + + + + + Part-DB1\templates\Parts\lists\supplier_list.html.twig:4 + Part-DB1\templates\Parts\lists\supplier_list.html.twig:4 + + + parts_list.supplier.title + Composants avec fournisseur + + + + + Part-DB1\templates\Parts\lists\tags_list.html.twig:4 + Part-DB1\templates\Parts\lists\tags_list.html.twig:4 + + + parts_list.tags.title + Composants avec tag + + + + + Part-DB1\templates\Parts\lists\_info_card.html.twig:22 + Part-DB1\templates\Parts\lists\_info_card.html.twig:17 + + + entity.info.common.tab + Général + + + + + Part-DB1\templates\Parts\lists\_info_card.html.twig:26 + Part-DB1\templates\Parts\lists\_info_card.html.twig:20 + + + entity.info.statistics.tab + Statistiques + + + + + Part-DB1\templates\Parts\lists\_info_card.html.twig:31 + + + entity.info.attachments.tab + Pièces jointes + + + + + Part-DB1\templates\Parts\lists\_info_card.html.twig:37 + + + entity.info.parameters.tab + Caractéristiques + + + + + Part-DB1\templates\Parts\lists\_info_card.html.twig:54 + Part-DB1\templates\Parts\lists\_info_card.html.twig:30 + + + entity.info.name + Nom + + + + + Part-DB1\templates\Parts\lists\_info_card.html.twig:58 + Part-DB1\templates\Parts\lists\_info_card.html.twig:96 + Part-DB1\templates\Parts\lists\_info_card.html.twig:34 + Part-DB1\templates\Parts\lists\_info_card.html.twig:67 + + + entity.info.parent + Parent + + + + + Part-DB1\templates\Parts\lists\_info_card.html.twig:70 + Part-DB1\templates\Parts\lists\_info_card.html.twig:46 + + + entity.edit.btn + Éditer + + + + + Part-DB1\templates\Parts\lists\_info_card.html.twig:92 + Part-DB1\templates\Parts\lists\_info_card.html.twig:63 + + + entity.info.children_count + Nombre de sous-éléments + + + + + Part-DB1\templates\security\2fa_base_form.html.twig:3 + Part-DB1\templates\security\2fa_base_form.html.twig:5 + Part-DB1\templates\security\2fa_base_form.html.twig:3 + Part-DB1\templates\security\2fa_base_form.html.twig:5 + + + tfa.check.title + Authentification à deux facteurs requise + + + + + Part-DB1\templates\security\2fa_base_form.html.twig:39 + Part-DB1\templates\security\2fa_base_form.html.twig:39 + + + tfa.code.trusted_pc + Il s'agit d'un ordinateur de confiance (si cette fonction est activée, aucune autre requête à deux facteurs n'est effectuée sur cet ordinateur) + + + + + Part-DB1\templates\security\2fa_base_form.html.twig:52 + Part-DB1\templates\security\login.html.twig:58 + Part-DB1\templates\security\2fa_base_form.html.twig:52 + Part-DB1\templates\security\login.html.twig:58 + + + login.btn + Connexion + + + + + Part-DB1\templates\security\2fa_base_form.html.twig:53 + Part-DB1\templates\security\U2F\u2f_login.html.twig:13 + Part-DB1\templates\_navbar.html.twig:42 + Part-DB1\templates\security\2fa_base_form.html.twig:53 + Part-DB1\templates\security\U2F\u2f_login.html.twig:13 + Part-DB1\templates\_navbar.html.twig:40 + + + user.logout + Déconnexion + + + + + Part-DB1\templates\security\2fa_form.html.twig:6 + Part-DB1\templates\security\2fa_form.html.twig:6 + + + tfa.check.code.label + Code d'application de l'authentificateur + + + + + Part-DB1\templates\security\2fa_form.html.twig:10 + Part-DB1\templates\security\2fa_form.html.twig:10 + + + tfa.check.code.help + Entrez le code à 6 chiffres de votre application d'authentification ou l'un de vos codes de secours si l'authentificateur n'est pas disponible. + + + + + Part-DB1\templates\security\login.html.twig:3 + Part-DB1\templates\security\login.html.twig:3 + templates\security\login.html.twig:3 + + + login.title + Connexion + + + + + Part-DB1\templates\security\login.html.twig:7 + Part-DB1\templates\security\login.html.twig:7 + templates\security\login.html.twig:7 + + + login.card_title + Connexion + + + + + Part-DB1\templates\security\login.html.twig:31 + Part-DB1\templates\security\login.html.twig:31 + templates\security\login.html.twig:31 + + + login.username.label + Nom d'utilisateur + + + + + Part-DB1\templates\security\login.html.twig:34 + Part-DB1\templates\security\login.html.twig:34 + templates\security\login.html.twig:34 + + + login.username.placeholder + Nom d'utilisateur + + + + + Part-DB1\templates\security\login.html.twig:38 + Part-DB1\templates\security\login.html.twig:38 + templates\security\login.html.twig:38 + + + login.password.label + Mot de passe + + + + + Part-DB1\templates\security\login.html.twig:40 + Part-DB1\templates\security\login.html.twig:40 + templates\security\login.html.twig:40 + + + login.password.placeholder + Mot de passe + + + + + Part-DB1\templates\security\login.html.twig:50 + Part-DB1\templates\security\login.html.twig:50 + templates\security\login.html.twig:50 + + + login.rememberme + Rester connecté (non recommandé sur les ordinateurs publics) + + + + + Part-DB1\templates\security\login.html.twig:64 + Part-DB1\templates\security\login.html.twig:64 + + + pw_reset.password_forget + Nom d'utilisateur/mot de passe oublié ? + + + + + Part-DB1\templates\security\pw_reset_new_pw.html.twig:5 + Part-DB1\templates\security\pw_reset_new_pw.html.twig:5 + + + pw_reset.new_pw.header.title + Définir un nouveau mot de passe + + + + + Part-DB1\templates\security\pw_reset_request.html.twig:5 + Part-DB1\templates\security\pw_reset_request.html.twig:5 + + + pw_reset.request.header.title + Demander un nouveau mot de passe + + + + + Part-DB1\templates\security\U2F\u2f_login.html.twig:7 + Part-DB1\templates\security\U2F\u2f_register.html.twig:10 + Part-DB1\templates\security\U2F\u2f_login.html.twig:7 + Part-DB1\templates\security\U2F\u2f_register.html.twig:10 + + + tfa_u2f.http_warning + Vous accédez à cette page en utilisant la méthode HTTP non sécurisée, donc U2F ne fonctionnera probablement pas (message d'erreur "Bad Request"). Demandez à un administrateur de mettre en place la méthode HTTPS sécurisée si vous souhaitez utiliser des clés de sécurité. + + + + + Part-DB1\templates\security\U2F\u2f_login.html.twig:10 + Part-DB1\templates\security\U2F\u2f_register.html.twig:22 + Part-DB1\templates\security\U2F\u2f_login.html.twig:10 + Part-DB1\templates\security\U2F\u2f_register.html.twig:22 + + + r_u2f_two_factor.pressbutton + Veuillez insérer la clé de sécurité et appuyer sur le bouton ! + + + + + Part-DB1\templates\security\U2F\u2f_register.html.twig:3 + Part-DB1\templates\security\U2F\u2f_register.html.twig:3 + + + tfa_u2f.add_key.title + Ajouter une clé de sécurité + + + + + Part-DB1\templates\security\U2F\u2f_register.html.twig:6 + Part-DB1\templates\Users\_2fa_settings.html.twig:111 + Part-DB1\templates\security\U2F\u2f_register.html.twig:6 + Part-DB1\templates\Users\_2fa_settings.html.twig:111 + + + tfa_u2f.explanation + À l'aide d'une clé de sécurité compatible U2F/FIDO (par exemple YubiKey ou NitroKey), une authentification à deux facteurs sûre et pratique peut être obtenue. Les clés de sécurité peuvent être enregistrées ici, et si une vérification à deux facteurs est nécessaire, il suffit d'insérer la clé via USB ou de la taper sur le dispositif via NFC. + + + + + Part-DB1\templates\security\U2F\u2f_register.html.twig:7 + Part-DB1\templates\security\U2F\u2f_register.html.twig:7 + + + tfa_u2f.add_key.backup_hint + Pour garantir l'accès même en cas de perte de la clé, il est recommandé d'enregistrer une deuxième clé en guise de sauvegarde et de la conserver dans un endroit sûr ! + + + + + Part-DB1\templates\security\U2F\u2f_register.html.twig:16 + Part-DB1\templates\security\U2F\u2f_register.html.twig:16 + + + r_u2f_two_factor.name + Afficher le nom de la clé (par exemple, sauvegarde) + + + + + Part-DB1\templates\security\U2F\u2f_register.html.twig:19 + Part-DB1\templates\security\U2F\u2f_register.html.twig:19 + + + tfa_u2f.add_key.add_button + Ajouter une clé de sécurité + + + + + Part-DB1\templates\security\U2F\u2f_register.html.twig:27 + Part-DB1\templates\security\U2F\u2f_register.html.twig:27 + + + tfa_u2f.add_key.back_to_settings + Retour aux paramètres + + + + + Part-DB1\templates\Statistics\statistics.html.twig:5 + Part-DB1\templates\Statistics\statistics.html.twig:8 + Part-DB1\templates\Statistics\statistics.html.twig:5 + Part-DB1\templates\Statistics\statistics.html.twig:8 + new + + + statistics.title + Statistiques + + + + + Part-DB1\templates\Statistics\statistics.html.twig:14 + Part-DB1\templates\Statistics\statistics.html.twig:14 + new + + + statistics.parts + Composants + + + + + Part-DB1\templates\Statistics\statistics.html.twig:19 + Part-DB1\templates\Statistics\statistics.html.twig:19 + new + + + statistics.data_structures + Structures des données + + + + + Part-DB1\templates\Statistics\statistics.html.twig:24 + Part-DB1\templates\Statistics\statistics.html.twig:24 + new + + + statistics.attachments + Fichiers joints + + + + + Part-DB1\templates\Statistics\statistics.html.twig:34 + Part-DB1\templates\Statistics\statistics.html.twig:59 + Part-DB1\templates\Statistics\statistics.html.twig:104 + Part-DB1\templates\Statistics\statistics.html.twig:34 + Part-DB1\templates\Statistics\statistics.html.twig:59 + Part-DB1\templates\Statistics\statistics.html.twig:104 + new + + + statistics.property + Propriété + + + + + Part-DB1\templates\Statistics\statistics.html.twig:35 + Part-DB1\templates\Statistics\statistics.html.twig:60 + Part-DB1\templates\Statistics\statistics.html.twig:105 + Part-DB1\templates\Statistics\statistics.html.twig:35 + Part-DB1\templates\Statistics\statistics.html.twig:60 + Part-DB1\templates\Statistics\statistics.html.twig:105 + new + + + statistics.value + Valeur + + + + + Part-DB1\templates\Statistics\statistics.html.twig:40 + Part-DB1\templates\Statistics\statistics.html.twig:40 + new + + + statistics.distinct_parts_count + Nombre de composants distincts + + + + + Part-DB1\templates\Statistics\statistics.html.twig:44 + Part-DB1\templates\Statistics\statistics.html.twig:44 + new + + + statistics.parts_instock_sum + Somme de tout les composants en stock + + + + + Part-DB1\templates\Statistics\statistics.html.twig:48 + Part-DB1\templates\Statistics\statistics.html.twig:48 + new + + + statistics.parts_with_price + Nombre de composants avec information de prix + + + + + Part-DB1\templates\Statistics\statistics.html.twig:65 + Part-DB1\templates\Statistics\statistics.html.twig:65 + new + + + statistics.categories_count + Nombre de catégories + + + + + Part-DB1\templates\Statistics\statistics.html.twig:69 + Part-DB1\templates\Statistics\statistics.html.twig:69 + new + + + statistics.footprints_count + Nombre d'empreintes + + + + + Part-DB1\templates\Statistics\statistics.html.twig:73 + Part-DB1\templates\Statistics\statistics.html.twig:73 + new + + + statistics.manufacturers_count + Nombre de fabricants + + + + + Part-DB1\templates\Statistics\statistics.html.twig:77 + Part-DB1\templates\Statistics\statistics.html.twig:77 + new + + + statistics.storelocations_count + Nombre d'emplacements de stockage + + + + + Part-DB1\templates\Statistics\statistics.html.twig:81 + Part-DB1\templates\Statistics\statistics.html.twig:81 + new + + + statistics.suppliers_count + Nombre de fournisseurs + + + + + Part-DB1\templates\Statistics\statistics.html.twig:85 + Part-DB1\templates\Statistics\statistics.html.twig:85 + new + + + statistics.currencies_count + Nombre de devises + + + + + Part-DB1\templates\Statistics\statistics.html.twig:89 + Part-DB1\templates\Statistics\statistics.html.twig:89 + new + + + statistics.measurement_units_count + Nombre d'unités de mesure + + + + + Part-DB1\templates\Statistics\statistics.html.twig:93 + Part-DB1\templates\Statistics\statistics.html.twig:93 + new + + + statistics.devices_count + Nombre de projets + + + + + Part-DB1\templates\Statistics\statistics.html.twig:110 + Part-DB1\templates\Statistics\statistics.html.twig:110 + new + + + statistics.attachment_types_count + Nombre de types de fichiers joints + + + + + Part-DB1\templates\Statistics\statistics.html.twig:114 + Part-DB1\templates\Statistics\statistics.html.twig:114 + new + + + statistics.all_attachments_count + Total des pièces jointes + + + + + Part-DB1\templates\Statistics\statistics.html.twig:118 + Part-DB1\templates\Statistics\statistics.html.twig:118 + new + + + statistics.user_uploaded_attachments_count + Nombre de fichiers joints envoyées + + + + + Part-DB1\templates\Statistics\statistics.html.twig:122 + Part-DB1\templates\Statistics\statistics.html.twig:122 + new + + + statistics.private_attachments_count + Nombre de fichiers joints privés + + + + + Part-DB1\templates\Statistics\statistics.html.twig:126 + Part-DB1\templates\Statistics\statistics.html.twig:126 + new + + + statistics.external_attachments_count + Nombre de fichiers joints externes + + + + + Part-DB1\templates\Users\backup_codes.html.twig:3 + Part-DB1\templates\Users\backup_codes.html.twig:9 + Part-DB1\templates\Users\backup_codes.html.twig:3 + Part-DB1\templates\Users\backup_codes.html.twig:9 + + + tfa_backup.codes.title + Codes de secours + + + + + Part-DB1\templates\Users\backup_codes.html.twig:12 + Part-DB1\templates\Users\backup_codes.html.twig:12 + + + tfa_backup.codes.explanation + Imprimez ces codes et conservez-les dans un endroit sûr ! + + + + + Part-DB1\templates\Users\backup_codes.html.twig:13 + Part-DB1\templates\Users\backup_codes.html.twig:13 + + + tfa_backup.codes.help + Si vous n'avez plus accès à votre appareil avec l'application d'authentification (smartphone perdu, perte de données, etc.), vous pouvez utiliser un de ces codes pour accéder à votre compte et éventuellement configurer une nouvelle application d'authentification. Chacun de ces codes peut être utilisé une fois, il est recommandé de supprimer les codes utilisés. Toute personne ayant accès à ces codes peut potentiellement accéder à votre compte, alors gardez-les en lieu sûr. + + + + + Part-DB1\templates\Users\backup_codes.html.twig:16 + Part-DB1\templates\Users\backup_codes.html.twig:16 + + + tfa_backup.username + Nom d'utilisateur + + + + + Part-DB1\templates\Users\backup_codes.html.twig:29 + Part-DB1\templates\Users\backup_codes.html.twig:29 + + + tfa_backup.codes.page_generated_on + Page générée le %date% + + + + + Part-DB1\templates\Users\backup_codes.html.twig:32 + Part-DB1\templates\Users\backup_codes.html.twig:32 + + + tfa_backup.codes.print + Imprimer + + + + + Part-DB1\templates\Users\backup_codes.html.twig:35 + Part-DB1\templates\Users\backup_codes.html.twig:35 + + + tfa_backup.codes.copy_clipboard + Copier dans le presse-papier + + + + + Part-DB1\templates\Users\user_info.html.twig:3 + Part-DB1\templates\Users\user_info.html.twig:6 + Part-DB1\templates\_navbar.html.twig:40 + Part-DB1\templates\Users\user_info.html.twig:3 + Part-DB1\templates\Users\user_info.html.twig:6 + Part-DB1\templates\_navbar.html.twig:38 + templates\base.html.twig:99 + templates\Users\user_info.html.twig:3 + templates\Users\user_info.html.twig:6 + + + user.info.label + Informations sur l'utilisateur + + + + + Part-DB1\templates\Users\user_info.html.twig:18 + Part-DB1\src\Form\UserSettingsType.php:77 + Part-DB1\templates\Users\user_info.html.twig:18 + Part-DB1\src\Form\UserSettingsType.php:77 + templates\Users\user_info.html.twig:18 + src\Form\UserSettingsType.php:32 + + + user.firstName.label + Prénom + + + + + Part-DB1\templates\Users\user_info.html.twig:24 + Part-DB1\src\Form\UserSettingsType.php:82 + Part-DB1\templates\Users\user_info.html.twig:24 + Part-DB1\src\Form\UserSettingsType.php:82 + templates\Users\user_info.html.twig:24 + src\Form\UserSettingsType.php:35 + + + user.lastName.label + Nom + + + + + Part-DB1\templates\Users\user_info.html.twig:30 + Part-DB1\src\Form\UserSettingsType.php:92 + Part-DB1\templates\Users\user_info.html.twig:30 + Part-DB1\src\Form\UserSettingsType.php:92 + templates\Users\user_info.html.twig:30 + src\Form\UserSettingsType.php:41 + + + user.email.label + Email + + + + + Part-DB1\templates\Users\user_info.html.twig:37 + Part-DB1\src\Form\UserSettingsType.php:87 + Part-DB1\templates\Users\user_info.html.twig:37 + Part-DB1\src\Form\UserSettingsType.php:87 + templates\Users\user_info.html.twig:37 + src\Form\UserSettingsType.php:38 + + + user.department.label + Département + + + + + Part-DB1\templates\Users\user_info.html.twig:47 + Part-DB1\src\Form\UserSettingsType.php:73 + Part-DB1\templates\Users\user_info.html.twig:47 + Part-DB1\src\Form\UserSettingsType.php:73 + templates\Users\user_info.html.twig:47 + src\Form\UserSettingsType.php:30 + + + user.username.label + Nom d'utilisateur + + + + + Part-DB1\templates\Users\user_info.html.twig:53 + Part-DB1\src\Services\ElementTypeNameGenerator.php:93 + Part-DB1\templates\Users\user_info.html.twig:53 + Part-DB1\src\Services\ElementTypeNameGenerator.php:93 + templates\Users\user_info.html.twig:53 + + + group.label + Groupe + + + + + Part-DB1\templates\Users\user_info.html.twig:67 + Part-DB1\templates\Users\user_info.html.twig:67 + + + user.permissions + Autorisations + + + + + Part-DB1\templates\Users\user_settings.html.twig:3 + Part-DB1\templates\Users\user_settings.html.twig:6 + Part-DB1\templates\_navbar.html.twig:39 + Part-DB1\templates\Users\user_settings.html.twig:3 + Part-DB1\templates\Users\user_settings.html.twig:6 + Part-DB1\templates\_navbar.html.twig:37 + templates\base.html.twig:98 + templates\Users\user_settings.html.twig:3 + templates\Users\user_settings.html.twig:6 + + + user.settings.label + Paramètres utilisateur + + + + + Part-DB1\templates\Users\user_settings.html.twig:18 + Part-DB1\templates\Users\user_settings.html.twig:18 + templates\Users\user_settings.html.twig:14 + + + user_settings.data.label + Données personnelles + + + + + Part-DB1\templates\Users\user_settings.html.twig:22 + Part-DB1\templates\Users\user_settings.html.twig:22 + templates\Users\user_settings.html.twig:18 + + + user_settings.configuration.label + Configuration + + + + + Part-DB1\templates\Users\user_settings.html.twig:55 + Part-DB1\templates\Users\user_settings.html.twig:55 + templates\Users\user_settings.html.twig:48 + + + user.settings.change_pw + Changer de mot de passe + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:6 + Part-DB1\templates\Users\_2fa_settings.html.twig:6 + + + user.settings.2fa_settings + Authentification à deux facteurs + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:13 + Part-DB1\templates\Users\_2fa_settings.html.twig:13 + + + tfa.settings.google.tab + Application d'authentification + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:17 + Part-DB1\templates\Users\_2fa_settings.html.twig:17 + + + tfa.settings.bakup.tab + Codes de secours + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:21 + Part-DB1\templates\Users\_2fa_settings.html.twig:21 + + + tfa.settings.u2f.tab + Clés de sécurité (U2F) + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:25 + Part-DB1\templates\Users\_2fa_settings.html.twig:25 + + + tfa.settings.trustedDevices.tab + Appareils de confiance + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:33 + Part-DB1\templates\Users\_2fa_settings.html.twig:33 + + + tfa_google.disable.confirm_title + Voulez-vous vraiment désactiver l'application d'authentification ? + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:33 + Part-DB1\templates\Users\_2fa_settings.html.twig:33 + + + tfa_google.disable.confirm_message + Si vous désactivez l'application d'authentification, tous les codes de sauvegarde seront supprimés, vous devrez donc peut-être les réimprimer.<br> +Notez également que sans authentification à deux facteurs, votre compte n'est pas aussi bien protégé ! + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:39 + Part-DB1\templates\Users\_2fa_settings.html.twig:39 + + + tfa_google.disabled_message + Application d'authentification désactivée + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:48 + Part-DB1\templates\Users\_2fa_settings.html.twig:48 + + + tfa_google.step.download + Télécharger une application d'authentification (par exemple <a class="link-external" target="_blank" href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2">Authentificateur Google</a> ou <a class="link-external" target="_blank" href="https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp">Authentificateur FreeOTP</a>) + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:49 + Part-DB1\templates\Users\_2fa_settings.html.twig:49 + + + tfa_google.step.scan + Scannez le QR code adjacent avec l'application ou saisissez les données manuellement + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:50 + Part-DB1\templates\Users\_2fa_settings.html.twig:50 + + + tfa_google.step.input_code + Entrez le code généré dans le champ ci-dessous et confirmez + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:51 + Part-DB1\templates\Users\_2fa_settings.html.twig:51 + + + tfa_google.step.download_backup + Imprimez vos codes de secours et conservez-les dans un endroit sûr + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:58 + Part-DB1\templates\Users\_2fa_settings.html.twig:58 + + + tfa_google.manual_setup + Configuration manuelle + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:62 + Part-DB1\templates\Users\_2fa_settings.html.twig:62 + + + tfa_google.manual_setup.type + Type + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:63 + Part-DB1\templates\Users\_2fa_settings.html.twig:63 + + + tfa_google.manual_setup.username + Nom d'utilisateur + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:64 + Part-DB1\templates\Users\_2fa_settings.html.twig:64 + + + tfa_google.manual_setup.secret + Secret + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:65 + Part-DB1\templates\Users\_2fa_settings.html.twig:65 + + + tfa_google.manual_setup.digit_count + Nombre de caractères + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:74 + Part-DB1\templates\Users\_2fa_settings.html.twig:74 + + + tfa_google.enabled_message + Application d'authentification activée + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:83 + Part-DB1\templates\Users\_2fa_settings.html.twig:83 + + + tfa_backup.disabled + Codes de secours désactivés. Configurez l'application d'authentification pour activer les codes de secours. + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:84 + Part-DB1\templates\Users\_2fa_settings.html.twig:92 + Part-DB1\templates\Users\_2fa_settings.html.twig:84 + Part-DB1\templates\Users\_2fa_settings.html.twig:92 + + + tfa_backup.explanation + Grâce à ces codes de secours, vous pouvez accéder à votre compte même si vous perdez l'appareil avec l'application d'authentification. Imprimez les codes et conservez-les dans un endroit sûr. + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:88 + Part-DB1\templates\Users\_2fa_settings.html.twig:88 + + + tfa_backup.reset_codes.confirm_title + Etes vous sûr de vouloir réinitialiser les codes ? + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:88 + Part-DB1\templates\Users\_2fa_settings.html.twig:88 + + + tfa_backup.reset_codes.confirm_message + Cela permettra de supprimer tous les codes précédents et de générer un ensemble de nouveaux codes. Cela ne peut pas être annulé. N'oubliez pas d'imprimer les nouveaux codes et de les conserver dans un endroit sûr ! + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:91 + Part-DB1\templates\Users\_2fa_settings.html.twig:91 + + + tfa_backup.enabled + Codes de secours activés + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:99 + Part-DB1\templates\Users\_2fa_settings.html.twig:99 + + + tfa_backup.show_codes + Afficher les codes de secours + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:114 + Part-DB1\templates\Users\_2fa_settings.html.twig:114 + + + tfa_u2f.table_caption + Clés de sécurité enregistrées + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:115 + Part-DB1\templates\Users\_2fa_settings.html.twig:115 + + + tfa_u2f.delete_u2f.confirm_title + Etes vous sûr de vouloir supprimer cette clé de sécurité ? + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:116 + Part-DB1\templates\Users\_2fa_settings.html.twig:116 + + + tfa_u2f.delete_u2f.confirm_message + Si vous supprimez cette clé, il ne sera plus possible de se connecter avec cette clé. S'il ne reste aucune clé de sécurité, l'authentification à deux facteurs sera désactivée. + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:123 + Part-DB1\templates\Users\_2fa_settings.html.twig:123 + + + tfa_u2f.keys.name + Nom de la clé + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:124 + Part-DB1\templates\Users\_2fa_settings.html.twig:124 + + + tfa_u2f.keys.added_date + Date d'enregistrement + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:134 + Part-DB1\templates\Users\_2fa_settings.html.twig:134 + + + tfa_u2f.key_delete + Supprimer la clé + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:141 + Part-DB1\templates\Users\_2fa_settings.html.twig:141 + + + tfa_u2f.no_keys_registered + Aucune clé de sécurité enregistrée + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:144 + Part-DB1\templates\Users\_2fa_settings.html.twig:144 + + + tfa_u2f.add_new_key + Enregistrer une nouvelle clé de sécurité + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:148 + Part-DB1\templates\Users\_2fa_settings.html.twig:148 + + + tfa_trustedDevices.explanation + Lors de la vérification du deuxième facteur, l'ordinateur actuel peut être marqué comme étant digne de confiance, de sorte qu'il n'est plus nécessaire de procéder à des vérifications à deux facteurs sur cet ordinateur. +Si vous avez fait cela de manière incorrecte ou si un ordinateur n'est plus fiable, vous pouvez réinitialiser le statut de <i>tous</i> les ordinateurs ici. + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:149 + Part-DB1\templates\Users\_2fa_settings.html.twig:149 + + + tfa_trustedDevices.invalidate.confirm_title + Etes vous sûr de vouloir supprimer tous les ordinateurs de confiance ? + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:150 + Part-DB1\templates\Users\_2fa_settings.html.twig:150 + + + tfa_trustedDevices.invalidate.confirm_message + Vous devrez à nouveau procéder à une authentification à deux facteurs sur tous les ordinateurs. Assurez-vous d'avoir votre appareil à deux facteurs à portée de main. + + + + + Part-DB1\templates\Users\_2fa_settings.html.twig:154 + Part-DB1\templates\Users\_2fa_settings.html.twig:154 + + + tfa_trustedDevices.invalidate.btn + Supprimer tous les dispositifs de confiance + + + + + Part-DB1\templates\_navbar.html.twig:4 + Part-DB1\templates\_navbar.html.twig:4 + templates\base.html.twig:29 + + + sidebar.toggle + Activer/désactiver la barre latérale + + + + + Part-DB1\templates\_navbar.html.twig:22 + + + navbar.scanner.link + Scanner + + + + + Part-DB1\templates\_navbar.html.twig:38 + Part-DB1\templates\_navbar.html.twig:36 + templates\base.html.twig:97 + + + user.loggedin.label + Connecté en tant que + + + + + Part-DB1\templates\_navbar.html.twig:44 + Part-DB1\templates\_navbar.html.twig:42 + templates\base.html.twig:103 + + + user.login + Connexion + + + + + Part-DB1\templates\_navbar.html.twig:50 + Part-DB1\templates\_navbar.html.twig:48 + + + ui.toggle_darkmode + Darkmode + + + + + Part-DB1\templates\_navbar.html.twig:54 + Part-DB1\src\Form\UserSettingsType.php:97 + Part-DB1\templates\_navbar.html.twig:52 + Part-DB1\src\Form\UserSettingsType.php:97 + templates\base.html.twig:106 + src\Form\UserSettingsType.php:44 + + + user.language_select + Langue + + + + + Part-DB1\templates\_navbar_search.html.twig:4 + Part-DB1\templates\_navbar_search.html.twig:4 + templates\base.html.twig:49 + + + search.options.label + Options de recherche + + + + + Part-DB1\templates\_navbar_search.html.twig:23 + + + tags.label + Tags + + + + + Part-DB1\templates\_navbar_search.html.twig:27 + Part-DB1\src\Form\LabelOptionsType.php:68 + Part-DB1\src\Services\ElementTypeNameGenerator.php:88 + Part-DB1\src\Services\ElementTypeNameGenerator.php:88 + templates\base.html.twig:60 + templates\Parts\show_part_info.html.twig:36 + src\Form\PartType.php:77 + + + storelocation.label + Emplacement de stockage + + + + + Part-DB1\templates\_navbar_search.html.twig:36 + Part-DB1\templates\_navbar_search.html.twig:31 + templates\base.html.twig:65 + + + ordernumber.label.short + Codecmd. + + + + + Part-DB1\templates\_navbar_search.html.twig:40 + Part-DB1\src\Services\ElementTypeNameGenerator.php:89 + Part-DB1\templates\_navbar_search.html.twig:35 + Part-DB1\src\Services\ElementTypeNameGenerator.php:89 + templates\base.html.twig:67 + + + supplier.label + Fournisseur + + + + + Part-DB1\templates\_navbar_search.html.twig:57 + Part-DB1\templates\_navbar_search.html.twig:52 + templates\base.html.twig:75 + + + search.deactivateBarcode + Désa. Code barres + + + + + Part-DB1\templates\_navbar_search.html.twig:61 + Part-DB1\templates\_navbar_search.html.twig:56 + templates\base.html.twig:77 + + + search.regexmatching + Reg.Ex. Correspondance + + + + + Part-DB1\templates\_navbar_search.html.twig:68 + Part-DB1\templates\_navbar_search.html.twig:62 + + + search.submit + Rechercher! + + + + + Part-DB1\templates\_sidebar.html.twig:2 + Part-DB1\templates\_sidebar.html.twig:2 + templates\base.html.twig:165 + templates\base.html.twig:192 + templates\base.html.twig:220 + + + actions + Actions + + + + + Part-DB1\templates\_sidebar.html.twig:6 + Part-DB1\templates\_sidebar.html.twig:6 + templates\base.html.twig:169 + templates\base.html.twig:196 + templates\base.html.twig:224 + + + datasource + Source de données + + + + + Part-DB1\templates\_sidebar.html.twig:10 + Part-DB1\templates\_sidebar.html.twig:10 + templates\base.html.twig:173 + templates\base.html.twig:200 + templates\base.html.twig:228 + + + manufacturer.labelp + Fabricants + + + + + Part-DB1\templates\_sidebar.html.twig:11 + Part-DB1\templates\_sidebar.html.twig:11 + templates\base.html.twig:174 + templates\base.html.twig:201 + templates\base.html.twig:229 + + + supplier.labelp + Fournisseurs + + + + + Part-DB1\src\Controller\AdminPages\BaseAdminController.php:213 + Part-DB1\src\Controller\AdminPages\BaseAdminController.php:293 + Part-DB1\src\Controller\PartController.php:173 + Part-DB1\src\Controller\PartController.php:293 + Part-DB1\src\Controller\AdminPages\BaseAdminController.php:181 + Part-DB1\src\Controller\AdminPages\BaseAdminController.php:243 + Part-DB1\src\Controller\PartController.php:173 + Part-DB1\src\Controller\PartController.php:268 + + + attachment.download_failed + Le téléchargement du fichier joint a échoué ! + + + + + Part-DB1\src\Controller\AdminPages\BaseAdminController.php:222 + Part-DB1\src\Controller\AdminPages\BaseAdminController.php:190 + + + entity.edit_flash + Changements sauvegardés avec succès. + + + + + Part-DB1\src\Controller\AdminPages\BaseAdminController.php:231 + Part-DB1\src\Controller\AdminPages\BaseAdminController.php:196 + + + entity.edit_flash.invalid + Les changements n'ont pas pu être sauvegardés ! Veuillez vérifier vos données ! + + + + + Part-DB1\src\Controller\AdminPages\BaseAdminController.php:302 + Part-DB1\src\Controller\AdminPages\BaseAdminController.php:252 + + + entity.created_flash + Élément créé avec succès ! + + + + + Part-DB1\src\Controller\AdminPages\BaseAdminController.php:308 + Part-DB1\src\Controller\AdminPages\BaseAdminController.php:258 + + + entity.created_flash.invalid + L'élément n'a pas pu être créé ! Vérifiez vos données ! + + + + + Part-DB1\src\Controller\AdminPages\BaseAdminController.php:399 + Part-DB1\src\Controller\AdminPages\BaseAdminController.php:352 + src\Controller\BaseAdminController.php:154 + + + attachment_type.deleted + Élément supprimé ! + + + + + Part-DB1\src\Controller\AdminPages\BaseAdminController.php:401 + Part-DB1\src\Controller\UserController.php:109 + Part-DB1\src\Controller\UserSettingsController.php:159 + Part-DB1\src\Controller\UserSettingsController.php:193 + Part-DB1\src\Controller\AdminPages\BaseAdminController.php:354 + Part-DB1\src\Controller\UserController.php:101 + Part-DB1\src\Controller\UserSettingsController.php:150 + Part-DB1\src\Controller\UserSettingsController.php:182 + + + csfr_invalid + Le jeton RFTS n'est pas valable ! Rechargez cette page ou contactez un administrateur si le problème persiste ! + + + + + Part-DB1\src\Controller\LabelController.php:125 + + + label_generator.no_entities_found + Aucune entité correspondant à la gamme trouvée. + + + + + Part-DB1\src\Controller\LogController.php:149 + Part-DB1\src\Controller\LogController.php:154 + new + + + log.undo.target_not_found + L'élément ciblé n'a pas pu être trouvé dans la base de données ! + + + + + Part-DB1\src\Controller\LogController.php:156 + Part-DB1\src\Controller\LogController.php:160 + new + + + log.undo.revert_success + Rétablissement réussi. + + + + + Part-DB1\src\Controller\LogController.php:176 + Part-DB1\src\Controller\LogController.php:180 + new + + + log.undo.element_undelete_success + Élément restauré avec succès. + + + + + Part-DB1\src\Controller\LogController.php:178 + Part-DB1\src\Controller\LogController.php:182 + new + + + log.undo.element_element_already_undeleted + L'élément a déjà été restauré ! + + + + + Part-DB1\src\Controller\LogController.php:185 + Part-DB1\src\Controller\LogController.php:189 + new + + + log.undo.element_delete_success + L'élément a été supprimé avec succès. + + + + + Part-DB1\src\Controller\LogController.php:187 + Part-DB1\src\Controller\LogController.php:191 + new + + + log.undo.element.element_already_delted + L'élément a déjà été supprimé ! + + + + + Part-DB1\src\Controller\LogController.php:194 + Part-DB1\src\Controller\LogController.php:198 + new + + + log.undo.element_change_undone + Annulation de la modification de l'élément + + + + + Part-DB1\src\Controller\LogController.php:196 + Part-DB1\src\Controller\LogController.php:200 + new + + + log.undo.do_undelete_before + Vous devez supprimer l'élément avant de pouvoir annuler ce changement ! + + + + + Part-DB1\src\Controller\LogController.php:199 + Part-DB1\src\Controller\LogController.php:203 + new + + + log.undo.log_type_invalid + Cette entrée de journal ne peut pas être annulée ! + + + + + Part-DB1\src\Controller\PartController.php:182 + Part-DB1\src\Controller\PartController.php:182 + src\Controller\PartController.php:80 + + + part.edited_flash + Changements sauvegardés ! + + + + + Part-DB1\src\Controller\PartController.php:186 + Part-DB1\src\Controller\PartController.php:186 + + + part.edited_flash.invalid + Erreur lors de l'enregistrement : Vérifiez vos données ! + + + + + Part-DB1\src\Controller\PartController.php:216 + Part-DB1\src\Controller\PartController.php:219 + + + part.deleted + Composant supprimé avec succès. + + + + + Part-DB1\src\Controller\PartController.php:302 + Part-DB1\src\Controller\PartController.php:277 + Part-DB1\src\Controller\PartController.php:317 + src\Controller\PartController.php:113 + src\Controller\PartController.php:142 + + + part.created_flash + Composants créés avec succès ! + + + + + Part-DB1\src\Controller\PartController.php:308 + Part-DB1\src\Controller\PartController.php:283 + + + part.created_flash.invalid + Erreur lors de la création : Vérifiez vos données ! + + + + + Part-DB1\src\Controller\ScanController.php:68 + Part-DB1\src\Controller\ScanController.php:90 + + + scan.qr_not_found + Aucun élément trouvé pour le code-barres donné. + + + + + Part-DB1\src\Controller\ScanController.php:71 + + + scan.format_unknown + Format inconnu ! + + + + + Part-DB1\src\Controller\ScanController.php:86 + + + scan.qr_success + Élément trouvé. + + + + + Part-DB1\src\Controller\SecurityController.php:114 + Part-DB1\src\Controller\SecurityController.php:109 + + + pw_reset.user_or_email + Nom d'utilisateur / Email + + + + + Part-DB1\src\Controller\SecurityController.php:131 + Part-DB1\src\Controller\SecurityController.php:126 + + + pw_reset.request.success + Demande de mot de passe réussie ! Consultez vos e-mails pour plus d'informations. + + + + + Part-DB1\src\Controller\SecurityController.php:162 + Part-DB1\src\Controller\SecurityController.php:160 + + + pw_reset.username + Nom d'utilisateur + + + + + Part-DB1\src\Controller\SecurityController.php:165 + Part-DB1\src\Controller\SecurityController.php:163 + + + pw_reset.token + Jeton + + + + + Part-DB1\src\Controller\SecurityController.php:194 + Part-DB1\src\Controller\SecurityController.php:192 + + + pw_reset.new_pw.error + Nom d'utilisateur ou jeton invalide ! Veuillez vérifier vos données. + + + + + Part-DB1\src\Controller\SecurityController.php:196 + Part-DB1\src\Controller\SecurityController.php:194 + + + pw_reset.new_pw.success + Le mot de passe a été réinitialisé avec succès. Vous pouvez maintenant vous connecter avec le nouveau mot de passe. + + + + + Part-DB1\src\Controller\UserController.php:107 + Part-DB1\src\Controller\UserController.php:99 + + + user.edit.reset_success + Toutes les méthodes d'authentification à deux facteurs ont été désactivées avec succès. + + + + + Part-DB1\src\Controller\UserSettingsController.php:101 + Part-DB1\src\Controller\UserSettingsController.php:92 + + + tfa_backup.no_codes_enabled + Aucun code de secours n'est activé ! + + + + + Part-DB1\src\Controller\UserSettingsController.php:138 + Part-DB1\src\Controller\UserSettingsController.php:132 + + + tfa_u2f.u2f_delete.not_existing + Il n'y a pas de clé de sécurité avec cet ID ! + + + + + Part-DB1\src\Controller\UserSettingsController.php:145 + Part-DB1\src\Controller\UserSettingsController.php:139 + + + tfa_u2f.u2f_delete.access_denied + Vous ne pouvez pas supprimer les clés de sécurité des autres utilisateurs ! + + + + + Part-DB1\src\Controller\UserSettingsController.php:153 + Part-DB1\src\Controller\UserSettingsController.php:147 + + + tfa.u2f.u2f_delete.success + Clé de sécurité retirée avec succès. + + + + + Part-DB1\src\Controller\UserSettingsController.php:188 + Part-DB1\src\Controller\UserSettingsController.php:180 + + + tfa_trustedDevice.invalidate.success + Les appareils de confiance ont été réinitialisés avec succès. + + + + + Part-DB1\src\Controller\UserSettingsController.php:235 + Part-DB1\src\Controller\UserSettingsController.php:226 + src\Controller\UserController.php:98 + + + user.settings.saved_flash + Paramètres sauvegardés ! + + + + + Part-DB1\src\Controller\UserSettingsController.php:297 + Part-DB1\src\Controller\UserSettingsController.php:288 + src\Controller\UserController.php:130 + + + user.settings.pw_changed_flash + Mot de passe changé ! + + + + + Part-DB1\src\Controller\UserSettingsController.php:317 + Part-DB1\src\Controller\UserSettingsController.php:306 + + + user.settings.2fa.google.activated + L'application d'authentification a été activée avec succès. + + + + + Part-DB1\src\Controller\UserSettingsController.php:328 + Part-DB1\src\Controller\UserSettingsController.php:315 + + + user.settings.2fa.google.disabled + L'application d'authentification a été désactivée avec succès. + + + + + Part-DB1\src\Controller\UserSettingsController.php:346 + Part-DB1\src\Controller\UserSettingsController.php:332 + + + user.settings.2fa.backup_codes.regenerated + De nouveaux codes de secours ont été générés avec succès. + + + + + Part-DB1\src\DataTables\AttachmentDataTable.php:148 + Part-DB1\src\DataTables\AttachmentDataTable.php:148 + + + attachment.table.filename + Nom du fichier + + + + + Part-DB1\src\DataTables\AttachmentDataTable.php:153 + Part-DB1\src\DataTables\AttachmentDataTable.php:153 + + + attachment.table.filesize + Taille du fichier + + + + + Part-DB1\src\DataTables\AttachmentDataTable.php:183 + Part-DB1\src\DataTables\AttachmentDataTable.php:191 + Part-DB1\src\DataTables\AttachmentDataTable.php:200 + Part-DB1\src\DataTables\AttachmentDataTable.php:209 + Part-DB1\src\DataTables\PartsDataTable.php:245 + Part-DB1\src\DataTables\PartsDataTable.php:252 + Part-DB1\src\DataTables\AttachmentDataTable.php:183 + Part-DB1\src\DataTables\AttachmentDataTable.php:191 + Part-DB1\src\DataTables\AttachmentDataTable.php:200 + Part-DB1\src\DataTables\AttachmentDataTable.php:209 + Part-DB1\src\DataTables\PartsDataTable.php:193 + Part-DB1\src\DataTables\PartsDataTable.php:200 + + + true + Vrai + + + + + Part-DB1\src\DataTables\AttachmentDataTable.php:184 + Part-DB1\src\DataTables\AttachmentDataTable.php:192 + Part-DB1\src\DataTables\AttachmentDataTable.php:201 + Part-DB1\src\DataTables\AttachmentDataTable.php:210 + Part-DB1\src\DataTables\PartsDataTable.php:246 + Part-DB1\src\DataTables\PartsDataTable.php:253 + Part-DB1\src\Form\Type\SIUnitType.php:139 + Part-DB1\src\DataTables\AttachmentDataTable.php:184 + Part-DB1\src\DataTables\AttachmentDataTable.php:192 + Part-DB1\src\DataTables\AttachmentDataTable.php:201 + Part-DB1\src\DataTables\AttachmentDataTable.php:210 + Part-DB1\src\DataTables\PartsDataTable.php:194 + Part-DB1\src\DataTables\PartsDataTable.php:201 + Part-DB1\src\Form\Type\SIUnitType.php:139 + + + false + Faux + + + + + Part-DB1\src\DataTables\Column\LogEntryTargetColumn.php:128 + Part-DB1\src\DataTables\Column\LogEntryTargetColumn.php:119 + + + log.target_deleted + Cible supprimée. + + + + + Part-DB1\src\DataTables\Column\RevertLogColumn.php:57 + Part-DB1\src\DataTables\Column\RevertLogColumn.php:60 + new + + + log.undo.undelete + Annuler la suppression + + + + + Part-DB1\src\DataTables\Column\RevertLogColumn.php:63 + Part-DB1\src\DataTables\Column\RevertLogColumn.php:66 + new + + + log.undo.undo + Annuler la modification + + + + + Part-DB1\src\DataTables\Column\RevertLogColumn.php:83 + Part-DB1\src\DataTables\Column\RevertLogColumn.php:86 + new + + + log.undo.revert + Restaurer à cette date + + + + + Part-DB1\src\DataTables\LogDataTable.php:173 + Part-DB1\src\DataTables\LogDataTable.php:161 + + + log.id + ID + + + + + Part-DB1\src\DataTables\LogDataTable.php:178 + Part-DB1\src\DataTables\LogDataTable.php:166 + + + log.timestamp + Horodatage + + + + + Part-DB1\src\DataTables\LogDataTable.php:183 + Part-DB1\src\DataTables\LogDataTable.php:171 + + + log.type + Type + + + + + Part-DB1\src\DataTables\LogDataTable.php:191 + Part-DB1\src\DataTables\LogDataTable.php:179 + + + log.level + Niveau + + + + + Part-DB1\src\DataTables\LogDataTable.php:200 + Part-DB1\src\DataTables\LogDataTable.php:188 + + + log.user + Utilisateur + + + + + Part-DB1\src\DataTables\LogDataTable.php:213 + Part-DB1\src\DataTables\LogDataTable.php:201 + + + log.target_type + Type de cible + + + + + Part-DB1\src\DataTables\LogDataTable.php:226 + Part-DB1\src\DataTables\LogDataTable.php:214 + + + log.target + Cible + + + + + Part-DB1\src\DataTables\LogDataTable.php:231 + Part-DB1\src\DataTables\LogDataTable.php:218 + new + + + log.extra + Extra + + + + + Part-DB1\src\DataTables\PartsDataTable.php:168 + Part-DB1\src\DataTables\PartsDataTable.php:116 + + + part.table.name + Nom + + + + + part.table.name.value.for_part + %value% (Componente) + + + + + part.table.name.value.for_assembly + %value% (Assemblage) + + + + + part.table.name.value.for_project + %value% (Projet) + + + + + Part-DB1\src\DataTables\PartsDataTable.php:178 + Part-DB1\src\DataTables\PartsDataTable.php:126 + + + part.table.id + ID + + + + + Part-DB1\src\DataTables\PartsDataTable.php:182 + Part-DB1\src\DataTables\PartsDataTable.php:130 + + + part.table.description + Description + + + + + Part-DB1\src\DataTables\PartsDataTable.php:185 + Part-DB1\src\DataTables\PartsDataTable.php:133 + + + part.table.category + Catégorie + + + + + Part-DB1\src\DataTables\PartsDataTable.php:190 + Part-DB1\src\DataTables\PartsDataTable.php:138 + + + part.table.footprint + Empreinte + + + + + Part-DB1\src\DataTables\PartsDataTable.php:194 + Part-DB1\src\DataTables\PartsDataTable.php:142 + + + part.table.manufacturer + Fabricant + + + + + Part-DB1\src\DataTables\PartsDataTable.php:197 + Part-DB1\src\DataTables\PartsDataTable.php:145 + + + part.table.storeLocations + Emplacement de stockage + + + + + Part-DB1\src\DataTables\PartsDataTable.php:216 + Part-DB1\src\DataTables\PartsDataTable.php:164 + + + part.table.amount + Quantité + + + + + Part-DB1\src\DataTables\PartsDataTable.php:224 + Part-DB1\src\DataTables\PartsDataTable.php:172 + + + part.table.minamount + Quantité min. + + + + + Part-DB1\src\DataTables\PartsDataTable.php:232 + Part-DB1\src\DataTables\PartsDataTable.php:180 + + + part.table.partUnit + Unité de mesure + + + + + Part-DB1\src\DataTables\PartsDataTable.php:236 + Part-DB1\src\DataTables\PartsDataTable.php:184 + + + part.table.addedDate + Créé le + + + + + Part-DB1\src\DataTables\PartsDataTable.php:240 + Part-DB1\src\DataTables\PartsDataTable.php:188 + + + part.table.lastModified + Dernière modification + + + + + Part-DB1\src\DataTables\PartsDataTable.php:244 + Part-DB1\src\DataTables\PartsDataTable.php:192 + + + part.table.needsReview + Révision nécessaire + + + + + Part-DB1\src\DataTables\PartsDataTable.php:251 + Part-DB1\src\DataTables\PartsDataTable.php:199 + + + part.table.favorite + Favoris + + + + + Part-DB1\src\DataTables\PartsDataTable.php:258 + Part-DB1\src\DataTables\PartsDataTable.php:206 + + + part.table.manufacturingStatus + État + + + + + Part-DB1\src\DataTables\PartsDataTable.php:260 + Part-DB1\src\DataTables\PartsDataTable.php:262 + Part-DB1\src\Form\Part\PartBaseType.php:90 + Part-DB1\src\DataTables\PartsDataTable.php:208 + Part-DB1\src\DataTables\PartsDataTable.php:210 + Part-DB1\src\Form\Part\PartBaseType.php:88 + + + m_status.unknown + Inconnu + + + + + Part-DB1\src\DataTables\PartsDataTable.php:263 + Part-DB1\src\Form\Part\PartBaseType.php:90 + Part-DB1\src\DataTables\PartsDataTable.php:211 + Part-DB1\src\Form\Part\PartBaseType.php:88 + + + m_status.announced + Annoncé + + + + + Part-DB1\src\DataTables\PartsDataTable.php:264 + Part-DB1\src\Form\Part\PartBaseType.php:90 + Part-DB1\src\DataTables\PartsDataTable.php:212 + Part-DB1\src\Form\Part\PartBaseType.php:88 + + + m_status.active + Actif + + + + + Part-DB1\src\DataTables\PartsDataTable.php:265 + Part-DB1\src\Form\Part\PartBaseType.php:90 + Part-DB1\src\DataTables\PartsDataTable.php:213 + Part-DB1\src\Form\Part\PartBaseType.php:88 + + + m_status.nrfnd + Non recommandé pour les nouvelles conceptions + + + + + Part-DB1\src\DataTables\PartsDataTable.php:266 + Part-DB1\src\Form\Part\PartBaseType.php:90 + Part-DB1\src\DataTables\PartsDataTable.php:214 + Part-DB1\src\Form\Part\PartBaseType.php:88 + + + m_status.eol + Fin de vie + + + + + Part-DB1\src\DataTables\PartsDataTable.php:267 + Part-DB1\src\Form\Part\PartBaseType.php:90 + Part-DB1\src\DataTables\PartsDataTable.php:215 + Part-DB1\src\Form\Part\PartBaseType.php:88 + + + m_status.discontinued + Arrêtés + + + + + Part-DB1\src\DataTables\PartsDataTable.php:271 + Part-DB1\src\DataTables\PartsDataTable.php:219 + + + part.table.mpn + MPN + + + + + Part-DB1\src\DataTables\PartsDataTable.php:275 + Part-DB1\src\DataTables\PartsDataTable.php:223 + + + part.table.mass + Poids + + + + + Part-DB1\src\DataTables\PartsDataTable.php:279 + Part-DB1\src\DataTables\PartsDataTable.php:227 + + + part.table.tags + Tags + + + + + Part-DB1\src\DataTables\PartsDataTable.php:283 + Part-DB1\src\DataTables\PartsDataTable.php:231 + + + part.table.attachments + Fichiers joints + + + + + Part-DB1\src\EventSubscriber\UserSystem\LoginSuccessSubscriber.php:82 + Part-DB1\src\EventSubscriber\LoginSuccessListener.php:82 + + + flash.login_successful + Connexion réussie. + + + + + Part-DB1\src\Form\AdminPages\ImportType.php:77 + Part-DB1\src\Form\AdminPages\ImportType.php:77 + src\Form\ImportType.php:68 + + + JSON + JSON + + + + + Part-DB1\src\Form\AdminPages\ImportType.php:77 + Part-DB1\src\Form\AdminPages\ImportType.php:77 + src\Form\ImportType.php:68 + + + XML + XML + + + + + Part-DB1\src\Form\AdminPages\ImportType.php:77 + Part-DB1\src\Form\AdminPages\ImportType.php:77 + src\Form\ImportType.php:68 + + + CSV + CSV + + + + + Part-DB1\src\Form\AdminPages\ImportType.php:77 + Part-DB1\src\Form\AdminPages\ImportType.php:77 + src\Form\ImportType.php:68 + + + YAML + YAML + + + + + Part-DB1\src\Form\AdminPages\ImportType.php:124 + Part-DB1\src\Form\AdminPages\ImportType.php:124 + + + import.abort_on_validation.help + Si cette option est activée, l'ensemble du processus est interrompu si des données non valides sont détectées. Si cette option n'est pas active, les entrées non valides sont ignorées et une tentative est faite pour importer les autres entrées. + + + + + Part-DB1\src\Form\AdminPages\ImportType.php:86 + Part-DB1\src\Form\AdminPages\ImportType.php:86 + src\Form\ImportType.php:70 + + + import.csv_separator + Séparateur CSV + + + + + Part-DB1\src\Form\AdminPages\ImportType.php:93 + Part-DB1\src\Form\AdminPages\ImportType.php:93 + src\Form\ImportType.php:72 + + + parent.label + Élément parent + + + + + Part-DB1\src\Form\AdminPages\ImportType.php:101 + Part-DB1\src\Form\AdminPages\ImportType.php:101 + src\Form\ImportType.php:75 + + + import.file + Fichier + + + + + Part-DB1\src\Form\AdminPages\ImportType.php:111 + Part-DB1\src\Form\AdminPages\ImportType.php:111 + src\Form\ImportType.php:78 + + + import.preserve_children + Importer également des sous-éléments + + + + + Part-DB1\src\Form\AdminPages\ImportType.php:120 + Part-DB1\src\Form\AdminPages\ImportType.php:120 + src\Form\ImportType.php:80 + + + import.abort_on_validation + Interrompre sur donnée invalide + + + + + Part-DB1\src\Form\AdminPages\ImportType.php:132 + Part-DB1\src\Form\AdminPages\ImportType.php:132 + src\Form\ImportType.php:85 + + + import.btn + Importer + + + + + Part-DB1\src\Form\AttachmentFormType.php:113 + Part-DB1\src\Form\AttachmentFormType.php:109 + + + attachment.edit.secure_file.help + Un fichier joint marqué comme étant privé ne peut être consulté que par un utilisateur connecté qui a l'autorisation appropriée. Si cette option est activée, aucune miniature n'est générée et l'accès au fichier est plus lent. + + + + + Part-DB1\src\Form\AttachmentFormType.php:127 + Part-DB1\src\Form\AttachmentFormType.php:123 + + + attachment.edit.url.help + Il est possible de saisir ici soit l'URL d'un fichier externe, soit un mot clé pour rechercher les ressources intégrées (par exemple les empreintes). + + + + + Part-DB1\src\Form\AttachmentFormType.php:82 + Part-DB1\src\Form\AttachmentFormType.php:79 + + + attachment.edit.name + Nom + + + + + Part-DB1\src\Form\AttachmentFormType.php:85 + Part-DB1\src\Form\AttachmentFormType.php:82 + + + attachment.edit.attachment_type + Type de fichier joint + + + + + Part-DB1\src\Form\AttachmentFormType.php:94 + Part-DB1\src\Form\AttachmentFormType.php:91 + + + attachment.edit.show_in_table + Voir dans le tableau + + + + + Part-DB1\src\Form\AttachmentFormType.php:105 + Part-DB1\src\Form\AttachmentFormType.php:102 + + + attachment.edit.secure_file + Fichier joint privé + + + + + Part-DB1\src\Form\AttachmentFormType.php:119 + Part-DB1\src\Form\AttachmentFormType.php:115 + + + attachment.edit.url + URL + + + + + Part-DB1\src\Form\AttachmentFormType.php:133 + Part-DB1\src\Form\AttachmentFormType.php:129 + + + attachment.edit.download_url + Télécharger un fichier externe + + + + + Part-DB1\src\Form\AttachmentFormType.php:146 + Part-DB1\src\Form\AttachmentFormType.php:142 + + + attachment.edit.file + Télécharger le fichier + + + + + Part-DB1\src\Form\LabelOptionsType.php:68 + Part-DB1\src\Services\ElementTypeNameGenerator.php:86 + + + part.label + Composant + + + + + Part-DB1\src\Form\LabelOptionsType.php:68 + Part-DB1\src\Services\ElementTypeNameGenerator.php:87 + + + part_lot.label + Lot de composant + + + + + Part-DB1\src\Form\LabelOptionsType.php:78 + + + label_options.barcode_type.none + Aucun + + + + + Part-DB1\src\Form\LabelOptionsType.php:78 + + + label_options.barcode_type.qr + QR Code (recommandé) + + + + + Part-DB1\src\Form\LabelOptionsType.php:78 + + + label_options.barcode_type.code128 + Code 128 (recommandé) + + + + + Part-DB1\src\Form\LabelOptionsType.php:78 + + + label_options.barcode_type.code39 + Code 39 (recommandé) + + + + + Part-DB1\src\Form\LabelOptionsType.php:78 + + + label_options.barcode_type.code93 + Code 93 + + + + + Part-DB1\src\Form\LabelOptionsType.php:78 + + + label_options.barcode_type.datamatrix + Datamatrix + + + + + Part-DB1\src\Form\LabelOptionsType.php:122 + + + label_options.lines_mode.html + Placeholders + + + + + Part-DB1\src\Form\LabelOptionsType.php:122 + + + label.options.lines_mode.twig + Twig + + + + + Part-DB1\src\Form\LabelOptionsType.php:126 + + + label_options.lines_mode.help + Si vous sélectionnez Twig ici, le champ de contenu est interprété comme un modèle Twig. Voir <a href="https://twig.symfony.com/doc/3.x/templates.html">Documentation de Twig</a> et <a href="https://github.com/Part-DB/Part-DB-symfony/wiki/Labels#twig-mode">Wiki</a> pour plus d'informations. + + + + + Part-DB1\src\Form\LabelOptionsType.php:47 + + + label_options.page_size.label + Taille de l'étiquette + + + + + Part-DB1\src\Form\LabelOptionsType.php:66 + + + label_options.supported_elements.label + Type de cible + + + + + Part-DB1\src\Form\LabelOptionsType.php:75 + + + label_options.barcode_type.label + Code barre + + + + + Part-DB1\src\Form\LabelOptionsType.php:102 + + + label_profile.lines.label + Contenu + + + + + Part-DB1\src\Form\LabelOptionsType.php:111 + + + label_options.additional_css.label + Styles supplémentaires (CSS) + + + + + Part-DB1\src\Form\LabelOptionsType.php:120 + + + label_options.lines_mode.label + Parser mode + + + + + Part-DB1\src\Form\LabelOptionsType.php:51 + + + label_options.width.placeholder + Largeur + + + + + Part-DB1\src\Form\LabelOptionsType.php:60 + + + label_options.height.placeholder + Hauteur + + + + + Part-DB1\src\Form\LabelSystem\LabelDialogType.php:49 + + + label_generator.target_id.range_hint + Vous pouvez spécifier ici plusieurs ID (par exemple 1,2,3) et/ou une plage (1-3) pour générer des étiquettes pour plusieurs éléments à la fois. + + + + + Part-DB1\src\Form\LabelSystem\LabelDialogType.php:46 + + + label_generator.target_id.label + ID des cibles + + + + + Part-DB1\src\Form\LabelSystem\LabelDialogType.php:59 + + + label_generator.update + Actualisation + + + + + Part-DB1\src\Form\LabelSystem\ScanDialogType.php:36 + + + scan_dialog.input + Saisie + + + + + Part-DB1\src\Form\LabelSystem\ScanDialogType.php:44 + + + scan_dialog.submit + Soumettre + + + + + Part-DB1\src\Form\ParameterType.php:41 + + + parameters.name.placeholder + ex. Gain de courant DC + + + + + Part-DB1\src\Form\ParameterType.php:50 + + + parameters.symbol.placeholder + ex. h_{FE} + + + + + Part-DB1\src\Form\ParameterType.php:60 + + + parameters.text.placeholder + ex. Test conditions + + + + + Part-DB1\src\Form\ParameterType.php:71 + + + parameters.max.placeholder + ex. 350 + + + + + Part-DB1\src\Form\ParameterType.php:82 + + + parameters.min.placeholder + ex. 100 + + + + + Part-DB1\src\Form\ParameterType.php:93 + + + parameters.typical.placeholder + ex. 200 + + + + + Part-DB1\src\Form\ParameterType.php:103 + + + parameters.unit.placeholder + ex. V + + + + + Part-DB1\src\Form\ParameterType.php:114 + + + parameter.group.placeholder + ex. Spécifications techniques + + + + + Part-DB1\src\Form\Part\OrderdetailType.php:72 + Part-DB1\src\Form\Part\OrderdetailType.php:75 + + + orderdetails.edit.supplierpartnr + Numéro de commande + + + + + Part-DB1\src\Form\Part\OrderdetailType.php:81 + Part-DB1\src\Form\Part\OrderdetailType.php:84 + + + orderdetails.edit.supplier + Fournisseur + + + + + Part-DB1\src\Form\Part\OrderdetailType.php:87 + Part-DB1\src\Form\Part\OrderdetailType.php:90 + + + orderdetails.edit.url + Lien vers l'offre + + + + + Part-DB1\src\Form\Part\OrderdetailType.php:93 + Part-DB1\src\Form\Part\OrderdetailType.php:96 + + + orderdetails.edit.obsolete + Plus disponible + + + + + Part-DB1\src\Form\Part\OrderdetailType.php:75 + Part-DB1\src\Form\Part\OrderdetailType.php:78 + + + orderdetails.edit.supplierpartnr.placeholder + Ex. BC 547C + + + + + Part-DB1\src\Form\Part\PartBaseType.php:101 + Part-DB1\src\Form\Part\PartBaseType.php:99 + + + part.edit.name + Nom + + + + + Part-DB1\src\Form\Part\PartBaseType.php:109 + Part-DB1\src\Form\Part\PartBaseType.php:107 + + + part.edit.description + Description + + + + + Part-DB1\src\Form\Part\PartBaseType.php:120 + Part-DB1\src\Form\Part\PartBaseType.php:118 + + + part.edit.mininstock + Stock minimum + + + + + Part-DB1\src\Form\Part\PartBaseType.php:129 + Part-DB1\src\Form\Part\PartBaseType.php:127 + + + part.edit.category + Catégories + + + + + Part-DB1\src\Form\Part\PartBaseType.php:135 + Part-DB1\src\Form\Part\PartBaseType.php:133 + + + part.edit.footprint + Empreinte + + + + + Part-DB1\src\Form\Part\PartBaseType.php:142 + Part-DB1\src\Form\Part\PartBaseType.php:140 + + + part.edit.tags + Tags + + + + + Part-DB1\src\Form\Part\PartBaseType.php:154 + Part-DB1\src\Form\Part\PartBaseType.php:152 + + + part.edit.manufacturer.label + Fabricant + + + + + Part-DB1\src\Form\Part\PartBaseType.php:161 + Part-DB1\src\Form\Part\PartBaseType.php:159 + + + part.edit.manufacturer_url.label + Lien vers la page du produit + + + + + Part-DB1\src\Form\Part\PartBaseType.php:167 + Part-DB1\src\Form\Part\PartBaseType.php:165 + + + part.edit.mpn + Numéro de pièce du fabricant + + + + + Part-DB1\src\Form\Part\PartBaseType.php:173 + Part-DB1\src\Form\Part\PartBaseType.php:171 + + + part.edit.manufacturing_status + État de la fabrication + + + + + Part-DB1\src\Form\Part\PartBaseType.php:181 + Part-DB1\src\Form\Part\PartBaseType.php:179 + + + part.edit.needs_review + Révision nécessaire + + + + + Part-DB1\src\Form\Part\PartBaseType.php:189 + Part-DB1\src\Form\Part\PartBaseType.php:187 + + + part.edit.is_favorite + Favoris + + + + + Part-DB1\src\Form\Part\PartBaseType.php:197 + Part-DB1\src\Form\Part\PartBaseType.php:195 + + + part.edit.mass + Poids + + + + + Part-DB1\src\Form\Part\PartBaseType.php:203 + Part-DB1\src\Form\Part\PartBaseType.php:201 + + + part.edit.partUnit + Unité de mesure + + + + + Part-DB1\src\Form\Part\PartBaseType.php:212 + Part-DB1\src\Form\Part\PartBaseType.php:210 + + + part.edit.comment + Commentaire + + + + + Part-DB1\src\Form\Part\PartBaseType.php:250 + Part-DB1\src\Form\Part\PartBaseType.php:246 + + + part.edit.master_attachment + Miniature + + + + + Part-DB1\src\Form\Part\PartBaseType.php:295 + Part-DB1\src\Form\Part\PartBaseType.php:276 + src\Form\PartType.php:91 + + + part.edit.save + Sauvegarder les modifications + + + + + Part-DB1\src\Form\Part\PartBaseType.php:296 + Part-DB1\src\Form\Part\PartBaseType.php:277 + src\Form\PartType.php:92 + + + part.edit.reset + rejeter les modifications + + + + + Part-DB1\src\Form\Part\PartBaseType.php:105 + Part-DB1\src\Form\Part\PartBaseType.php:103 + + + part.edit.name.placeholder + Ex. BC547 + + + + + Part-DB1\src\Form\Part\PartBaseType.php:115 + Part-DB1\src\Form\Part\PartBaseType.php:113 + + + part.edit.description.placeholder + Ex. NPN 45V, 0,1A, 0,5W + + + + + Part-DB1\src\Form\Part\PartBaseType.php:123 + Part-DB1\src\Form\Part\PartBaseType.php:121 + + + part.editmininstock.placeholder + Ex. 1 + + + + + Part-DB1\src\Form\Part\PartLotType.php:69 + Part-DB1\src\Form\Part\PartLotType.php:69 + + + part_lot.edit.description + Description + + + + + Part-DB1\src\Form\Part\PartLotType.php:78 + Part-DB1\src\Form\Part\PartLotType.php:78 + + + part_lot.edit.location + Emplacement de stockage + + + + + Part-DB1\src\Form\Part\PartLotType.php:89 + Part-DB1\src\Form\Part\PartLotType.php:89 + + + part_lot.edit.amount + Quantité + + + + + Part-DB1\src\Form\Part\PartLotType.php:98 + Part-DB1\src\Form\Part\PartLotType.php:97 + + + part_lot.edit.instock_unknown + Quantité inconnue + + + + + Part-DB1\src\Form\Part\PartLotType.php:109 + Part-DB1\src\Form\Part\PartLotType.php:108 + + + part_lot.edit.needs_refill + Doit être rempli + + + + + Part-DB1\src\Form\Part\PartLotType.php:120 + Part-DB1\src\Form\Part\PartLotType.php:119 + + + part_lot.edit.expiration_date + Date d'expiration + + + + + Part-DB1\src\Form\Part\PartLotType.php:128 + Part-DB1\src\Form\Part\PartLotType.php:125 + + + part_lot.edit.comment + Commentaire + + + + + Part-DB1\src\Form\Permissions\PermissionsType.php:99 + Part-DB1\src\Form\Permissions\PermissionsType.php:99 + + + perm.group.other + Divers + + + + + Part-DB1\src\Form\TFAGoogleSettingsType.php:97 + Part-DB1\src\Form\TFAGoogleSettingsType.php:97 + + + tfa_google.enable + Activer l'application d'authentification + + + + + Part-DB1\src\Form\TFAGoogleSettingsType.php:101 + Part-DB1\src\Form\TFAGoogleSettingsType.php:101 + + + tfa_google.disable + Désactiver l'application d'authentification + + + + + Part-DB1\src\Form\TFAGoogleSettingsType.php:74 + Part-DB1\src\Form\TFAGoogleSettingsType.php:74 + + + google_confirmation + Code de confirmation + + + + + Part-DB1\src\Form\UserSettingsType.php:108 + Part-DB1\src\Form\UserSettingsType.php:108 + src\Form\UserSettingsType.php:46 + + + user.timezone.label + Fuseau horaire + + + + + Part-DB1\src\Form\UserSettingsType.php:133 + Part-DB1\src\Form\UserSettingsType.php:132 + + + user.currency.label + Devise préférée + + + + + Part-DB1\src\Form\UserSettingsType.php:140 + Part-DB1\src\Form\UserSettingsType.php:139 + src\Form\UserSettingsType.php:53 + + + save + Appliquer les modifications + + + + + Part-DB1\src\Form\UserSettingsType.php:141 + Part-DB1\src\Form\UserSettingsType.php:140 + src\Form\UserSettingsType.php:54 + + + reset + Rejeter les modifications + + + + + Part-DB1\src\Form\UserSettingsType.php:104 + Part-DB1\src\Form\UserSettingsType.php:104 + src\Form\UserSettingsType.php:45 + + + user_settings.language.placeholder + Langue du serveur + + + + + Part-DB1\src\Form\UserSettingsType.php:115 + Part-DB1\src\Form\UserSettingsType.php:115 + src\Form\UserSettingsType.php:48 + + + user_settings.timezone.placeholder + Fuseau horaire du serveur + + + + + Part-DB1\src\Services\ElementTypeNameGenerator.php:79 + Part-DB1\src\Services\ElementTypeNameGenerator.php:79 + + + attachment.label + Fichier joint + + + + + Part-DB1\src\Services\ElementTypeNameGenerator.php:81 + Part-DB1\src\Services\ElementTypeNameGenerator.php:81 + + + attachment_type.label + Type de fichier joint + + + + + Part-DB1\src\Services\ElementTypeNameGenerator.php:85 + Part-DB1\src\Services\ElementTypeNameGenerator.php:85 + + + measurement_unit.label + Unité de mesure + + + + + Part-DB1\src\Services\ElementTypeNameGenerator.php:90 + Part-DB1\src\Services\ElementTypeNameGenerator.php:90 + + + currency.label + Devise + + + + + Part-DB1\src\Services\ElementTypeNameGenerator.php:91 + Part-DB1\src\Services\ElementTypeNameGenerator.php:91 + + + orderdetail.label + Informations de commande + + + + + Part-DB1\src\Services\ElementTypeNameGenerator.php:92 + Part-DB1\src\Services\ElementTypeNameGenerator.php:92 + + + pricedetail.label + Informations sur les prix + + + + + Part-DB1\src\Services\ElementTypeNameGenerator.php:94 + Part-DB1\src\Services\ElementTypeNameGenerator.php:94 + + + user.label + Utilisateur + + + + + Part-DB1\src\Services\ElementTypeNameGenerator.php:95 + + + parameter.label + Caractéristique + + + + + Part-DB1\src\Services\ElementTypeNameGenerator.php:96 + + + label_profile.label + Profil d'étiquette + + + + + Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:176 + Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:161 + new + + + log.element_deleted.old_name.unknown + Inconnu + + + + + Part-DB1\src\Services\MarkdownParser.php:73 + Part-DB1\src\Services\MarkdownParser.php:73 + + + markdown.loading + Chargement de la remise. Si ce message ne disparaît pas, essayez de recharger la page. + + + + + Part-DB1\src\Services\PasswordResetManager.php:98 + Part-DB1\src\Services\PasswordResetManager.php:98 + + + pw_reset.email.subject + Réinitialisation du mot de passe de votre compte Part-DB + + + + + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:108 + + + tree.tools.tools + Outils + + + + + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:109 + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:107 + src\Services\ToolsTreeBuilder.php:74 + + + tree.tools.edit + Éditer + + + + + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:110 + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:108 + src\Services\ToolsTreeBuilder.php:81 + + + tree.tools.show + Afficher + + + + + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:111 + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:109 + + + tree.tools.system + Système + + + + + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:123 + + + tree.tools.tools.label_dialog + Générateur d'étiquettes + + + + + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:130 + + + tree.tools.tools.label_scanner + Scanner + + + + + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:149 + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:126 + src\Services\ToolsTreeBuilder.php:62 + + + tree.tools.edit.attachment_types + Types de fichier joint + + + + + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:155 + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:132 + src\Services\ToolsTreeBuilder.php:64 + + + tree.tools.edit.categories + Catégories + + + + + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:167 + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:144 + src\Services\ToolsTreeBuilder.php:68 + + + tree.tools.edit.suppliers + Fournisseurs + + + + + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:173 + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:150 + src\Services\ToolsTreeBuilder.php:70 + + + tree.tools.edit.manufacturer + Fabricants + + + + + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:179 + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:156 + + + tree.tools.edit.storelocation + Emplacements de stockage + + + + + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:185 + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:162 + + + tree.tools.edit.footprint + Empreintes + + + + + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:191 + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:168 + + + tree.tools.edit.currency + Devises + + + + + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:197 + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:174 + + + tree.tools.edit.measurement_unit + Unité de mesure + + + + + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:203 + + + tree.tools.edit.label_profile + Profils d'étiquettes + + + + + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:209 + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:180 + + + tree.tools.edit.part + Composant + + + + + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:226 + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:197 + src\Services\ToolsTreeBuilder.php:77 + + + tree.tools.show.all_parts + Voir tous les composants + + + + + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:232 + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:203 + + + tree.tools.show.all_attachments + Fichiers joints + + + + + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:239 + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:210 + new + + + tree.tools.show.statistics + Statistiques + + + + + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:258 + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:229 + + + tree.tools.system.users + Utilisateurs + + + + + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:264 + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:235 + + + tree.tools.system.groups + Groupes + + + + + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:271 + Part-DB1\src\Services\Trees\ToolsTreeBuilder.php:242 + new + + + tree.tools.system.event_log + Système d'événements + + + + + Part-DB1\src\Services\Trees\TreeViewGenerator.php:95 + Part-DB1\src\Services\Trees\TreeViewGenerator.php:95 + src\Services\TreeBuilder.php:124 + + + entity.tree.new + Nouvel élément + + + + + Part-DB1\templates\Parts\info\_attachments_info.html.twig:34 + obsolete + + + attachment.external_file + Fichier extérieur + + + + + Part-DB1\templates\Parts\info\_attachments_info.html.twig:62 + obsolete + + + attachment.edit + Éditer + + + + + Part-DB1\templates\_navbar.html.twig:27 + templates\base.html.twig:88 + obsolete + + + barcode.scan + Scanner un code-barres + + + + + Part-DB1\src\Form\UserSettingsType.php:119 + src\Form\UserSettingsType.php:49 + obsolete + + + user.theme.label + Thème + + + + + Part-DB1\src\Form\UserSettingsType.php:129 + src\Form\UserSettingsType.php:50 + obsolete + + + user_settings.theme.placeholder + Thème du serveur + + + + + Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:100 + new + obsolete + + + log.user_login.ip + IP + + + + + Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:128 + Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:150 + Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:169 + Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:207 + new + obsolete + + + log.undo_mode.undo + Modification annulée + + + + + Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:130 + Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:152 + Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:171 + Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:209 + new + obsolete + + + log.undo_mode.revert + Élément restauré + + + + + Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:139 + new + obsolete + + + log.element_created.original_instock + Ancien stock + + + + + Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:160 + new + obsolete + + + log.element_deleted.old_name + Ancien nom + + + + + Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:184 + new + obsolete + + + log.element_edited.changed_fields + Champs modifiés + + + + + Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:198 + new + obsolete + + + log.instock_changed.comment + Commentaire + + + + + Part-DB1\src\Services\LogSystem\LogEntryExtraFormatter.php:214 + new + obsolete + + + log.collection_deleted.deleted + Élément supprimé : + + + + + templates\base.html.twig:81 + obsolete + obsolete + + + go.exclamation + Allez! + + + + + templates\base.html.twig:109 + obsolete + obsolete + + + language.english + Anglais + + + + + templates\base.html.twig:112 + obsolete + obsolete + + + language.german + Allemand + + + + + obsolete + obsolete + + + flash.password_change_needed + Votre mot de passe doit être changé ! + + + + + obsolete + obsolete + + + attachment.table.type + Type de fichier joint + + + + + obsolete + obsolete + + + attachment.table.element + élément lié + + + + + obsolete + obsolete + + + attachment.edit.isPicture + Image? + + + + + obsolete + obsolete + + + attachment.edit.is3DModel + Modèle 3D? + + + + + obsolete + obsolete + + + attachment.edit.isBuiltin + Intégré? + + + + + obsolete + obsolete + + + category.edit.default_comment.placeholder + Ex. utilisé pour les alimentations à découpage + + + + + obsolete + obsolete + + + tfa_backup.regenerate_codes + Créer de nouveaux codes de secours + + + + + obsolete + obsolete + + + validator.noneofitschild.self + Un élément ne peut pas être son propre parent. + + + + + obsolete + obsolete + + + validator.noneofitschild.children + Le parent ne peut pas être un de ses propres enfants. + + + + + obsolete + obsolete + + + validator.part_lot.location_full.no_increasment + Le lieu de stockage utilisé a été marqué comme étant plein, le stock ne peut donc pas être augmenté. (Nouveau stock maximum {{old_amount}}) + + + + + obsolete + obsolete + + + validator.part_lot.location_full + L'emplacement de stockage est plein, c'est pourquoi aucun nouveau composant ne peut être ajouté. + + + + + obsolete + obsolete + + + validator.part_lot.only_existing + L'emplacement de stockage a été marqué comme "uniquement existant", donc aucun nouveau composant ne peut être ajouté. + + + + + obsolete + obsolete + + + validator.part_lot.single_part + L'emplacement de stockage a été marqué comme "Composant seul", par conséquent aucun nouveau composant ne peut être ajouté. + + + + + obsolete + obsolete + + + m_status.active.help + Le composant est actuellement en cours de production et sera produit dans un avenir proche. + + + + + obsolete + obsolete + + + m_status.announced.help + Le composant a été annoncé, mais n'est pas encore disponible. + + + + + obsolete + obsolete + + + m_status.discontinued.help + Le composant n'est plus fabriqué. + + + + + obsolete + obsolete + + + m_status.eol.help + La production de ce composant sera bientôt arrêtée. + + + + + obsolete + obsolete + + + m_status.nrfnd.help + Ce composant est actuellement en production mais n'est pas recommandé pour les nouvelles conceptions. + + + + + obsolete + obsolete + + + m_status.unknown.help + L'état de la production n'est pas connu. + + + + + obsolete + obsolete + + + flash.success + Succès + + + + + obsolete + obsolete + + + flash.error + Erreur + + + + + obsolete + obsolete + + + flash.warning + Attention + + + + + obsolete + obsolete + + + flash.notice + Remarque + + + + + obsolete + obsolete + + + flash.info + Info + + + + + obsolete + obsolete + + + validator.noLockout + Vous ne pouvez pas révoquer vous-même l'autorisation de "modifier les autorisations" pour éviter de vous verrouiller accidentellement ! + + + + + obsolete + obsolete + + + attachment_type.edit.filetype_filter + Types de fichiers autorisés + + + + + obsolete + obsolete + + + attachment_type.edit.filetype_filter.help + Vous pouvez spécifier ici une liste, séparée par des virgules, des extensions de fichiers ou des mimétapes qu'un fichier téléchargé avec ce type de pièce jointe doit avoir. Pour autoriser tous les fichiers d'images pris en charge, utilisez image/*. + + + + + obsolete + obsolete + + + attachment_type.edit.filetype_filter.placeholder + Ex. .txt, application/pdf, image/* + + + + + src\Form\PartType.php:63 + obsolete + obsolete + + + part.name.placeholder + Ex. BC547 + + + + + obsolete + obsolete + + + entity.edit.not_selectable + Non sélectionnable + + + + + obsolete + obsolete + + + entity.edit.not_selectable.help + Si cette option est activée, alors cet élément ne peut être attribué à aucun composant en tant que propriété. Utile, par exemple si cet élément doit être utilisé uniquement pour le tri. + + + + + obsolete + obsolete + + + bbcode.hint + Le BBCode peut être utilisé ici (par exemple [b]Bold[/b]) + + + + + obsolete + obsolete + + + entity.create + Créer un élément + + + + + obsolete + obsolete + + + entity.edit.save + Sauvegarder + + + + + obsolete + obsolete + + + category.edit.disable_footprints + Désactiver les empreintes + + + + + obsolete + obsolete + + + category.edit.disable_footprints.help + Si cette option est activée, la propriété Empreinte est désactivée pour tous les composants de cette catégorie. + + + + + obsolete + obsolete + + + category.edit.disable_manufacturers + Désactiver les fabricants + + + + + obsolete + obsolete + + + category.edit.disable_manufacturers.help + Si cette option est activée, la propriété fabricant est désactivée pour tous les composants de cette catégorie. + + + + + obsolete + obsolete + + + category.edit.disable_autodatasheets + Désactiver les liens automatiques des fiches techniques + + + + + obsolete + obsolete + + + category.edit.disable_autodatasheets.help + Si cette option est activée, aucun lien automatique avec la fiche technique n'est généré pour les pièces de cette catégorie. + + + + + obsolete + obsolete + + + category.edit.disable_properties + Désactiver les propriétés + + + + + obsolete + obsolete + + + category.edit.disable_properties.help + Si cette option est activée, les propriétés des composants pour tous les composants de cette catégorie sont désactivées. + + + + + obsolete + obsolete + + + category.edit.partname_hint + Indication du nom du composant + + + + + obsolete + obsolete + + + category.edit.partname_hint.placeholder + Ex. 100nF + + + + + obsolete + obsolete + + + category.edit.partname_regex + Filtre de nom + + + + + obsolete + obsolete + + + category.edit.default_description + Description par défaut + + + + + obsolete + obsolete + + + category.edit.default_description.placeholder + Ex. Condensateur, 10mmx10mm, CMS + + + + + obsolete + obsolete + + + category.edit.default_comment + Commentaire par défaut + + + + + obsolete + obsolete + + + company.edit.address + Adresse + + + + + obsolete + obsolete + + + company.edit.address.placeholder + Ex. 99 exemple de rue +exemple de ville + + + + + obsolete + obsolete + + + company.edit.phone_number + Numéro de téléphone + + + + + obsolete + obsolete + + + company.edit.phone_number.placeholder + +33 1 23 45 67 89 + + + + + obsolete + obsolete + + + company.edit.fax_number + Numéro de fax + + + + + obsolete + obsolete + + + company.edit.email + Email + + + + + obsolete + obsolete + + + company.edit.email.placeholder + Ex. contact@foo.bar + + + + + obsolete + obsolete + + + company.edit.website + Site internet + + + + + obsolete + obsolete + + + company.edit.website.placeholder + https://www.foo.bar + + + + + obsolete + obsolete + + + company.edit.auto_product_url + URL du produit + + + + + obsolete + obsolete + + + company.edit.auto_product_url.help + Si cette URL est définie, elle est utilisée pour générer l'URL d'un composant sur le site web du fabricant. Dans ce cas, %PARTNUMBER% sera remplacé par le numéro de commande. + + + + + obsolete + obsolete + + + company.edit.auto_product_url.placeholder + https://foo.bar/product/%PARTNUMBER% + + + + + obsolete + obsolete + + + currency.edit.iso_code + Code ISO + + + + + obsolete + obsolete + + + currency.edit.exchange_rate + Taux de change + + + + + obsolete + obsolete + + + footprint.edit.3d_model + Modèle 3D + + + + + obsolete + obsolete + + + mass_creation.lines + Saisie + + + + + obsolete + obsolete + + + mass_creation.lines.placeholder + Élément 1 +Élément 2 +Élément 3 + + + + + obsolete + obsolete + + + entity.mass_creation.btn + Créer + + + + + obsolete + obsolete + + + measurement_unit.edit.is_integer + Nombre entier + + + + + obsolete + obsolete + + + measurement_unit.edit.is_integer.help + Si cette option est activée, toutes les quantités dans cette unité sont arrondies à des nombres entiers. + + + + + obsolete + obsolete + + + measurement_unit.edit.use_si_prefix + Utiliser les préfixes SI + + + + + obsolete + obsolete + + + measurement_unit.edit.use_si_prefix.help + Si cette option est activée, les préfixes SI sont utilisés lors de la génération des nombres (par exemple 1,2 kg au lieu de 1200 g) + + + + + obsolete + obsolete + + + measurement_unit.edit.unit_symbol + Symbole de l'unité + + + + + obsolete + obsolete + + + measurement_unit.edit.unit_symbol.placeholder + Ex. m + + + + + obsolete + obsolete + + + storelocation.edit.is_full.label + Emplacement de stockage plein + + + + + obsolete + obsolete + + + storelocation.edit.is_full.help + Si cette option est activée, il n'est pas possible d'ajouter de nouveaux composants à ce lieu de stockage ni d'augmenter le nombre de composants existants. + + + + + obsolete + obsolete + + + storelocation.limit_to_existing.label + Limiter aux composants existants + + + + + obsolete + obsolete + + + storelocation.limit_to_existing.help + Si cette option est active, il n'est pas possible d'ajouter de nouveaux composants à ce lieu de stockage, mais il est possible d'augmenter le nombre de composants existants. + + + + + obsolete + obsolete + + + storelocation.only_single_part.label + Seulement un composant + + + + + obsolete + obsolete + + + storelocation.only_single_part.help + Si cette option est activée, cet emplacement de stockage ne peut contenir qu'un seul composant (mais une quantité quelconque). Utile pour les petits compartiments ou les distributeurs de CMS. + + + + + obsolete + obsolete + + + storelocation.storage_type.label + Type de stockage + + + + + obsolete + obsolete + + + storelocation.storage_type.help + Ici, vous pouvez sélectionner une unité de mesure qu'un composant doit avoir pour être stocké dans ce lieu de stockage. + + + + + obsolete + obsolete + + + supplier.edit.default_currency + Devise par défaut + + + + + obsolete + obsolete + + + supplier.shipping_costs.label + Frais de port + + + + + obsolete + obsolete + + + user.username.placeholder + Ex. j.doe + + + + + obsolete + obsolete + + + user.firstName.placeholder + Ex. John + + + + + obsolete + obsolete + + + user.lastName.placeholder + Ex. Doe + + + + + obsolete + obsolete + + + user.email.placeholder + j.doe@ecorp.com + + + + + obsolete + obsolete + + + user.department.placeholder + Ex. Development + + + + + obsolete + obsolete + + + user.settings.pw_new.label + Nouveau mot de passe + + + + + obsolete + obsolete + + + user.settings.pw_confirm.label + Confirmer le nouveau mot de passe + + + + + obsolete + obsolete + + + user.edit.needs_pw_change + L'utilisateur doit changer de mot de passe + + + + + obsolete + obsolete + + + user.edit.user_disabled + Utilisateur désactivé (connexion impossible) + + + + + obsolete + obsolete + + + user.create + Créer l'utilisateur + + + + + obsolete + obsolete + + + user.edit.save + Enregistrer + + + + + obsolete + obsolete + + + entity.edit.reset + Rejeter les modifications + + + + + templates\Parts\show_part_info.html.twig:166 + obsolete + obsolete + + + part.withdraw.btn + Retrait + + + + + templates\Parts\show_part_info.html.twig:171 + obsolete + obsolete + + + part.withdraw.comment: + Commentaire/objet + + + + + templates\Parts\show_part_info.html.twig:189 + obsolete + obsolete + + + part.add.caption + Ajouter composants + + + + + templates\Parts\show_part_info.html.twig:194 + obsolete + obsolete + + + part.add.btn + Ajouter + + + + + templates\Parts\show_part_info.html.twig:199 + obsolete + obsolete + + + part.add.comment + Commentaire/objet + + + + + templates\AdminPages\CompanyAdminBase.html.twig:15 + obsolete + obsolete + + + admin.comment + Commentaire + + + + + src\Form\PartType.php:83 + obsolete + obsolete + + + manufacturer_url.label + Lien vers le site du fabricant + + + + + src\Form\PartType.php:66 + obsolete + obsolete + + + part.description.placeholder + Ex. NPN 45V 0,1A 0,5W + + + + + src\Form\PartType.php:69 + obsolete + obsolete + + + part.instock.placeholder + Ex. 10 + + + + + src\Form\PartType.php:72 + obsolete + obsolete + + + part.mininstock.placeholder + Ex. 10 + + + + + obsolete + obsolete + + + part.order.price_per + Prix par + + + + + obsolete + obsolete + + + part.withdraw.caption + Retrait de composants + + + + + obsolete + obsolete + + + datatable.datatable.lengthMenu + _MENU_ + + + + + obsolete + obsolete + + + perm.group.parts + Composants + + + + + obsolete + obsolete + + + perm.group.structures + Structures des données + + + + + obsolete + obsolete + + + perm.group.system + Système + + + + + obsolete + obsolete + + + perm.parts + Général + + + + + obsolete + obsolete + + + perm.read + Afficher + + + + + obsolete + obsolete + + + perm.edit + Éditer + + + + + obsolete + obsolete + + + perm.create + Créer + + + + + obsolete + obsolete + + + perm.part.move + Changer de catégorie + + + + + obsolete + obsolete + + + perm.delete + Supprimer + + + + + obsolete + obsolete + + + perm.part.search + Rechercher + + + + + obsolete + obsolete + + + perm.part.all_parts + Liste de tous les composants + + + + + obsolete + obsolete + + + perm.part.no_price_parts + Liste des composants sans prix + + + + + obsolete + obsolete + + + perm.part.obsolete_parts + Liste des composants obsolètes + + + + + obsolete + obsolete + + + perm.part.unknown_instock_parts + Liste des composants dont le stock est inconnu + + + + + obsolete + obsolete + + + perm.part.change_favorite + Changer le statut de favori + + + + + obsolete + obsolete + + + perm.part.show_favorite + Afficher les favoris + + + + + obsolete + obsolete + + + perm.part.show_last_edit_parts + Afficher les derniers composants modifiés/ajoutés + + + + + obsolete + obsolete + + + perm.part.show_users + Afficher le dernier utilisateur ayant apporté des modifications + + + + + obsolete + obsolete + + + perm.part.show_history + Afficher l'historique + + + + + obsolete + obsolete + + + perm.part.name + Nom + + + + + obsolete + obsolete + + + perm.part.description + Description + + + + + obsolete + obsolete + + + perm.part.instock + En stock + + + + + obsolete + obsolete + + + perm.part.mininstock + Stock minimum + + + + + obsolete + obsolete + + + perm.part.comment + Commentaire + + + + + obsolete + obsolete + + + perm.part.storelocation + Emplacement de stockage + + + + + obsolete + obsolete + + + perm.part.manufacturer + Fabricant + + + + + obsolete + obsolete + + + perm.part.orderdetails + Informations pour la commande + + + + + obsolete + obsolete + + + perm.part.prices + Prix + + + + + obsolete + obsolete + + + perm.part.attachments + Fichiers joints + + + + + obsolete + obsolete + + + perm.part.order + Commandes + + + + + obsolete + obsolete + + + perm.storelocations + Emplacements de stockage + + + + + obsolete + obsolete + + + perm.move + Déplacer + + + + + obsolete + obsolete + + + perm.list_parts + Liste des composants + + + + + obsolete + obsolete + + + perm.part.footprints + Empreintes + + + + + obsolete + obsolete + + + perm.part.categories + Catégories + + + + + obsolete + obsolete + + + perm.part.supplier + Fournisseurs + + + + + obsolete + obsolete + + + perm.part.manufacturers + Fabricants + + + + + obsolete + obsolete + + + perm.part.attachment_types + Types de fichiers joints + + + + + obsolete + obsolete + + + perm.tools.import + Importer + + + + + obsolete + obsolete + + + perm.tools.labels + Étiquettes + + + + + obsolete + obsolete + + + perm.tools.calculator + Calculateur de résistance + + + + + obsolete + obsolete + + + perm.tools.footprints + Empreintes + + + + + obsolete + obsolete + + + perm.tools.ic_logos + Logos CI + + + + + obsolete + obsolete + + + perm.tools.statistics + Statistiques + + + + + obsolete + obsolete + + + perm.edit_permissions + Éditer les autorisations + + + + + obsolete + obsolete + + + perm.users.edit_user_name + Modifier le nom d'utilisateur + + + + + obsolete + obsolete + + + perm.users.edit_change_group + Modifier le groupe + + + + + obsolete + obsolete + + + perm.users.edit_infos + Editer les informations + + + + + obsolete + obsolete + + + perm.users.edit_permissions + Modifier les autorisations + + + + + obsolete + obsolete + + + perm.users.set_password + Définir le mot de passe + + + + + obsolete + obsolete + + + perm.users.change_user_settings + Changer les paramètres utilisateur + + + + + obsolete + obsolete + + + perm.database.see_status + Afficher l’état + + + + + obsolete + obsolete + + + perm.database.update_db + Actualiser la base de données + + + + + obsolete + obsolete + + + perm.database.read_db_settings + Lecture des paramètres de la base de donnée + + + + + obsolete + obsolete + + + perm.database.write_db_settings + Modifier les paramètres de la base de données + + + + + obsolete + obsolete + + + perm.config.read_config + Lecture de la configuration + + + + + obsolete + obsolete + + + perm.config.edit_config + Modifier la configuration + + + + + obsolete + obsolete + + + perm.config.server_info + Informations sur le serveur + + + + + obsolete + obsolete + + + perm.config.use_debug + Utiliser les outils de débogage + + + + + obsolete + obsolete + + + perm.show_logs + Afficher les logs + + + + + obsolete + obsolete + + + perm.delete_logs + Supprimer les logs + + + + + obsolete + obsolete + + + perm.self.edit_infos + Modifier les informations + + + + + obsolete + obsolete + + + perm.self.edit_username + Modifier le nom d'utilisateur + + + + + obsolete + obsolete + + + perm.self.show_permissions + Voir les autorisations + + + + + obsolete + obsolete + + + perm.self.show_logs + Afficher ses propres logs + + + + + obsolete + obsolete + + + perm.self.create_labels + Créer des étiquettes + + + + + obsolete + obsolete + + + perm.self.edit_options + Modifier les options + + + + + obsolete + obsolete + + + perm.self.delete_profiles + Supprimer les profils + + + + + obsolete + obsolete + + + perm.self.edit_profiles + Modifier les profils + + + + + obsolete + obsolete + + + perm.part.tools + Outils + + + + + obsolete + obsolete + + + perm.groups + Groupes + + + + + obsolete + obsolete + + + perm.users + Utilisateurs + + + + + obsolete + obsolete + + + perm.database + Base de données + + + + + obsolete + obsolete + + + perm.config + Configuration + + + + + obsolete + obsolete + + + perm.system + Système + + + + + obsolete + obsolete + + + perm.self + Propre utilisateur + + + + + obsolete + obsolete + + + perm.labels + Étiquettes + + + + + obsolete + obsolete + + + perm.part.category + Catégorie + + + + + obsolete + obsolete + + + perm.part.minamount + Quantité minimum + + + + + obsolete + obsolete + + + perm.part.footprint + Empreinte + + + + + obsolete + obsolete + + + perm.part.mpn + MPN + + + + + obsolete + obsolete + + + perm.part.status + État de la fabrication + + + + + obsolete + obsolete + + + perm.part.tags + Tags + + + + + obsolete + obsolete + + + perm.part.unit + Unité + + + + + obsolete + obsolete + + + perm.part.mass + Poids + + + + + obsolete + obsolete + + + perm.part.lots + Lots de composants + + + + + obsolete + obsolete + + + perm.show_users + Afficher le dernier utilisateur ayant apporté des modifications + + + + + obsolete + obsolete + + + perm.currencies + Devises + + + + + obsolete + obsolete + + + perm.measurement_units + Unités de mesure + + + + + obsolete + obsolete + + + user.settings.pw_old.label + Ancien mot de passe + + + + + obsolete + obsolete + + + pw_reset.submit + Réinitialiser le mot de passe + + + + + obsolete + obsolete + + + u2f_two_factor + Clé de sécurité (U2F) + + + + + obsolete + obsolete + + + google + google + + + + + obsolete + obsolete + + + tfa.provider.google + Application d'authentification + + + + + obsolete + obsolete + + + Login successful + Connexion réussie + + + + + obsolete + obsolete + + + log.type.exception + Exception + + + + + obsolete + obsolete + + + log.type.user_login + Connexion utilisateur + + + + + obsolete + obsolete + + + log.type.user_logout + Déconnexion de l’utilisateur + + + + + obsolete + obsolete + + + log.type.unknown + Inconnu + + + + + obsolete + obsolete + + + log.type.element_created + Élément créé + + + + + obsolete + obsolete + + + log.type.element_edited + Élément modifié + + + + + obsolete + obsolete + + + log.type.element_deleted + Élément supprimé + + + + + obsolete + obsolete + + + log.type.database_updated + Base de données mise à jour + + + + + obsolete + + + perm.revert_elements + Restaurer les éléments + + + + + obsolete + + + perm.show_history + Afficher l'historique + + + + + obsolete + + + perm.tools.lastActivity + Afficher l'activité récente + + + + + obsolete + + + perm.tools.timeTravel + Afficher les anciennes versions des éléments (Time travel) + + + + + obsolete + + + tfa_u2f.key_added_successful + Clé de sécurité ajoutée avec succès. + + + + + obsolete + + + Username + Nom d'utilisateur + + + + + obsolete + + + log.type.security.google_disabled + Application d'authentification désactivée + + + + + obsolete + + + log.type.security.u2f_removed + Clé de sécurité enlevée + + + + + obsolete + + + log.type.security.u2f_added + Clé de sécurité ajoutée + + + + + obsolete + + + log.type.security.backup_keys_reset + Clés de sauvegarde régénérées + + + + + obsolete + + + log.type.security.google_enabled + Application Authenticator activée + + + + + obsolete + + + log.type.security.password_changed + Mot de passe modifié + + + + + obsolete + + + log.type.security.trusted_device_reset + Appareils de confiance réinitialisés + + + + + obsolete + + + log.type.collection_element_deleted + Élément de collecte supprimé + + + + + obsolete + + + log.type.security.password_reset + Réinitialisation du mot de passe + + + + + obsolete + + + log.type.security.2fa_admin_reset + Réinitialisation à deux facteurs par l'administrateur + + + + + obsolete + + + log.type.user_not_allowed + Tentative d'accès non autorisé + + + + + obsolete + + + log.database_updated.success + Succès + + + + + obsolete + + + label_options.barcode_type.2D + 2D + + + + + obsolete + + + label_options.barcode_type.1D + 1D + + + + + obsolete + + + perm.part.parameters + Caractéristiques + + + + + obsolete + + + perm.attachment_show_private + Voir les pièces jointes privées + + + + + obsolete + + + perm.tools.label_scanner + Lecteur d'étiquettes + + + + + obsolete + + + perm.self.read_profiles + Lire les profils + + + + + obsolete + + + perm.self.create_profiles + Créer des profils + + + + + obsolete + + + perm.labels.use_twig + Utiliser le mode twig + + + + + label_profile.showInDropdown + Afficher en sélection rapide + + + + + group.edit.enforce_2fa + Imposer l'authentification à deux facteurs (2FA) + + + + + group.edit.enforce_2fa.help + Si cette option est activée, chaque membre direct de ce groupe doit configurer au moins un deuxième facteur d'authentification. Recommandé pour les groupes administratifs ayant beaucoup de permissions. + + + + + selectpicker.empty + Rien n'est sélectionné + + + + + selectpicker.nothing_selected + Rien n'est sélectionné + + + + + entity.delete.must_not_contain_parts + L'élement contient encore des parties ! Vous devez déplacer les parties pour pouvoir supprimer cet élément. + + + + + entity.delete.must_not_contain_attachments + Le type de pièce jointe contient toujours des pièces jointes. Changez leur type, pour pouvoir supprimer ce type de pièce jointe. + + + + + entity.delete.must_not_contain_prices + La devise contient encore des prix. Vous devez changer leur devise pour pouvoir supprimer cet élément. + + + + + entity.delete.must_not_contain_users + Des utilisateurs utilisent toujours ce groupe ! Changez les de groupe pour pouvoir supprimer ce groupe. + + + + + part.table.edit + Modifier + + + + + part.table.edit.title + Modifier composant + + + + + part_list.action.action.title + Sélectionnez une action + + + + + part_list.action.action.group.favorite + Statut favori + + + + + part_list.action.action.favorite + Favorable + + + + + part_list.action.action.unfavorite + Défavorable + + + + + part_list.action.action.group.change_field + Modifier le champ + + + + + part_list.action.action.change_category + Modifier la catégorie + + + + + part_list.action.action.change_footprint + Modifier l'empreinte + + + + + part_list.action.action.change_manufacturer + Modifier le fabricant + + + + + part_list.action.action.change_unit + Modifier l'unité + + + + + part_list.action.action.delete + Supprimer + + + + + part_list.action.submit + Soumettre + + + + + part_list.action.part_count + %count% composants sélectionnés + + + + + company.edit.quick.website + Ouvrir le site web + + + + + company.edit.quick.email + Envoyer un e-mail + + + + + company.edit.quick.phone + Téléphoner + + + + + company.edit.quick.fax + Envoyer une télécopie + + + + + company.fax_number.placeholder + ex. +33 12 34 56 78 90 + + + + + part.edit.save_and_clone + Sauvegarder et dupliquer + + + + + validator.file_ext_not_allowed + L'extension de fichier n'est pas autorisée pour ce type de pièce jointe. + + + + + tools.reel_calc.title + Calculateur de bobines CMS + + + + + tools.reel_calc.inner_dia + Diamètre intérieur + + + + + tools.reel_calc.outer_dia + Diamètre extérieur + + + + + tools.reel_calc.tape_thick + Épaisseur du ruban + + + + + tools.reel_calc.part_distance + Distance entre les composants + + + + + tools.reel_calc.update + Actualiser + + + + + tools.reel_calc.parts_per_meter + Composants par mètre + + + + + tools.reel_calc.result_length + Longueur de la bande + + + + + tools.reel_calc.result_amount + Nbre approximatif de composants + + + + + tools.reel_calc.outer_greater_inner_error + Erreur : Le diamètre extérieur doit être supérieur au diamètre intérieur ! + + + + + tools.reel_calc.missing_values.error + Veuillez remplir toutes les valeurs ! + + + + + tools.reel_calc.load_preset + Charger la présélection + + + + + tools.reel_calc.explanation + Ce calculateur vous donne une estimation du nombre de pièces qui restent sur une bobine de CMS. Mesurez les dimensions notées sur la bobine (ou utilisez certains des préréglages) et cliquez sur "Actualiser" pour obtenir un résultat. + + + + + perm.tools.reel_calculator + Calculateur de bobines CMS + + + + + tree.tools.tools.reel_calculator + Calculateur de bobines CMS + + + + + currency.edit.update_rate + Taux de rafraîchissement + + + + + currency.edit.exchange_rate_update.unsupported_currency + Devise non prise en charge + + + + + currency.edit.exchange_rate_update.generic_error + Erreur générique + + + + + currency.edit.exchange_rate_updated.success + Succès + + + + + homepage.forum.text + Si vous avez des questions à propos de Part-DB , rendez vous sur <a href="%href%" class="link-external" target="_blank">Github</a> + + + + + assembly.edit.status + Statut de l'assemblage + + + + + assembly.status.draft + Brouillon + + + + + assembly.status.planning + En planification + + + + + assembly.status.in_production + En production + + + + + assembly.status.finished + Terminé + + + + + assembly.status.archived + Archivé + + + + + assembly.label + Assemblage + + + + + assembly.caption + Assemblage + + + + + perm.assemblies + Assemblages + + + + + assembly_bom_entry.label + Composants + + + + + assembly.labelp + Assemblages + + + + + assembly.referencedAssembly.labelp + Assemblages référencés + + + + + assembly.edit + Modifier l'assemblage + + + + + assembly.new + Nouvel assemblage + + + + + assembly.edit.bom.import_bom + Importer des composants + + + + + log.database_updated.failed + __log.database_updated.failed + + + + + log.database_updated.old_version + __log.database_updated.old_version + + + + + log.database_updated.new_version + __log.database_updated.new_version + + + + + tree.tools.edit.assemblies + Assemblages + + + + + assembly.bom_import.flash.success + %count% composant(s) ont été importé(s) avec succès dans l'assemblage. + + + + + assembly.bom_import.flash.invalid_entries + Erreur de validation ! Veuillez vérifier le fichier importé ! + + + + + assembly.bom_import.flash.invalid_file + Le fichier n'a pas pu être importé. Veuillez vérifier que vous avez sélectionné le bon type de fichier. Message d'erreur : %message% + + + + + assembly.bom.quantity + Quantité + + + + + assembly.bom.mountnames + Noms de montage + + + + + assembly.bom.designator + Désignateur + + + + + assembly.bom.designator.help + Identifiants de référence libres (designator) + + + + + assembly.bom.instockAmount + Quantité en stock + + + + + assembly.info.title + Informations sur l'assemblage + + + + + assembly.info.info.label + Informations + + + + + assembly.info.sub_assemblies.label + Sous-ensembles + + + + + assembly.info.builds.label + Constructions + + + + + assembly.info.bom_add_parts + Ajouter des pièces + + + + + assembly.info.bom_entries_count + Composants + + + + + assembly.info.sub_assemblies_count + Sous-ensembles + + + + + assembly.bom.delete.confirm + Voulez-vous vraiment supprimer cette entrée ? + + + + + assembly.add_parts_to_assembly + Ajouter des pièces à l'assemblage + + + + + part.info.add_part_to_assembly + Ajouter cette pièce à un assemblage + + + + + assembly.bom.project + Projet + + + + + assembly.bom.referencedAssembly + Assemblage + + + + + assembly.bom.name + Nom + + + + + assembly.bom.name.help + Titre lisible par l’humain de l’entrée de nomenclature + + + + + assembly.bom.comment + Commentaires + + + + + assembly.import_bom + Importer des pièces pour l'assemblage + + + + + assembly.bom.partOrAssembly + Pièce ou assemblage + + + + + assembly.bom.identifiers + Identifiants + + + + + assembly.bom.add_entry + Ajouter une ligne + + + + + assembly.bom.price + Prix + + + + + assembly.bom_import.type + Type + + + + + assembly.bom_import.type.json + JSON pour un assemblage + + + + + assembly.bom_import.type.csv + CSV pour un assemblage + + + + + assembly.bom_import.type.json + JSON + + + + + assembly.bom_import.type.csv + CSV + + + + + assembly.bom_import.type.kicad_pcbnew + CSV (KiCAD Pcbnew BOM) + + + + + assembly.bom_import.type.kicad_schematic + KiCAD Éditeur Schématique BOM (fichier CSV) + + + + + assembly.bom_import.clear_existing_bom + Supprimer les entrées de pièces existantes avant l’importation + + + + + assembly.bom_import.clear_existing_bom.help + Si cette option est cochée, toutes les pièces existantes dans l’assemblage seront supprimées et remplacées par les données importées. + + + + + assembly.import_bom.template.header.json + Modèle d’importation JSON pour un assemblage + + + + + assembly.import_bom.template.header.csv + Modèle d'importation CSV pour un assemblage + + + + + assembly.import_bom.template.header.kicad_pcbnew + Modèle d’importation CSV (KiCAD Pcbnew BOM) pour un assemblage + + + + + assembly.bom_import.template.entry.name + Nom de la pièce dans l’assemblage + + + + + assembly.bom_import.template.entry.part.mpnr + Numéro unique de la pièce chez le fabricant + + + + + assembly.bom_import.template.entry.part.ipn + Numéro IPN unique de la pièce + + + + + assembly.bom_import.template.entry.part.name + Nom unique de la pièce + + + + + assembly.bom_import.template.entry.part.manufacturer.name + Nom unique du fabricant + + + + + assembly.bom_import.template.entry.part.category.name + Nom unique de la catégorie + + + + + assembly.bom_import.template.json.table + + + + + Champ + Condition + Type de données + Description + + + + + quantity + Champ obligatoire + Nombre à virgule flottante (Float) + Doit être rempli et contenir une valeur décimale (Float) supérieure à 0.0. + + + name + Optionnel + Chaîne + Si renseigné, doit être une chaîne non vide. Le nom de l'élément dans l'assemblage. + + + part + Optionnel + Objet/Tableau + + Si une pièce doit être assignée, cela doit être un objet/tableau et au moins un des champs suivants doit être renseigné : +
    +
  • part.id
  • +
  • part.mpnr
  • +
  • part.ipn
  • +
  • part.name
  • +
+ + + + part.id + Optionnel + Entier (Integer) + Nombre entier > 0. Correspond à l'ID interne numérique de la pièce dans la base de données. + + + part.mpnr + Optionnel + Chaîne + Chaîne non vide si part.id, part.ipn ou part.name ne sont pas renseignés. + + + part.ipn + Optionnel + Chaîne + Chaîne non vide si part.id, part.mpnr ou part.name ne sont pas renseignés. + + + part.name + Optionnel + Chaîne + Chaîne non vide si part.id, part.mpnr ou part.ipn ne sont pas renseignés. + + + part.description + Optionnel + Chaîne ou null + Si renseignée, doit être une chaîne non vide ou null. Ce champ remplacera la valeur existante de la pièce. + + + part.manufacturer + Optionnel + Objet/Tableau + + Si le fabricant de la pièce doit être modifié ou recherché de manière unique à l'aide de la valeur part.mpnr, cela doit être un objet/tableau et au moins un des champs suivants doit être renseigné : +
    +
  • manufacturer.id
  • +
  • manufacturer.name
  • +
+ + + + manufacturer.id + Optionnel + Entier (Integer) + Nombre entier > 0. Correspond à l'ID interne numérique du fabricant. + + + manufacturer.name + Optionnel + Chaîne + Chaîne non vide si manufacturer.id n'est pas renseigné. + + + part.category + Optionnel + Objet/Tableau + + Si la catégorie de la pièce doit être modifiée, cela doit être un objet/tableau et au moins un des champs suivants doit être renseigné : +
    +
  • category.id
  • +
  • category.name
  • +
+ + + + category.id + Optionnel + Entier (Integer) + Nombre entier > 0. Correspond à l'ID interne numérique de la catégorie de la pièce. + + + category.name + Optionnel + Chaîne + Chaîne non vide si category.id n'est pas renseigné. + + + + ]]> +
+
+
+ + + assembly.bom_import.template.csv.exptected_columns + Colonnes possibles : + + + + + assembly.bom_import.template.csv.table + + + + + Colonne + Condition + Type de données + Description + + + + + quantity + Champ obligatoire + Nombre à virgule flottante (Float) + Doit être rempli et contenir une valeur décimale (Float) supérieure à 0.0. + + + name + Optionnel + Chaîne + Le nom de l'élément dans l'assemblage. + + + Colonnes commençant par part_ + + Si une pièce doit être assignée, au moins une des colonnes suivantes doit être renseignée : +
    +
  • part_id
  • +
  • part_mpnr
  • +
  • part_ipn
  • +
  • part_name
  • +
+ + + + part_id + Optionnel + Entier (Integer) + Nombre entier > 0. Correspond à l'ID interne numérique de la pièce dans la base de données. + + + part_mpnr + Optionnel + Chaîne + Doit être renseignée si les colonnes part_id, part_ipn ou part_name ne sont pas remplies. + + + part_ipn + Optionnel + Chaîne + Doit être renseignée si les colonnes part_id, part_mpnr ou part_name ne sont pas remplies. + + + part_name + Optionnel + Chaîne + Doit être renseignée si les colonnes part_id, part_mpnr ou part_ipn ne sont pas remplies. + + + part_description + Optionnel + Chaîne + Sera transférée et remplacera la valeur existante de la description si une chaîne non vide est fournie. + + + Colonnes commençant par part_manufacturer_ + + Si le fabricant de la pièce doit être modifié ou recherché uniquement via part_mpnr, au moins une des colonnes suivantes doit être renseignée : +
    +
  • part_manufacturer_id
  • +
  • part_manufacturer_name
  • +
+ + + + part_manufacturer_id + Optionnel + Entier (Integer) + Nombre entier > 0. Correspond à l'ID interne numérique du fabricant. + + + part_manufacturer_name + Optionnel + Chaîne + Doit être renseignée si part_manufacturer_id n'est pas fourni. + + + Colonnes commençant par part.category_ + + Si la catégorie de la pièce doit être modifiée, au moins une des colonnes suivantes doit être renseignée : +
    +
  • part_category_id
  • +
  • part_category_name
  • +
+ + + + part_category_id + Optionnel + Entier (Integer) + Nombre entier > 0. Correspond à l'ID interne numérique de la catégorie de la pièce. + + + part_category_name + Optionnel + Chaîne + Doit être renseignée si part_category_id n'est pas fourni. + + + + ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.exptected_columns + Colonnes attendues: + + + + + assembly.bom_import.template.kicad_pcbnew.exptected_columns.note + + Remarque: Aucun mappage n'est effectué avec des composants spécifiques issus de la gestion des catégories.

+ ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.table + + + + + Champ + Condition + Type de Données + Description + + + + + Id + Optionnel + Entier + Champ libre. Un numéro d'identification unique pour chaque composant. + + + Designator + Optionnel + Chaîne + Champ libre. Une désignation de référence unique pour le composant sur le PCB, par exemple, "R1" pour la résistance 1.
Utilisé comme le nom de l'emplacement de l'entrée composant dans l'assemblage. + + + Package + Optionnel + Chaîne + Champ libre. Le boîtier ou le format du composant, par exemple, "0805" pour les résistances CMS.
Non inclus dans l'entrée composant pour l'assemblage. + + + Quantity + Obligatoire + Entier + Le nombre de composants identiques nécessaires pour créer une instance de l'assemblage.
Utilisé comme la quantité dans l'entrée composant de l'assemblage. + + + Designation + Obligatoire + Chaîne + La description ou la fonction du composant, par exemple, valeur de résistance "10kΩ" ou valeur de condensateur "100nF".
Utilisé comme le nom dans l'entrée composant pour l'assemblage. + + + Supplier and ref + Optionnel + Chaîne + Champ libre. Peut contenir par exemple des informations spécifiques sur le fournisseur.
Utilisé comme une note dans l'entrée composant pour l'assemblage. + + + + ]]> +
+
+
+ + + assembly_list.all.title + Toutes les assemblages + + + + + assembly.edit.tab.common + Général + + + + + assembly.edit.tab.advanced + Options avancées + + + + + assembly.edit.tab.attachments + Pièces jointes + + + + + assembly.filter.dbId + ID de la base de données + + + + + assembly.filter.ipn + Numéro de pièce interne (IPN) + + + + + assembly.filter.name + Nom + + + + + assembly.filter.description + Description + + + + + assembly.filter.comment + Commentaires + + + + + assembly.filter.attachments_count + Nombre de pièces jointes + + + + + assembly.filter.attachmentName + Nom de la pièce jointe + + + + + assemblies.create.btn + Créer un nouvel assemblage + + + + + assembly.table.id + ID + + + + + assembly.table.name + Nom + + + + + assembly.table.ipn + IPN + + + + + assembly.table.description + Description + + + + + assembly.table.referencedAssemblies + Ensembles référencés + + + + + assembly.table.addedDate + Ajouté + + + + + assembly.table.lastModified + Dernière modification + + + + + assembly.table.edit + Modifier + + + + + assembly.table.edit.title + Modifier l'assemblage + + + + + assembly.table.invalid_regex + Expression régulière invalide (regex) + + + + + assembly.bom.table.id + ID + + + + + assembly.bom.table.name + Nom + + + + + assembly.bom.table.quantity + Quantité + + + + + assembly.bom.table.ipn + IPN + + + + + assembly.bom.table.description + Description + + + + + assembly.bom.table.category + Catégorie + + + + + assembly.bom.table.manufacturer + Fabricant + + + + + assembly.bom.table.designator + Désignateur de référence + + + + + assembly.bom.table.mountnames + Noms de montage + + + + + assembly.bom.table.storage_location + Emplacement de stockage + + + + + assembly.bom.table.amount + Quantité + + + + + assembly.bom.table.addedDate + Créé le + + + + + assembly.bom.table.lastModified + Dernière modification + + + + + assembly.bom.table.edit + Modifier + + +
+
diff --git a/translations/messages.it.xlf b/translations/messages.it.xlf index 828304eba..cefcc202b 100644 --- a/translations/messages.it.xlf +++ b/translations/messages.it.xlf @@ -351,6 +351,24 @@ Esportare tutti gli elementi + + + export.readable.label + Esporta leggibile + + + + + export.readable + CSV + + + + + export.readable_bom + PDF + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:185 @@ -4742,6 +4760,24 @@ Se è stato fatto in modo errato o se un computer non è più attendibile, puoi Nome + + + part.table.name.value.for_part + %value% (Componente) + + + + + part.table.name.value.for_assembly + %value% (Assemblaggio) + + + + + part.table.name.value.for_project + %value% (Progetto) + + Part-DB1\src\DataTables\PartsDataTable.php:178 @@ -9884,6 +9920,48 @@ Element 3 Archiviato + + + assembly.edit.status + Stato dell'assemblaggio + + + + + assembly.edit.ipn + Codice interno (IPN) + + + + + assembly.status.draft + Bozza + + + + + assembly.status.planning + In pianificazione + + + + + assembly.status.in_production + In produzione + + + + + assembly.status.finished + Completato + + + + + assembly.status.archived + Archiviato + + part.new_build_part.error.build_part_already_exists @@ -11030,6 +11108,18 @@ Element 3 Tipo + + + project.bom_import.type.json + JSON + + + + + project.bom_import.type.csv + CSV + + project.bom_import.type.kicad_pcbnew @@ -11042,6 +11132,319 @@ Element 3 Cancellare le voci della BOM (lista dei materiali) esistenti prima dell'importazione + + + project.import_bom.template.header.json + Modello di importazione JSON + + + + + project.import_bom.template.header.csv + Modello di importazione CSV + + + + + project.import_bom.template.header.kicad_pcbnew + Modello di importazione CSV (KiCAD Pcbnew BOM) + + + + + project.bom_import.template.entry.name + Nome del componente nel progetto + + + + + project.bom_import.template.entry.part.mpnr + Codice prodotto unico del produttore + + + + + project.bom_import.template.entry.part.ipn + IPN unico del componente + + + + + project.bom_import.template.entry.part.name + Nome unico del componente + + + + + project.bom_import.template.entry.part.manufacturer.name + Nome unico del produttore + + + + + project.bom_import.template.json.table + + + + + Campo + Condizione + Tipo di Dati + Descrizione + + + + + quantity + Obbligatorio + Decimale (Float) + Deve essere fornito e contenere un valore decimale (Float) maggiore di 0.0. + + + name + Opzionale + Stringa (String) + Se presente, deve essere una stringa non vuota. Il nome dell'elemento all'interno della distinta materiali. + + + part + Opzionale + Oggetto/Array + + Se un componente deve essere assegnato, deve essere un oggetto/array e almeno uno dei seguenti campi deve essere compilato: +
    +
  • part.id
  • +
  • part.mpnr
  • +
  • part.ipn
  • +
  • part.name
  • +
+ + + + part.id + Opzionale + Intero (Integer) + Intero (Integer) > 0. Corrisponde all'ID numerico interno del componente nel database delle parti (Part-DB). + + + part.mpnr + Opzionale + Stringa (String) + Una stringa non vuota se non sono forniti part.id, part.ipn o part.name. + + + part.ipn + Opzionale + Stringa (String) + Una stringa non vuota se non sono forniti part.id, part.mpnr o part.name. + + + part.name + Opzionale + Stringa (String) + Una stringa non vuota se non sono forniti part.id, part.mpnr o part.ipn. + + + part.manufacturer + Opzionale + Oggetto/Array + + Se il produttore di un componente deve essere modificato o se è necessario identificare univocamente il componente basandosi su part.mpnr, deve essere un oggetto/array e almeno uno dei seguenti campi deve essere compilato: +
    +
  • manufacturer.id
  • +
  • manufacturer.name
  • +
+ + + + manufacturer.id + Opzionale + Intero (Integer) + Intero (Integer) > 0. Corrisponde all'ID numerico interno del produttore. + + + manufacturer.name + Opzionale + Stringa (String) + Una stringa non vuota se non è fornito manufacturer.id. + + + + ]]> +
+
+
+ + + project.bom_import.template.csv.exptected_columns + Colonne possibili: + + + + + project.bom_import.template.csv.table + + + + + Colonna + Condizione + Tipo di dato + Descrizione + + + + + quantity + Obbligatoria + Numero decimale (Float) + Deve essere fornita e contenere un valore decimale (Float) maggiore di 0.0. + + + name + Optional + String + Se disponibile, deve essere una stringa non vuota. Il nome della voce all'interno della distinta base. + + + Colonne che iniziano con part_ + + Se un componente deve essere assegnato, almeno una delle seguenti colonne deve essere fornita e compilata: +
    +
  • part_id
  • +
  • part_mpnr
  • +
  • part_ipn
  • +
  • part_name
  • +
+ + + + part_id + Opzionale + Intero (Integer) + Intero > 0. Corrisponde all'ID numerico interno del componente nel database delle parti (Part-DB). + + + part_mpnr + Opzionale + Stringa (String) + Deve essere fornita se le colonne part_id, part_ipn o part_name non sono compilate. + + + part_ipn + Opzionale + Stringa (String) + Deve essere fornita se le colonne part_id, part_mpnr o part_name non sono compilate. + + + part_name + Opzionale + Stringa (String) + Deve essere fornita se le colonne part_id, part_mpnr o part_ipn non sono compilate. + + + Colonne che iniziano con part_manufacturer_ + + Se il produttore di un componente deve essere modificato o il componente deve essere identificato univocamente in base al valore part_mpnr, almeno una delle seguenti colonne deve essere fornita e compilata: +
    +
  • part_manufacturer_id
  • +
  • part_manufacturer_name
  • +
+ + + + part_manufacturer_id + Opzionale + Intero (Integer) + Intero > 0. Corrisponde all'ID numerico interno del produttore. + + + part_manufacturer_name + Opzionale + Stringa (String) + Deve essere fornita se la colonna part_manufacturer_id non è compilata. + + + + ]]> +
+
+
+ + + project.bom_import.template.kicad_pcbnew.exptected_columns + Colonne previste: + + + + + project.bom_import.template.kicad_pcbnew.exptected_columns.note + + Nota: Non viene effettuata alcuna associazione con componenti specifici dalla gestione delle categorie.

+ ]]> +
+
+
+ + + project.bom_import.template.kicad_pcbnew.table + + + + + Campo + Condizione + Tipo di dato + Descrizione + + + + + Id + Opzionale + Numero intero + Valore libero. Un numero identificativo univoco per ciascun componente. + + + Designator + Opzionale + Stringa + Valore libero. Un identificatore di riferimento univoco del componente sul PCB, ad esempio "R1" per il resistore 1.
Viene trasferito nel nome di montaggio del record del componente. + + + Package + Opzionale + Stringa + Valore libero. L'involucro o la forma del componente, ad esempio "0805" per i resistori SMD.
Non viene trasferito nel record del componente. + + + Quantity + Campo obbligatorio + Numero intero + Il numero dei componenti identici necessari per creare un'istanza.
Registrato come il numero della voce del componente. + + + Designation + Campo obbligatorio + Stringa + Descrizione o funzione del componente, ad esempio valore del resistore "10kΩ" o valore del condensatore "100nF".
Viene trasferita nel nome del record del componente. + + + Supplier and ref + Opzionale + Stringa + Valore libero. Può contenere ad esempio un valore specifico del distributore.
Viene trasferito come nota nel record del componente. + + + + ]]> +
+
+
project.bom_import.clear_existing_bom.help @@ -12346,6 +12749,671 @@ Notare che non è possibile impersonare un utente disattivato. Quando si prova a Visualizza la versione esterna + + + assembly.label + Assemblaggio + + + + + assembly.caption + Assemblaggio + + + + + perm.assemblies + Assemblaggi + + + + + assembly_bom_entry.label + Componenti + + + + + assembly.labelp + Assemblaggi + + + + + assembly.referencedAssembly.labelp + Assembly referenziati + + + + + assembly.edit + Modifica assemblaggio + + + + + assembly.new + Nuovo assemblaggio + + + + + assembly.edit.bom.import_bom + Importa componenti + + + + + log.database_updated.failed + __log.database_updated.failed + + + + + log.database_updated.old_version + __log.database_updated.old_version + + + + + log.database_updated.new_version + __log.database_updated.new_version + + + + + tree.tools.edit.assemblies + Assemblaggi + + + + + assembly.bom_import.flash.success + %count% componente(i) importato(i) correttamente nell'assemblaggio. + + + + + assembly.bom_import.flash.invalid_entries + Errore di convalida! Controlla il file importato! + + + + + assembly.bom_import.flash.invalid_file + Impossibile importare il file. Assicurati di aver selezionato il tipo di file corretto. Messaggio di errore: %message% + + + + + assembly.bom.quantity + Quantità + + + + + assembly.bom.mountnames + Nomi di montaggio + + + + + assembly.bom.designator + Designatore di riferimento + + + + + assembly.bom.designator.help + Identificatori di riferimento liberi (designator) + + + + + assembly.bom.instockAmount + Quantità in magazzino + + + + + assembly.info.title + Informazioni sul gruppo + + + + + assembly.info.info.label + Info + + + + + assembly.info.sub_assemblies.label + Sotto-gruppi + + + + + assembly.info.builds.label + Costruzioni + + + + + assembly.info.bom_add_parts + Aggiungi componenti + + + + + assembly.info.bom_entries_count + Componenti + + + + + assembly.info.sub_assemblies_count + Sotto-gruppi + + + + + assembly.bom.delete.confirm + Vuoi davvero eliminare questa voce? + + + + + assembly.add_parts_to_assembly + Aggiungi componenti al gruppo + + + + + part.info.add_part_to_assembly + Aggiungi questa parte a un assemblaggio + + + + + assembly.bom.project + Progetto + + + + + assembly.bom.referencedAssembly + Assemblaggio + + + + + assembly.bom.name + Nome + + + + + assembly.bom.name.help + Titolo leggibile dall'utente della voce della distinta base + + + + + assembly.bom.comment + Commenti + + + + + assembly.import_bom + Importa componenti per il gruppo + + + + + assembly.bom.partOrAssembly + Parte o assieme + + + + + assembly.bom.identifiers + Identificatori + + + + + assembly.bom.add_entry + Aggiungi voce + + + + + assembly.bom.price + Prezzo + + + + + assembly.bom_import.type + Tipo + + + + + assembly.bom_import.type.json + JSON per un gruppo + + + + + assembly.bom_import.type.csv + CSV per un'assemblaggio + + + + + assembly.bom_import.type.kicad_pcbnew + CSV (KiCAD Pcbnew) + + + + + assembly.bom_import.type.kicad_schematic + KiCAD Editor Schematico BOM (file CSV) + + + + + assembly.bom_import.clear_existing_bom + Elimina i componenti esistenti prima di importare + + + + + assembly.bom_import.clear_existing_bom.help + Se abilitata, tutti i componenti esistenti verranno rimossi e sostituiti dai dati importati. + + + + + assembly.import_bom.template.header.json + Template di importazione JSON per un gruppo + + + + + assembly.import_bom.template.header.csv + Modello di importazione CSV per un assemblaggio + + + + + assembly.import_bom.template.header.kicad_pcbnew + Template di importazione CSV (KiCAD Pcbnew BOM) per un gruppo + + + + + assembly.bom_import.template.entry.name + Nome del componente nel gruppo + + + + + assembly.bom_import.template.entry.part.mpnr + Numero univoco del componente del produttore + + + + + assembly.bom_import.template.entry.part.ipn + IPN univoco del componente + + + + + assembly.bom_import.template.entry.part.name + Nome univoco del componente + + + + + assembly.bom_import.template.entry.part.manufacturer.name + Nome univoco del produttore + + + + + assembly.bom_import.template.entry.part.category.name + Nome univoco della categoria + + + + + assembly.bom_import.template.json.table + + + + + Campo + Condizione + Tipo di dati + Descrizione + + + + + quantity + Campo obbligatorio + Numero decimale (Float) + Deve essere compilato e contenere un valore decimale (Float) maggiore di 0.0. + + + name + Opzionale + Stringa + Se specificato, deve essere una stringa non vuota. Il nome del componente all'interno dell'assemblaggio. + + + part + Opzionale + Oggetto/Array + + Se è necessario assegnare una parte, deve essere un Oggetto/Array e almeno uno dei seguenti campi deve essere compilato: +
    +
  • part.id
  • +
  • part.mpnr
  • +
  • part.ipn
  • +
  • part.name
  • +
+ + + + part.id + Opzionale + Numero intero + Numero intero > 0. Corrisponde all'ID interno numerico del componente nel database. + + + part.mpnr + Opzionale + Stringa + Stringa non vuota se i campi part.id, part.ipn o part.name non sono compilati. + + + part.ipn + Opzionale + Stringa + Stringa non vuota se i campi part.id, part.mpnr o part.name non sono compilati. + + + part.name + Opzionale + Stringa + Stringa non vuota se i campi part.id, part.mpnr o part.ipn non sono compilati. + + + part.description + Opzionale + Stringa o null + Se specificato, deve essere una stringa non vuota o null. Questo valore sovrascriverà quello esistente nella parte. + + + part.manufacturer + Opzionale + Oggetto/Array + + Se il produttore della parte deve essere cambiato o ricercato esclusivamente utilizzando il valore part.mpnr, deve essere un Oggetto/Array e almeno uno dei seguenti campi deve essere compilato: +
    +
  • manufacturer.id
  • +
  • manufacturer.name
  • +
+ + + + manufacturer.id + Opzionale + Numero intero + Numero intero > 0. Corrisponde all'ID interno numerico del produttore. + + + manufacturer.name + Opzionale + Stringa + Stringa non vuota se il campo manufacturer.id non è compilato. + + + part.category + Opzionale + Oggetto/Array + + Se è necessario modificare la categoria della parte, deve essere un Oggetto/Array e almeno uno dei seguenti campi deve essere compilato: +
    +
  • category.id
  • +
  • category.name
  • +
+ + + + category.id + Opzionale + Numero intero + Numero intero > 0. Corrisponde all'ID interno numerico della categoria della parte. + + + category.name + Opzionale + Stringa + Stringa non vuota se il campo category.id non è compilato. + + + + ]]> +
+
+
+ + + assembly.bom_import.template.csv.exptected_columns + Colonne possibili: + + + + + assembly.bom_import.template.csv.table + + + + + Colonna + Condizione + Tipo di dati + Descrizione + + + + + quantity + Campo obbligatorio + Numero decimale (Float) + Deve essere compilato e contenere un valore decimale (Float) maggiore di 0.0. + + + name + Opzionale + Stringa + Il nome dell'elemento all'interno dell'assemblaggio. + + + Colonne che iniziano con part_ + + Se è necessario assegnare una parte, almeno una delle colonne seguenti deve essere compilata: +
    +
  • part_id
  • +
  • part_mpnr
  • +
  • part_ipn
  • +
  • part_name
  • +
+ + + + part_id + Opzionale + Numero intero + Numero intero > 0. Corrisponde all'ID interno numerico del componente nel database. + + + part_mpnr + Opzionale + Stringa + Deve essere compilato se le colonne part_id, part_ipn o part_name non sono compilate. + + + part_ipn + Opzionale + Stringa + Deve essere compilato se le colonne part_id, part_mpnr o part_name non sono compilate. + + + part_name + Opzionale + Stringa + Deve essere compilato se le colonne part_id, part_mpnr o part_ipn non sono compilate. + + + part_description + Opzionale + Stringa + Sarà trasferita e sostituirà il valore esistente della descrizione se viene fornita una stringa non vuota. + + + Colonne che iniziano con part_manufacturer_ + + Se il produttore del componente deve essere modificato o ricercato esclusivamente tramite part_mpnr, almeno una delle seguenti colonne deve essere compilata: +
    +
  • part_manufacturer_id
  • +
  • part_manufacturer_name
  • +
+ + + + part_manufacturer_id + Opzionale + Numero intero + Numero intero > 0. Corrisponde all'ID interno numerico del produttore. + + + part_manufacturer_name + Opzionale + Stringa + Deve essere compilata se il campo part_manufacturer_id non è fornito. + + + Colonne che iniziano con part_category_ + + Se è necessario modificare la categoria della parte, almeno una delle seguenti colonne deve essere compilata: +
    +
  • part_category_id
  • +
  • part_category_name
  • +
+ + + + part_category_id + Opzionale + Numero intero + Numero intero > 0. Corrisponde all'ID interno numerico della categoria del componente. + + + part_category_name + Opzionale + Stringa + Deve essere compilata se il campo part_category_id non è fornito. + + + + ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.exptected_columns + Colonne previste: + + + + + assembly.bom_import.template.kicad_pcbnew.exptected_columns.note + + Nota: Non viene eseguita alcuna mappatura con componenti specifici dalla gestione delle categorie.

+ ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.table + + + + + Campo + Condizione + Tipo di Dati + Descrizione + + + + + Id + Opzionale + Intero + Campo libero. Un numero identificativo univoco per ogni componente. + + + Designator + Opzionale + Stringa + Campo libero. Un riferimento univoco al componente su PCB, ad esempio "R1" per il resistore 1.
Utilizzato come nome della posizione nella voce componenti all'interno dell'assemblaggio. + + + Package + Opzionale + Stringa + Campo libero. L'involucro o il fattore di forma del componente, ad esempio "0805" per i resistori SMD.
Non incluso nelle informazioni del componente nell'assemblaggio. + + + Quantity + Obbligatorio + Intero + Il numero di componenti identici richiesti per creare un'istanza dell'assemblaggio.
Utilizzato come quantità nella voce componenti dell'assemblaggio. + + + Designation + Obbligatorio + Stringa + Descrizione o funzione del componente, ad esempio valore resistore "10kΩ" o valore condensatore "100nF".
Utilizzato come nome nella voce componenti dell'assemblaggio. + + + Supplier and ref + Opzionale + Stringa + Campo libero. Può contenere, ad esempio, informazioni specifiche del fornitore.
Utilizzato come nota nelle informazioni del componente nell'assemblaggio. + + + + ]]> +
+
+
part.table.actions.error @@ -12370,5 +13438,221 @@ Notare che non è possibile impersonare un utente disattivato. Quando si prova a Questo componente contiene più di uno stock. Cambia manualmente la posizione per selezionare quale stock scegliere. + + + assembly_list.all.title + Tutti gli assiemi + + + + + assembly.edit.tab.common + Generale + + + + + assembly.edit.tab.advanced + Opzioni avanzate + + + + + assembly.edit.tab.attachments + Allegati + + + + + assembly.filter.dbId + ID del database + + + + + assembly.filter.ipn + Numero interno di parte (IPN) + + + + + assembly.filter.name + Nome + + + + + assembly.filter.description + Descrizione + + + + + assembly.filter.comment + Commenti + + + + + assembly.filter.attachments_count + Numero di allegati + + + + + assembly.filter.attachmentName + Nome dell'allegato + + + + + assemblies.create.btn + Crea un nuovo assieme + + + + + assembly.table.id + ID + + + + + assembly.table.name + Nome + + + + + assembly.table.ipn + IPN + + + + + assembly.table.description + Descrizione + + + + + assembly.table.referencedAssemblies + Assiemi referenziati + + + + + assembly.table.addedDate + Aggiunto + + + + + assembly.table.lastModified + Ultima modifica + + + + + assembly.table.edit + Modifica + + + + + assembly.table.edit.title + Modifica l'assieme + + + + + assembly.table.invalid_regex + Espressione regolare non valida (regex) + + + + + assembly.bom.table.id + ID + + + + + assembly.bom.table.name + Nome + + + + + assembly.bom.table.quantity + Quantità + + + + + assembly.bom.table.ipn + IPN + + + + + assembly.bom.table.description + Descrizione + + + + + assembly.bom.table.category + Categoria + + + + + assembly.bom.table.manufacturer + Produttore + + + + + assembly.bom.table.designator + Designatore di riferimento + + + + + assembly.bom.table.mountnames + Nomi di montaggio + + + + + assembly.bom.table.storage_location + Ubicazione di magazzino + + + + + assembly.bom.table.amount + Quantità + + + + + assembly.bom.table.addedDate + Creato il + + + + + assembly.bom.table.lastModified + Ultima modifica + + + + + assembly.bom.table.edit + Modifica + + diff --git a/translations/messages.ja.xlf b/translations/messages.ja.xlf index 4becc319c..cf1cca2dc 100644 --- a/translations/messages.ja.xlf +++ b/translations/messages.ja.xlf @@ -320,6 +320,24 @@ すべてエクスポートする + + + export.readable.label + 読みやすいエクスポート + + + + + export.readable + CSV + + + + + export.readable_bom + PDF + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:185 @@ -4703,6 +4721,24 @@ 名称 + + + part.table.name.value.for_part + %value%(部品) + + + + + part.table.name.value.for_assembly + %value%(アセンブリ) + + + + + part.table.name.value.for_project + %value%(プロジェクト) + + Part-DB1\src\DataTables\PartsDataTable.php:178 @@ -8834,5 +8870,916 @@ Exampletown Part-DBについての質問は、<a href="%href%" class="link-external" target="_blank">GitHub</a> にスレッドがあります。 + + + assembly.edit.status + アセンブリのステータス + + + + + assembly.status.draft + 下書き + + + + + assembly.status.planning + 計画中 + + + + + assembly.status.in_production + 製作中 + + + + + assembly.status.finished + 完成 + + + + + assembly.status.archived + アーカイブ済み + + + + + assembly.label + アセンブリ + + + + + assembly.caption + アセンブリ + + + + + perm.assemblies + アセンブリ一覧 + + + + + assembly_bom_entry.label + コンポーネント + + + + + assembly.labelp + アセンブリ一覧 + + + + + assembly.referencedAssembly.labelp + 参照されたアセンブリ + + + + + assembly.edit + アセンブリを編集 + + + + + assembly.new + 新しいアセンブリ + + + + + assembly.edit.bom.import_bom + コンポーネントをインポート + + + + + log.database_updated.failed + __log.database_updated.failed + + + + + log.database_updated.old_version + __log.database_updated.old_version + + + + + log.database_updated.new_version + __log.database_updated.new_version + + + + + tree.tools.edit.assemblies + アセンブリ一覧 + + + + + assembly.bom_import.flash.success + %count% 個のコンポーネントが正常にアセンブリへインポートされました。 + + + + + assembly.bom_import.flash.invalid_entries + 検証エラー! インポートしたファイルを確認してください! + + + + + assembly.bom_import.flash.invalid_file + ファイルをインポートできませんでした。正しいファイル形式を選択しているか確認してください。エラーメッセージ: %message% + + + + + assembly.bom.quantity + 数量 + + + + + assembly.bom.mountnames + 取り付け名 + + + + + assembly.bom.designator + 参照記号 + + + + + assembly.bom.designator.help + 自由な参照記号(デジグネータ) + + + + + assembly.bom.instockAmount + 在庫数量 + + + + + assembly.info.title + アセンブリ情報 + + + + + assembly.info.info.label + 情報 + + + + + assembly.info.sub_assemblies.label + サブアセンブリ + + + + + assembly.info.builds.label + ビルド + + + + + assembly.info.bom_add_parts + 部品を追加 + + + + + assembly.info.bom_entries_count + 部品 + + + + + assembly.info.sub_assemblies_count + サブアセンブリ + + + + + assembly.bom.delete.confirm + 本当にこのエントリを削除しますか? + + + + + assembly.add_parts_to_assembly + アセンブリに部品を追加 + + + + + part.info.add_part_to_assembly + このパーツをアセンブリに追加 + + + + + assembly.bom.project + プロジェクト + + + + + assembly.bom.referencedAssembly + アセンブリ + + + + + assembly.bom.name + 名前 + + + + + assembly.bom.name.help + BOM エントリの人間が読めるタイトル + + + + + assembly.bom.comment + コメント + + + + + assembly.import_bom + アセンブリの部品表をインポート + + + + + assembly.bom.partOrAssembly + 部品またはアセンブリ + + + + + assembly.bom.identifiers + 識別子 + + + + + assembly.confirmation.required + + + + + + assembly.bom_import.type + タイプ + + + + + assembly.bom_import.type.json + アセンブリ用 JSON + + + + + assembly.bom_import.type.csv + アセンブリ用のCSV + + + + + assembly.bom_import.type.kicad_pcbnew + CSV (KiCAD Pcbnew) + + + + + assembly.bom_import.type.kicad_schematic + KiCAD 回路図エディタ BOM (CSV ファイル) + + + + + assembly.bom_import.clear_existing_bom + インポート前に既存の BOM をクリアする + + + + + assembly.bom_import.clear_existing_bom.help + 有効にすると、既存のすべての BOM エントリが削除され、インポートされたデータに置き換えられます。 + + + + + assembly.import_bom.template.header.json + アセンブリ用 JSON テンプレート + + + + + assembly.import_bom.template.header.csv + アセンブリ用のCSVインポートテンプレート + + + + + assembly.import_bom.template.header.kicad_pcbnew + アセンブリ用 CSV テンプレート(KiCAD Pcbnew BOM) + + + + + assembly.bom_import.template.entry.name + アセンブリ内の部品名 + + + + + assembly.bom_import.template.entry.part.mpnr + メーカーの部品番号 + + + + + assembly.bom_import.template.entry.part.ipn + 部品の一意の IPN + + + + + assembly.bom_import.template.entry.part.name + 部品名 + + + + + assembly.bom_import.template.entry.part.manufacturer.name + メーカー名 + + + + + assembly.bom_import.template.entry.part.category.name + カテゴリ名 + + + + + assembly.bom_import.template.json.table + + + + + フィールド + 条件 + データ型 + 説明 + + + + + quantity + 必須項目 + 浮動小数点数 (Float) + 入力必須で、0.0よりも大きい浮動小数点数 (Float) を含む必要があります。 + + + name + 任意 + 文字列 + 指定されている場合、空でない文字列でなければなりません。アセンブリ内のアイテムの名前。 + + + part + 任意 + オブジェクト/配列 + + 部品を割り当てる必要がある場合、これはオブジェクト/配列であり、次のフィールドのいずれかを少なくとも1つ入力する必要があります: +
    +
  • part.id
  • +
  • part.mpnr
  • +
  • part.ipn
  • +
  • part.name
  • +
+ + + + part.id + 任意 + 整数 (Integer) + 0より大きい整数。データベース内の部品の内部数値IDに対応します。 + + + part.mpnr + 任意 + 文字列 + part.id、part.ipn、または part.name が入力されていない場合、空でない文字列。 + + + part.ipn + 任意 + 文字列 + part.id、part.mpnr、または part.name が入力されていない場合、空でない文字列。 + + + part.name + 任意 + 文字列 + part.id、part.mpnr、または part.ipn が入力されていない場合、空でない文字列。 + + + part.description + 任意 + 文字列または null + 指定されている場合、空でない文字列または null である必要があります。この値は部品の既存の値を上書きします。 + + + part.manufacturer + 任意 + オブジェクト/配列 + + 部品のメーカーを変更する場合、または part.mpnr の値を利用して一意に検索する場合、これはオブジェクト/配列であり、次のフィールドのいずれかを少なくとも1つ入力する必要があります: +
    +
  • manufacturer.id
  • +
  • manufacturer.name
  • +
+ + + + manufacturer.id + 任意 + 整数 (Integer) + 0より大きい整数。メーカーの内部数値IDに対応します。 + + + manufacturer.name + 任意 + 文字列 + manufacturer.id が提供されていない場合、空でない文字列。 + + + part.category + 任意 + オブジェクト/配列 + + 部品のカテゴリーを変更する場合、これはオブジェクト/配列であり、次のフィールドのいずれかを少なくとも1つ入力する必要があります: +
    +
  • category.id
  • +
  • category.name
  • +
+ + + + category.id + 任意 + 整数 (Integer) + 0より大きい整数。部品のカテゴリーに対応する内部数値ID。 + + + category.name + 任意 + 文字列 + category.id が提供されていない場合、空でない文字列。 + + + + ]]> +
+
+
+ + + assembly.bom_import.template.csv.exptected_columns + 可能なカラム: + + + + + assembly.bom_import.template.csv.table + + + + + カラム + 条件 + データ型 + 説明 + + + + + quantity + 必須項目 + 浮動小数点数 (Float) + 入力必須で、0.0よりも大きい浮動小数点数 (Float) を含む必要があります。 + + + name + 任意 + 文字列 + アセンブリ内のアイテムの名前。 + + + part_ で始まるカラム + + 部品を割り当てる必要がある場合、次のカラムのいずれかが少なくとも1つ入力されなければなりません: +
    +
  • part_id
  • +
  • part_mpnr
  • +
  • part_ipn
  • +
  • part_name
  • +
+ + + + part_id + 任意 + 整数 (Integer) + 0より大きい整数。データベース内の部品の内部数値ID。 + + + part_mpnr + 任意 + 文字列 + part_id、part_ipn、または part_name が入力されていない場合に入力される必要があります。 + + + part_ipn + 任意 + 文字列 + part_id、part_mpnr、または part_name が入力されていない場合に入力される必要があります。 + + + part_name + 任意 + 文字列 + part_id、part_mpnr、または part_ipn が入力されていない場合に入力される必要があります。 + + + part_description + 任意 + 文字列 + 指定されている場合、部品の説明既存の値を上書きする非空の文字列。 + + + part_manufacturer_ で始まるカラム + + 部品の製造元を変更する場合、または part_mpnr を利用して一意に検索する場合、次のカラムのいずれかを少なくとも1つ入力する必要があります: +
    +
  • part_manufacturer_id
  • +
  • part_manufacturer_name
  • +
+ + + + part_manufacturer_id + 任意 + 整数 (Integer) + 0より大きい整数。製造元の内部数値ID。 + + + part_manufacturer_name + 任意 + 文字列 + part_manufacturer_id が入力されていない場合、入力される必要があります。 + + + part_category_ で始まるカラム + + 部品のカテゴリーを変更する場合、次のカラムのいずれかを少なくとも1つ入力する必要があります: +
    +
  • part_category_id
  • +
  • part_category_name
  • +
+ + + + part_category_id + 任意 + 整数 (Integer) + 0より大きい整数。部品のカテゴリーに対応する内部数値ID。 + + + part_category_name + 任意 + 文字列 + part_category_id が提供されていない場合、入力される必要があります。 + + + + ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.exptected_columns + 予想される列: + + + + + assembly.bom_import.template.kicad_pcbnew.exptected_columns.note + + 注意: カテゴリ管理から特定のコンポーネントへのマッピングは行われません。

+ ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.table + + + + + フィールド + 条件 + データ型 + 説明 + + + + + Id + 任意 + 整数 + 自由形式のフィールド。各コンポーネントのユニークな識別番号。 + + + Designator + 任意 + 文字列 + 自由形式のフィールド。PCB上のコンポーネントごとの一意のリファレンス識別子。例: 抵抗 "R1"。
アセンブリ内の部品エントリの配置名として使用。 + + + Package + 任意 + 文字列 + 自由形式のフィールド。コンポーネントのパッケージまたはフォームファクタ。例: 表面実装抵抗器 "0805"。
アセンブリ内の部品エントリ情報には含まれません。 + + + Quantity + 必須 + 整数 + アセンブリの一つのインスタンスを作るために必要な同一部品の数。
アセンブリの部品情報で数量として使用。 + + + Designation + 必須 + 文字列 + コンポーネントの説明や機能。例: 抵抗の値 "10kΩ" やコンデンサの値 "100nF"。
アセンブリの部品情報で名称として使用。 + + + Supplier and ref + 任意 + 文字列 + 自由形式フィールド。例: 供給元に関する特定の情報を含む場合がある。
アセンブリの部品情報の注記として使用。 + + + + ]]> +
+
+
+ + + assembly_list.all.title + すべてのアセンブリ + + + + + assembly.edit.tab.common + 一般 + + + + + assembly.edit.tab.advanced + 詳細オプション + + + + + assembly.edit.tab.attachments + 添付ファイル + + + + + assembly.filter.dbId + データベースID + + + + + assembly.filter.ipn + 内部部品番号(IPN) + + + + + assembly.filter.name + 名前 + + + + + assembly.filter.description + 説明 + + + + + assembly.filter.comment + コメント + + + + + assembly.filter.attachments_count + 添付ファイルの数 + + + + + assembly.filter.attachmentName + 添付ファイル名 + + + + + assemblies.create.btn + 新しいアセンブリを作成 + + + + + assembly.table.id + ID + + + + + assembly.table.name + 名前 + + + + + assembly.table.ipn + IPN + + + + + assembly.table.description + 説明 + + + + + assembly.table.referencedAssemblies + 参照されているアセンブリ + + + + + assembly.table.addedDate + 追加日 + + + + + assembly.table.lastModified + 最終変更 + + + + + assembly.table.edit + 編集 + + + + + assembly.table.edit.title + アセンブリを編集 + + + + + assembly.table.invalid_regex + 無効な正規表現(regex) + + + + + assembly.bom.table.id + ID + + + + + assembly.bom.table.name + 名前 + + + + + assembly.bom.table.quantity + 数量 + + + + + assembly.bom.table.ipn + IPN + + + + + assembly.bom.table.description + 説明 + + + + + assembly.bom.table.category + カテゴリ + + + + + assembly.bom.table.manufacturer + メーカー + + + + + assembly.bom.table.designator + 参照記号 + + + + + assembly.bom.table.mountnames + 実装名 + + + + + assembly.bom.table.storage_location + 保管場所 + + + + + assembly.bom.table.amount + 数量 + + + + + assembly.bom.table.addedDate + 作成日 + + + + + assembly.bom.table.lastModified + 最終更新 + + + + + assembly.bom.table.edit + 編集 + + diff --git a/translations/messages.nl.xlf b/translations/messages.nl.xlf index 760533d7c..170e4295d 100644 --- a/translations/messages.nl.xlf +++ b/translations/messages.nl.xlf @@ -351,6 +351,24 @@ Exporteer alle elementen + + + export.readable.label + Leesbare export + + + + + export.readable + CSV + + + + + export.readable_bom + PDF + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:185 @@ -724,5 +742,946 @@ Weet u zeker dat u wilt doorgaan? + + + part.table.name.value.for_part + %value% (Onderdeel) + + + + + part.table.name.value.for_assembly + %value% (Assemblage) + + + + + part.table.name.value.for_project + %value% (Project) + + + + + assembly.edit.status + Montagestatus + + + + + assembly.status.draft + Προσχέδιο + + + + + assembly.status.planning + Υπό σχεδιασμό + + + + + assembly.status.in_production + Σε παραγωγή + + + + + assembly.status.finished + Ολοκληρώθηκε + + + + + assembly.status.archived + Αρχειοθετήθηκε + + + + + assembly.label + Assemblage + + + + + assembly.caption + Assemblage + + + + + perm.assemblies + Assemblages + + + + + assembly_bom_entry.label + Componenten + + + + + assembly.labelp + Assemblages + + + + + assembly.referencedAssembly.labelp + Gerefereerde assemblages + + + + + assembly.edit + Assemblage bewerken + + + + + assembly.new + Nieuwe assemblage + + + + + assembly.edit.bom.import_bom + Componenten importeren + + + + + log.database_updated.failed + __log.database_updated.failed + + + + + log.database_updated.old_version + __log.database_updated.old_version + + + + + log.database_updated.new_version + __log.database_updated.new_version + + + + + tree.tools.edit.assemblies + Assemblages + + + + + assembly.bom_import.flash.success + %count% component(en) zijn succesvol geïmporteerd in de assemblage. + + + + + assembly.bom_import.flash.invalid_entries + Validatiefout! Controleer het geïmporteerde bestand! + + + + + assembly.bom_import.flash.invalid_file + Het bestand kon niet worden geïmporteerd. Controleer of je het correcte bestandstype hebt geselecteerd. Foutmelding: %message% + + + + + assembly.bom.quantity + Aantal + + + + + assembly.bom.mountnames + Montagenamen + + + + + assembly.bom.designator + Referentieaanduiding + + + + + assembly.bom.designator.help + Vrije referentieaanduidingen (designator) + + + + + assembly.bom.instockAmount + Beschikbaar in voorraad + + + + + assembly.info.title + Assemblage-informatie + + + + + assembly.info.info.label + Informatie + + + + + assembly.info.sub_assemblies.label + Subassemblages + + + + + assembly.info.builds.label + Bouw + + + + + assembly.info.bom_add_parts + Onderdelen toevoegen + + + + + assembly.info.bom_entries_count + Onderdelen + + + + + assembly.info.sub_assemblies_count + Subgroepen + + + + + assembly.bom.delete.confirm + Weet u zeker dat u dit item wilt verwijderen? + + + + + assembly.add_parts_to_assembly + Onderdelen toevoegen aan assemblage + + + + + part.info.add_part_to_assembly + Dit onderdeel aan een assemblage toevoegen + + + + + assembly.bom.project + Project + + + + + assembly.bom.referencedAssembly + Assemblage + + + + + assembly.bom.name + Naam + + + + + assembly.bom.name.help + Menselijk leesbare titel van de stuklijstinvoer + + + + + assembly.bom.comment + Notities + + + + + assembly.import_bom + Importeer onderdelen voor assemblage + + + + + assembly.bom.partOrAssembly + Onderdeel of samenstelling + + + + + assembly.bom.identifiers + Identificatoren + + + + + assembly.bom.add_entry + Voer item in + + + + + assembly.bom.price + Prijs + + + + + assembly.confirmation.required + + + + + + assembly.bom_import.type + Type + + + + + assembly.bom_import.type.json + JSON voor assemblage + + + + + assembly.bom_import.type.csv + CSV voor een assemblage + + + + + assembly.bom_import.type.kicad_pcbnew + CSV (KiCAD Pcbnew) + + + + + assembly.bom_import.type.kicad_schematic + KiCAD Schematische editor BOM (CSV-bestand) + + + + + assembly.bom_import.clear_existing_bom + Bestaande BOM wissen vóór importeren + + + + + assembly.bom_import.clear_existing_bom.help + Wanneer dit is ingeschakeld, worden alle bestaande BOM-items verwijderd en vervangen door de geïmporteerde gegevens. + + + + + assembly.import_bom.template.header.json + JSON-sjabloon voor assemblage + + + + + assembly.import_bom.template.header.csv + CSV-importsjabloon voor een assemblage + + + + + assembly.import_bom.template.header.kicad_pcbnew + CSV-sjabloon voor assemblage (KiCAD Pcbnew BOM) + + + + + assembly.bom_import.template.entry.name + Naam van onderdeel in de assemblage + + + + + assembly.bom_import.template.entry.part.mpnr + Onderdeelnummer van de fabrikant + + + + + assembly.bom_import.template.entry.part.ipn + Unieke IPN van het onderdeel + + + + + assembly.bom_import.template.entry.part.name + Unieke naam van het onderdeel + + + + + assembly.bom_import.template.entry.part.manufacturer.name + Unieke naam van de fabrikant + + + + + assembly.bom_import.template.entry.part.category.name + Unieke naam van de categorie + + + + + assembly.bom_import.template.json.table + + + + + Veld + Voorwaarde + Gegevenstype + Beschrijving + + + + + quantity + Verplicht veld + Kommagetal (Float) + Moet worden ingevuld en een kommagetal (Float) bevatten dat groter is dan 0,0. + + + name + Optioneel + Tekst + Wanneer ingevuld, moet het een niet-lege tekst zijn. De naam van het item binnen de assemblage. + + + part + Optioneel + Object/Array + + Als een onderdeel moet worden toegewezen, moet dit een object/array zijn en moet ten minste één van de volgende velden worden ingevuld: +
    +
  • part.id
  • +
  • part.mpnr
  • +
  • part.ipn
  • +
  • part.name
  • +
+ + + + part.id + Optioneel + Hele getal + Een geheel getal > 0. Komt overeen met de interne numerieke ID van het onderdeel in de database. + + + part.mpnr + Optioneel + Tekst + Niet-lege tekst, wanneer part.id, part.ipn of part.name niet zijn ingevuld. + + + part.ipn + Optioneel + Tekst + Niet-lege tekst wanneer part.id, part.mpnr of part.name niet zijn ingevuld. + + + part.name + Optioneel + Tekst + Niet-lege tekst, wanneer part.id, part.mpnr of part.ipn niet zijn ingevuld. + + + part.description + Optioneel + Tekst of null + Indien ingevuld, moet het een niet-lege tekst of null zijn. Deze waarde vervangt de bestaande waarde in het onderdeel. + + + part.manufacturer + Optioneel + Object/Array + + Als de fabrikant van het onderdeel moet worden gewijzigd of uniek moet worden opgezocht met de waarde part.mpnr, moet dit een object/array zijn en moet ten minste één van de volgende velden worden ingevuld: +
    +
  • manufacturer.id
  • +
  • manufacturer.name
  • +
+ + + + manufacturer.id + Optioneel + Hele getal + Een geheel getal > 0. Komt overeen met de interne numerieke ID van de fabrikant. + + + manufacturer.name + Optioneel + Tekst + Niet-lege tekst als manufacturer.id niet is ingevuld. + + + part.category + Optioneel + Object/Array + + Als de categorie van het onderdeel moet worden gewijzigd, moet dit een object/array zijn en moet ten minste één van de volgende velden worden ingevuld: +
    +
  • category.id
  • +
  • category.name
  • +
+ + + + category.id + Optioneel + Hele getal + Een geheel getal > 0. Komt overeen met de interne numerieke ID van de categorie van het onderdeel. + + + category.name + Optioneel + Tekst + Niet-lege tekst als category.id niet is ingevuld. + + + + ]]> +
+
+
+ + + assembly.bom_import.template.csv.exptected_columns + Mogelijke kolommen: + + + + + assembly.bom_import.template.csv.table + + + + + Kolom + Voorwaarde + Gegevenstype + Beschrijving + + + + + quantity + Verplicht veld + Kommagetal (Float) + Moet worden ingevuld en moet een kommagetal (Float) bevatten dat groter is dan 0,0. + + + name + Optioneel + Tekst + De naam van het item binnen de assemblage. + + + Kolommen die beginnen met part_ + + Als een onderdeel moet worden toegewezen, moet ten minste één van de volgende kolommen worden ingevuld: +
    +
  • part_id
  • +
  • part_mpnr
  • +
  • part_ipn
  • +
  • part_name
  • +
+ + + + part_id + Optioneel + Hele getal + Een geheel getal > 0. Komt overeen met de interne numerieke ID van het onderdeel in de database. + + + part_mpnr + Optioneel + Tekst + Moet worden ingevuld als part_id, part_ipn of part_name niet zijn ingevuld. + + + part_ipn + Optioneel + Tekst + Moet worden ingevuld als part_id, part_mpnr of part_name niet zijn ingevuld. + + + part_name + Optioneel + Tekst + Moet worden ingevuld als part_id, part_mpnr of part_ipn niet zijn ingevuld. + + + part_description + Optioneel + Tekst + Wordt overgenomen en vervangt de bestaande waarde van de beschrijving als er een niet-lege tekst wordt opgegeven. + + + Kolommen die beginnen met part_manufacturer_ + + Als de fabrikant van een onderdeel moet worden gewijzigd of uniek moet worden gezocht via part_mpnr, moet ten minste één van de volgende kolommen worden ingevuld: +
    +
  • part_manufacturer_id
  • +
  • part_manufacturer_name
  • +
+ + + + part_manufacturer_id + Optioneel + Hele getal + Een geheel getal > 0. Komt overeen met de interne numerieke ID van de fabrikant. + + + part_manufacturer_name + Optioneel + Tekst + Moet worden ingevuld als part_manufacturer_id niet wordt opgegeven. + + + Kolommen die beginnen met part_category_ + + Als de categorie van een onderdeel moet worden gewijzigd, moet ten minste één van de volgende kolommen worden ingevuld: +
    +
  • part_category_id
  • +
  • part_category_name
  • +
+ + + + part_category_id + Optioneel + Hele getal + Een geheel getal > 0. Komt overeen met de interne numerieke ID van de categorie van het onderdeel. + + + part_category_name + Optioneel + Tekst + Moet worden ingevuld als part_category_id niet wordt opgegeven. + + + + ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.exptected_columns + Verwachte kolommen: + + + + + assembly.bom_import.template.kicad_pcbnew.exptected_columns.note + + Opmerking: Er wordt geen mapping uitgevoerd met specifieke componenten uit de categoriebeheer.

+ ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.table + + + + + Veld + Voorwaarde + Gegevenstype + Beschrijving + + + + + Id + Optioneel + Integer + Vrij veld. Een unieke identificatienummer voor elk onderdeel. + + + Designator + Optioneel + String + Vrij veld. Een unieke referentienaam voor het onderdeel op de PCB, bijvoorbeeld "R1" voor weerstand 1.
Wordt gebruikt als positioneringsnaam in de onderdelenlijst van de assemblage. + + + Package + Optioneel + String + Vrij veld. De behuizing of vormfactor van het onderdeel, bijvoorbeeld "0805" voor SMD-weerstanden.
Wordt niet opgenomen in de onderdelenlijst binnen de assemblage. + + + Quantity + Vereist + Integer + Het aantal identieke onderdelen dat nodig is om een assemblage-instantie te creëren.
Wordt gebruikt als hoeveelheid in de onderdelenlijst binnen de assemblage. + + + Designation + Vereist + String + De beschrijving of functie van het onderdeel, zoals weerstandwaarde "10kΩ" of condensatorwaarde "100nF".
Wordt gebruikt als de naam in de onderdelenlijst binnen de assemblage. + + + Supplier and ref + Optioneel + String + Vrij veld. Kan bijvoorbeeld specifieke informatie over leveranciers bevatten.
Wordt gebruikt als notitie in de onderdelenlijst binnen de assemblage. + + + + ]]> +
+
+
+ + + assembly_list.all.title + Alle assemblages + + + + + assembly.edit.tab.common + Algemeen + + + + + assembly.edit.tab.advanced + Geavanceerde opties + + + + + assembly.edit.tab.attachments + Bijlagen + + + + + assembly.filter.dbId + Database-ID + + + + + assembly.filter.ipn + Intern partnummer (IPN) + + + + + assembly.filter.name + Naam + + + + + assembly.filter.description + Beschrijving + + + + + assembly.filter.comment + Opmerkingen + + + + + assembly.filter.attachments_count + Aantal bijlagen + + + + + assembly.filter.attachmentName + Naam van de bijlage + + + + + assemblies.create.btn + Nieuwe assemblage aanmaken + + + + + assembly.table.id + ID + + + + + assembly.table.name + Naam + + + + + assembly.table.ipn + IPN + + + + + assembly.table.description + Beschrijving + + + + + assembly.table.referencedAssemblies + Gerefereerde assemblages + + + + + assembly.table.addedDate + Toegevoegd + + + + + assembly.table.lastModified + Laatst gewijzigd + + + + + assembly.table.edit + Bewerken + + + + + assembly.table.edit.title + Assemblage bewerken + + + + + assembly.table.invalid_regex + Ongeldige reguliere expressie (regex) + + + + + assembly.bom.table.id + ID + + + + + assembly.bom.table.name + Naam + + + + + assembly.bom.table.quantity + Hoeveelheid + + + + + assembly.bom.table.ipn + IPN + + + + + assembly.bom.table.description + Beschrijving + + + + + assembly.bom.table.category + Categorie + + + + + assembly.bom.table.manufacturer + Fabrikant + + + + + assembly.bom.table.designator + Referentieaanduiding + + + + + assembly.bom.table.mountnames + Montagenamen + + + + + assembly.bom.table.storage_location + Opslaglocatie + + + + + assembly.bom.table.amount + Aantal + + + + + assembly.bom.table.addedDate + Aangemaakt op + + + + + assembly.bom.table.lastModified + Laatst gewijzigd + + + + + assembly.bom.table.edit + Bewerken + + diff --git a/translations/messages.pl.xlf b/translations/messages.pl.xlf index b769e2737..26d7af795 100644 --- a/translations/messages.pl.xlf +++ b/translations/messages.pl.xlf @@ -351,6 +351,24 @@ Eksportuj wszystkie elementy + + + export.readable.label + Eksport czytelny + + + + + export.readable + CSV + + + + + export.readable_bom + PDF + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:185 @@ -4745,6 +4763,24 @@ Jeśli zrobiłeś to niepoprawnie lub komputer nie jest już godny zaufania, mo Nazwa + + + part.table.name.value.for_part + %value%(部品) + + + + + part.table.name.value.for_assembly + %value% (Złożenie) + + + + + part.table.name.value.for_project + %value% (Projekt) + + Part-DB1\src\DataTables\PartsDataTable.php:178 @@ -9887,6 +9923,48 @@ Element 3 Zarchiwizowany + + + assembly.edit.status + Status montażu + + + + + assembly.edit.ipn + Internal Part Number (IPN) + + + + + assembly.status.draft + Wersja robocza + + + + + assembly.status.planning + W planowaniu + + + + + assembly.status.in_production + W produkcji + + + + + assembly.status.finished + Zakończony + + + + + assembly.status.archived + Zarchiwizowany + + part.new_build_part.error.build_part_already_exists @@ -11033,6 +11111,18 @@ Element 3 Typ + + + project.bom_import.type.json + JSON + + + + + project.bom_import.type.csv + CSV + + project.bom_import.type.kicad_pcbnew @@ -11045,6 +11135,319 @@ Element 3 Wyczyść istniejące wpisy BOM przed importem + + + project.import_bom.template.header.json + Szablon importu JSON + + + + + project.import_bom.template.header.csv + Szablon importu CSV + + + + + project.import_bom.template.header.kicad_pcbnew + Szablon importu CSV (KiCAD Pcbnew BOM) + + + + + project.bom_import.template.entry.name + Nazwa komponentu w projekcie + + + + + project.bom_import.template.entry.part.mpnr + Unikalny numer produktu producenta + + + + + project.bom_import.template.entry.part.ipn + Unikalny IPN komponentu + + + + + project.bom_import.template.entry.part.name + Unikalna nazwa komponentu + + + + + project.bom_import.template.entry.part.manufacturer.name + Unikalna nazwa producenta + + + + + project.bom_import.template.json.table + + + + + Pole + Warunek + Typ Danych + Opis + + + + + quantity + Wymagane + Dziesiętny (Float) + Musi być podane i zawierać wartość dziesiętną (Float) większą niż 0.0. + + + name + Opcjonalne + Ciąg (String) + Jeśli jest obecny, musi być niepustym ciągiem znaków. Nazwa elementu w wykazie materiałów. + + + part + Opcjonalne + Obiekt/Tablica + + Jeśli komponent musi być przypisany, musi być obiektem/tablą i co najmniej jedno z następujących pól musi zostać wypełnione: +
    +
  • part.id
  • +
  • part.mpnr
  • +
  • part.ipn
  • +
  • part.name
  • +
+ + + + part.id + Opcjonalne + Całkowity (Integer) + Całkowity (Integer) > 0. Odpowiada wewnętrznemu numerycznemu identyfikatorowi komponentu w bazie danych części (Part-DB). + + + part.mpnr + Opcjonalne + Ciag (String) + Niepusty ciąg, jeśli part.id, part.ipn ani part.name nie zostały podane. + + + part.ipn + Opcjonalne + Ciag (String) + Niepusty ciąg, jeśli part.id, part.mpnr ani part.name nie zostały podane. + + + part.name + Opcjonalne + Ciag (String) + Niepusty ciąg, jeśli part.id, part.mpnr ani part.ipn nie zostały podane. + + + part.manufacturer + Opcjonalne + Obiekt/Tablica + + Jeśli producent komponentu musi zostać dostosowany lub komponent musi zostać jednoznacznie zidentyfikowany na podstawie part.mpnr, musi być obiektem/tablą, a co najmniej jedno z następujących pól musi zostać wypełnione: +
    +
  • manufacturer.id
  • +
  • manufacturer.name
  • +
+ + + + manufacturer.id + Opcjonalne + Całkowity (Integer) + Całkowity (Integer) > 0. Odpowiada wewnętrznemu numerycznemu identyfikatorowi producenta. + + + manufacturer.name + Opcjonalne + Ciag (String) + Niepusty ciąg, jeśli manufacturer.id nie został podany. + + + + ]]> +
+
+
+ + + project.bom_import.template.csv.exptected_columns + Możliwe kolumny: + + + + + project.bom_import.template.csv.table + + + + + Kolumna + Warunek + Typ danych + Opis + + + + + quantity + Wymagana + Liczba zmiennoprzecinkowa (Float) + Liczba identycznych komponentów potrzebnych do utworzenia instancji.
Traktowane jako liczba wpisów komponentu. + + + name + Optional + String + Jeśli dostępny, musi być niepustym ciągiem znaków. Nazwa elementu w wykazie materiałów. + + + Kolumny zaczynające się od part_ + + Jeśli ma zostać przypisany komponent, co najmniej jedna z poniższych kolumn musi zostać podana i uzupełniona: +
    +
  • part_id
  • +
  • part_mpnr
  • +
  • part_ipn
  • +
  • part_name
  • +
+ + + + part_id + Opcjonalna + Liczba całkowita (Integer) + Liczba całkowita > 0. Odpowiada wewnętrznemu ID numerycznemu komponentu w Part-DB. + + + part_mpnr + Opcjonalna + Cišg znaków (String) + Musi być podana, jeśli kolumny part_id, part_ipn ani part_name nie są podane. + + + part_ipn + Opcjonalna + Cišg znaków (String) + Musi być podana, jeśli kolumny part_id, part_mpnr ani part_name nie są podane. + + + part_name + Opcjonalna + Cišg znaków (String) + Musi być podana, jeśli kolumny part_id, part_mpnr ani part_ipn nie są podane. + + + Kolumny zaczynające się od part_manufacturer_ + + Jeśli producent komponentu ma zostać zmieniony lub komponent ma zostać jednoznacznie zidentyfikowany na podstawie wartości part_mpnr, co najmniej jedna z poniższych kolumn musi zostać podana i uzupełniona: +
    +
  • part_manufacturer_id
  • +
  • part_manufacturer_name
  • +
+ + + + part_manufacturer_id + Opcjonalna + Liczba całkowita (Integer) + Liczba całkowita > 0. Odpowiada wewnętrznemu numerycznemu ID producenta. + + + part_manufacturer_name + Opcjonalna + Cišg znaków (String) + Musi być podana, jeśli kolumna part_manufacturer_id nie jest uzupełniona. + + + + ]]> +
+
+
+ + + project.bom_import.template.kicad_pcbnew.exptected_columns + Oczekiwane kolumny: + + + + + project.bom_import.template.kicad_pcbnew.exptected_columns.note + + Uwaga: Nie następuje przypisanie do konkretnych komponentów z zarządzania kategoriami.

+ ]]> +
+
+
+ + + project.bom_import.template.kicad_pcbnew.table + + + + + Pole + Warunek + Typ danych + Opis + + + + + Id + Opcjonalne + Liczba całkowita (Integer) + Dowolna wartość. Unikalny numer identyfikacyjny dla każdego komponentu. + + + Designator + Opcjonalne + String + Dowolna wartość. Unikalny identyfikator referencyjny komponentu na płytce PCB, np. „R1” dla rezystora 1.
Zostaje przeniesiony do nazwy montażowej wpisu komponentu. + + + Package + Opcjonalne + String + Dowolna wartość. Obudowa lub typ komponentu, np. „0805” dla rezystorów SMD.
Nie zostaje przeniesiony do wpisu komponentu. + + + Quantity + Pole obowiązkowe + Liczba całkowita (Integer) + Liczba identycznych komponentów potrzebnych do stworzenia instancji zestawu.
Zostaje przeniesiona jako ilość wpisu komponentu. + + + Designation + Pole obowiązkowe + String + Opis lub funkcja komponentu, np. wartość rezystora „10kΩ” lub wartość kondensatora „100nF”.
Zostaje przeniesiony do nazwy wpisu komponentu. + + + Supplier and ref + Opcjonalne + String + Dowolna wartość. Może zawierać np. wartość specyficzną dla dystrybutora.
Zostaje przeniesiona jako notatka do wpisu komponentu. + + + + ]]> +
+
+
project.bom_import.clear_existing_bom.help @@ -12223,5 +12626,886 @@ Należy pamiętać, że nie możesz udawać nieaktywnych użytkowników. Jeśli Wygenerowany kod + + + assembly.label + Zespół + + + + + assembly.caption + Zespół + + + + + perm.assemblies + Zespoły + + + + + assembly_bom_entry.label + Komponenty + + + + + assembly.labelp + Zespoły + + + + + assembly.referencedAssembly.labelp + Odwołane zestawy + + + + + assembly.edit + Edytuj zespół + + + + + assembly.new + Nowy zespół + + + + + assembly.edit.bom.import_bom + Importuj komponenty + + + + + log.database_updated.failed + __log.database_updated.failed + + + + + log.database_updated.old_version + __log.database_updated.old_version + + + + + log.database_updated.new_version + __log.database_updated.new_version + + + + + tree.tools.edit.assemblies + Zespoły + + + + + assembly.bom_import.flash.success + Pomyślnie zaimportowano %count% komponent(ów) do zespołu. + + + + + assembly.bom_import.flash.invalid_entries + Błąd walidacji! Sprawdź zaimportowany plik! + + + + + assembly.bom_import.flash.invalid_file + Nie udało się zaimportować pliku. Sprawdź, czy wybrano poprawny typ pliku. Komunikat błędu: %message% + + + + + assembly.bom.quantity + Ilość + + + + + assembly.bom.mountnames + Nazwy montażu + + + + + assembly.bom.designator + Oznaczenie referencyjne + + + + + assembly.bom.designator.help + Dowolne oznaczenia referencyjne (designator) + + + + + assembly.bom.instockAmount + Ilość na magazynie + + + + + assembly.info.title + Informacje o zespole + + + + + assembly.info.info.label + Informacje + + + + + assembly.info.sub_assemblies.label + Podzespoły + + + + + assembly.info.builds.label + Budowa + + + + + assembly.info.bom_add_parts + Dodaj części + + + + + assembly.info.bom_entries_count + Elementy + + + + + assembly.info.sub_assemblies_count + Podzespoły + + + + + assembly.bom.delete.confirm + Czy na pewno chcesz usunąć ten element? + + + + + assembly.add_parts_to_assembly + Dodaj części do zespołu + + + + + part.info.add_part_to_assembly + Dodaj tę część do zespołu + + + + + assembly.bom.project + Projekt + + + + + assembly.bom.referencedAssembly + Złożenie + + + + + assembly.bom.name + Nazwa + + + + + assembly.bom.name.help + Czytelny dla człowieka tytuł pozycji listy materiałowej + + + + + assembly.bom.comment + Uwagi + + + + + assembly.import_bom + Importuj części dla zespołu + + + + + assembly.bom.partOrAssembly + Część lub zespół + + + + + assembly.bom.identifiers + Identyfikatory + + + + + assembly.bom.add_entry + Dodaj pozycję + + + + + assembly.bom.price + Cena + + + + + assembly.bom_import.type + Typ + + + + + assembly.bom_import.type.json + JSON dla zespołu + + + + + assembly.bom_import.type.csv + CSV dla zestawienia + + + + + assembly.bom_import.type.kicad_pcbnew + CSV (KiCAD Pcbnew) + + + + + assembly.bom_import.type.kicad_schematic + KiCAD Schematyczny edytor BOM (plik CSV) + + + + + assembly.bom_import.clear_existing_bom + Usuń istniejące dane przed importem + + + + + assembly.bom_import.clear_existing_bom.help + Jeśli wybrano, wszystkie istniejące wpisy części zostaną usunięte i zastąpione danymi z importu. + + + + + assembly.import_bom.template.header.json + Szablon importu JSON dla zespołu + + + + + assembly.import_bom.template.header.csv + Szablon importu CSV dla zespołu + + + + + assembly.import_bom.template.header.kicad_pcbnew + Szablon importu CSV (KiCAD Pcbnew BOM) dla zespołu + + + + + assembly.bom_import.template.entry.name + Nazwa części w zespole + + + + + assembly.bom_import.template.entry.part.mpnr + Unikalny numer katalogowy producenta + + + + + assembly.bom_import.template.entry.part.ipn + Unikalny IPN części + + + + + assembly.bom_import.template.entry.part.name + Unikalna nazwa części + + + + + assembly.bom_import.template.entry.part.manufacturer.name + Unikalna nazwa producenta + + + + + assembly.bom_import.template.entry.part.category.name + Unikalna nazwa kategorii + + + + + assembly.bom_import.template.json.table + + + + + Pole + Warunek + Typ danych + Opis + + + + + quantity + Pole obowiązkowe + Liczba zmiennoprzecinkowa (Float) + Musi być wypełnione i zawierać liczbę zmiennoprzecinkową (Float) większą niż 0,0. + + + name + Opcjonalne + Tekst + Jeśli określono, musi to być niepusty tekst. Nazwa elementu w ramach montażu. + + + part + Opcjonalne + Obiekt/Tablica + + Jeśli konieczne jest przypisanie części, musi to być Obiekt/Tablica, a przynajmniej jedno z poniższych pól powinno być wypełnione: +
    +
  • part.id
  • +
  • part.mpnr
  • +
  • part.ipn
  • +
  • part.name
  • +
+ + + + part.id + Opcjonalne + Liczba całkowita + Liczba całkowita > 0. Odpowiada wewnętrznemu numerycznemu ID części w bazie danych. + + + part.mpnr + Opcjonalne + Tekst + Niepusty tekst, jeśli pola part.id, part.ipn lub part.name nie są wypełnione. + + + part.ipn + Opcjonalne + Tekst + Niepusty tekst, jeśli pola part.id, part.mpnr lub part.name nie są wypełnione. + + + part.name + Opcjonalne + Tekst + Niepusty tekst, jeśli pola part.id, part.mpnr lub part.ipn nie są wypełnione. + + + part.description + Opcjonalne + Tekst lub null + Jeśli określono, musi to być niepusty tekst lub null. Ta wartość nadpisze istniejącą wartość w części. + + + part.manufacturer + Opcjonalne + Obiekt/Tablica + + Jeśli producent części ma zostać zmieniony lub wyszukany unikalnie za pomocą wartości part.mpnr, musi to być Obiekt/Tablica i przynajmniej jedno z poniższych pól powinno być wypełnione: +
    +
  • manufacturer.id
  • +
  • manufacturer.name
  • +
+ + + + manufacturer.id + Opcjonalne + Liczba całkowita + Liczba całkowita > 0. Odpowiada wewnętrznemu numerycznemu ID producenta. + + + manufacturer.name + Opcjonalne + Tekst + Niepusty tekst, jeśli pole manufacturer.id nie jest wypełnione. + + + part.category + Opcjonalne + Obiekt/Tablica + + Jeśli konieczna jest zmiana kategorii części, musi to być Obiekt/Tablica i przynajmniej jedno z poniższych pól powinno być wypełnione: +
    +
  • category.id
  • +
  • category.name
  • +
+ + + + category.id + Opcjonalne + Liczba całkowita + Liczba całkowita > 0. Odpowiada wewnętrznemu numerycznemu ID kategorii części. + + + category.name + Opcjonalne + Tekst + Niepusty tekst, jeśli pole category.id nie jest wypełnione. + + + + ]]> +
+
+
+ + + assembly.bom_import.template.csv.exptected_columns + Możliwe kolumny: + + + + + assembly.bom_import.template.csv.table + + + + + Kolumna + Warunek + Typ danych + Opis + + + + + quantity + Pole obowiązkowe + Liczba zmiennoprzecinkowa (Float) + Musi być wypełnione i zawierać liczbę zmiennoprzecinkową (Float) większą niż 0,0. + + + name + Opcjonalne + Tekst + Nazwa elementu w ramach montażu. + + + Kolumny zaczynające się od part_ + + Jeśli konieczne jest przypisanie części, przynajmniej jedna z poniższych kolumn powinna być wypełniona: +
    +
  • part_id
  • +
  • part_mpnr
  • +
  • part_ipn
  • +
  • part_name
  • +
+ + + + part_id + Opcjonalne + Liczba całkowita + Liczba całkowita > 0. Odpowiada wewnętrznemu numerycznemu ID części w bazie danych. + + + part_mpnr + Opcjonalne + Tekst + Musi być wypełnione, gdy kolumny part_id, part_ipn lub part_name nie są wypełnione. + + + part_ipn + Opcjonalne + Tekst + Musi być wypełnione, gdy kolumny part_id, part_mpnr lub part_name nie są wypełnione. + + + part_name + Opcjonalne + Tekst + Musi być wypełnione, gdy kolumny part_id, part_mpnr lub part_ipn nie są wypełnione. + + + part_description + Opcjonalne + Tekst + Zostanie przeniesione i zastąpi istniejącą wartość opisu, jeśli określono niepusty tekst. + + + Kolumny zaczynające się od part_manufacturer_ + + Jeśli producent części musi zostać zmieniony lub wyszukany unikalnie za pomocą part_mpnr, przynajmniej jedna z poniższych kolumn powinna być wypełniona: +
    +
  • part_manufacturer_id
  • +
  • part_manufacturer_name
  • +
+ + + + part_manufacturer_id + Opcjonalne + Liczba całkowita + Liczba całkowita > 0. Odpowiada wewnętrznemu numerycznemu ID producenta. + + + part_manufacturer_name + Opcjonalne + Tekst + Musi być wypełnione, jeśli part_manufacturer_id nie jest określony. + + + Kolumny zaczynające się od part_category_ + + Jeśli konieczna jest zmiana kategorii części, przynajmniej jedna z poniższych kolumn powinna być wypełniona: +
    +
  • part_category_id
  • +
  • part_category_name
  • +
+ + + + part_category_id + Opcjonalne + Liczba całkowita + Liczba całkowita > 0. Odpowiada wewnętrznemu numerycznemu ID kategorii części. + + + part_category_name + Opcjonalne + Tekst + Musi być wypełnione, jeśli part_category_id nie jest określone. + + + + ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.exptected_columns + Oczekiwane kolumny: + + + + + assembly.bom_import.template.kicad_pcbnew.exptected_columns.note + + Uwaga: Nie wykonano mapowania z określonymi komponentami z zarządzania kategoriami.

+ ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.table + + + + + Pole + Warunek + Typ Danych + Opis + + + + + Id + Opcjonalne + Liczba całkowita + Pole dowolne. Unikalny numer identyfikacyjny dla każdego komponentu. + + + Designator + Opcjonalne + Tekst + Pole dowolne. Jednoznaczny znacznik referencyjny komponentu na PCB, np. "R1" dla rezystora 1.
Używane jako nazwa pozycji w pozycji komponentu w montażu. + + + Package + Opcjonalne + Tekst + Pole dowolne. Obudowa lub forma komponentu, np. "0805" dla rezystorów SMD.
Niewykorzystywane w pozycji komponentu w montażu. + + + Quantity + Wymagane + Liczba całkowita + Liczba identycznych komponentów potrzebna do utworzenia jednej instancji montażu.
Używane jako ilość w pozycji komponentu w montażu. + + + Designation + Wymagane + Tekst + Opis lub funkcja komponentu, np. wartość rezystora "10kΩ" lub wartość kondensatora "100nF".
Używane jako nazwa w pozycji komponentu w montażu. + + + Supplier and ref + Opcjonalne + Tekst + Pole dowolne. Może zawierać np. specyficzne informacje o dostawcy.
Używane jako notatka w pozycji komponentu w montażu. + + + + ]]> +
+
+
+ + + assembly_list.all.title + Wszystkie zespoły + + + + + assembly.edit.tab.common + Ogólne + + + + + assembly.edit.tab.advanced + Zaawansowane + + + + + assembly.edit.tab.attachments + Załączniki + + + + + assembly.filter.dbId + ID bazy danych + + + + + assembly.filter.ipn + Wewnętrzny numer części (IPN) + + + + + assembly.filter.name + Nazwa + + + + + assembly.filter.description + Opis + + + + + assembly.filter.comment + Komentarze + + + + + assembly.filter.attachments_count + Liczba załączników + + + + + assembly.filter.attachmentName + Nazwa załącznika + + + + + assemblies.create.btn + Utwórz nowy zespół + + + + + assembly.table.id + ID + + + + + assembly.table.name + Nazwa + + + + + assembly.table.ipn + IPN + + + + + assembly.table.description + Opis + + + + + assembly.table.referencedAssemblies + Zestawy referencyjne + + + + + assembly.table.addedDate + Dodano + + + + + assembly.table.lastModified + Ostatnia modyfikacja + + + + + assembly.table.edit + Edytuj + + + + + assembly.table.edit.title + Edytuj zespół + + + + + assembly.table.invalid_regex + Nieprawidłowe wyrażenie regularne (regex) + + + + + assembly.bom.table.id + ID + + + + + assembly.bom.table.name + Nazwa + + + + + assembly.bom.table.quantity + Ilość + + + + + assembly.bom.table.ipn + IPN + + + + + assembly.bom.table.description + Opis + + + + + assembly.bom.table.category + Kategoria + + + + + assembly.bom.table.manufacturer + Producent + + + + + assembly.bom.table.designator + Oznaczenie referencyjne + + + + + assembly.bom.table.mountnames + Nazwy montażowe + + + + + assembly.bom.table.storage_location + Miejsce przechowywania + + + + + assembly.bom.table.amount + Ilość + + + + + assembly.bom.table.addedDate + Data utworzenia + + + + + assembly.bom.table.lastModified + Ostatnia modyfikacja + + + + + assembly.bom.table.edit + Edytuj + + diff --git a/translations/messages.ru.xlf b/translations/messages.ru.xlf index 62570acb0..50657f6cd 100644 --- a/translations/messages.ru.xlf +++ b/translations/messages.ru.xlf @@ -351,6 +351,24 @@ Экспортировать всё + + + export.readable.label + Читаемый экспорт + + + + + export.readable + CSV + + + + + export.readable_bom + PDF + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:185 @@ -731,7 +749,7 @@ user.edit.tfa.disable_tfa_message - Это выключит <b>все активные двухфакторной способы аутентификации пользователя</b>и удалит <b>резервные коды</b>! + Это выключит <b>все активные двухфакторной способы аутентификации пользователя</b>и удалит <b>резервные коды</b>! <br> Пользователь должен будет снова настроить все методы двухфакторной аутентификации и распечатать новые резервные коды! <br><br> <b>Делайте это только в том случае, если вы абсолютно уверены в личности пользователя (обращающегося за помощью), в противном случае учетная запись может быть взломана злоумышленником!</b> @@ -3740,7 +3758,7 @@ tfa_backup.reset_codes.confirm_message - Это удалит все предыдущие коды и создаст набор новых. Это не может быть отменено. + Это удалит все предыдущие коды и создаст набор новых. Это не может быть отменено. Не забудьте распечатать новы кода и хранить их в безопасном месте! @@ -4751,6 +4769,24 @@ Имя + + + part.table.name.value.for_part + %value% (Часть) + + + + + part.table.name.value.for_assembly + %value% (Сборка) + + + + + part.table.name.value.for_project + %value% (Проект) + + Part-DB1\src\DataTables\PartsDataTable.php:178 @@ -9891,6 +9927,48 @@ Архивный + + + assembly.edit.status + Статус сборки + + + + + assembly.edit.ipn + Внутренний номер компонента (IPN) + + + + + assembly.status.draft + Черновик + + + + + assembly.status.planning + Планирование + + + + + assembly.status.in_production + В производстве + + + + + assembly.status.finished + Завершен + + + + + assembly.status.archived + Архивный + + part.new_build_part.error.build_part_already_exists @@ -11037,6 +11115,18 @@ Тип + + + project.bom_import.type.json + JSON + + + + + project.bom_import.type.csv + CSV + + project.bom_import.type.kicad_pcbnew @@ -11049,6 +11139,319 @@ Удалить существующие записи BOM перед импортом. + + + project.import_bom.template.header.json + Шаблон импорта JSON + + + + + project.import_bom.template.header.csv + Шаблон импорта CSV + + + + + project.import_bom.template.header.kicad_pcbnew + Шаблон импорта CSV (KiCAD Pcbnew BOM) + + + + + project.bom_import.template.entry.name + Название компонента в проекте + + + + + project.bom_import.template.entry.part.mpnr + Уникальный номер продукта производителя + + + + + project.bom_import.template.entry.part.ipn + Уникальный IPN компонента + + + + + project.bom_import.template.entry.part.name + Уникальное название компонента + + + + + project.bom_import.template.entry.part.manufacturer.name + Уникальное название производителя + + + + + project.bom_import.template.json.table + + + + + Поле + Условие + Тип данных + Описание + + + + + quantity + Обязательно + Дробное число (Float) + Должно быть указано и содержать дробное значение (Float), большее 0.0. + + + name + Опционально + Строка (String) + Если присутствует, должно быть непустой строкой. Название элемента в спецификации материалов. + + + part + Опционально + Объект/Массив + + Если необходимо назначить компонент, он должен быть объектом/массивом, и должно быть заполнено хотя бы одно из следующих полей: +
    +
  • part.id
  • +
  • part.mpnr
  • +
  • part.ipn
  • +
  • part.name
  • +
+ + + + part.id + Опционально + Целое число (Integer) + Целое число (Integer) > 0. Соответствует внутреннему числовому идентификатору компонента в базе данных компонентов (Part-DB). + + + part.mpnr + Опционально + Строка (String) + Непустая строка, если не указаны part.id, part.ipn или part.name. + + + part.ipn + Опционально + Строка (String) + Непустая строка, если не указаны part.id, part.mpnr или part.name. + + + part.name + Опционально + Строка (String) + Непустая строка, если не указаны part.id, part.mpnr или part.ipn. + + + part.manufacturer + Опционально + Объект/Массив + + Если необходимо указать производителя компонента или однозначно идентифицировать компонент на основе part.mpnr, он должен быть объектом/массивом, и хотя бы одно из следующих полей должно быть заполнено: +
    +
  • manufacturer.id
  • +
  • manufacturer.name
  • +
+ + + + manufacturer.id + Опционально + Целое число (Integer) + Целое число (Integer) > 0. Соответствует внутреннему числовому идентификатору производителя. + + + manufacturer.name + Опционально + Строка (String) + Непустая строка, если manufacturer.id не указан. + + + + ]]> +
+
+
+ + + project.bom_import.template.csv.exptected_columns + Возможные колонки: + + + + + project.bom_import.template.csv.table + + + + + Колонка + Условие + Тип данных + Описание + + + + + quantity + Обязательная + Число с плавающей запятой (Float) + Количество идентичных компонентов, необходимых для создания экземпляра.
Считается количеством записей компонента. + + + name + Optional + String + Если доступно, должна быть непустая строка. Название элемента в спецификации материалов. + + + Колонки, начинающиеся с part_ + + Если нужно назначить компонент, должна быть указана и заполнена по крайней мере одна из следующих колонок: +
    +
  • part_id
  • +
  • part_mpnr
  • +
  • part_ipn
  • +
  • part_name
  • +
+ + + + part_id + Необязательная + Целое число (Integer) + Целое > 0. Соответствует внутреннему числовому ID компонента в базе данных компонентов (Part-DB). + + + part_mpnr + Необязательная + Строка (String) + Должна быть указана, если колонки part_id, part_ipn или part_name не заполнены. + + + part_ipn + Необязательная + Строка (String) + Должна быть указана, если колонки part_id, part_mpnr или part_name не заполнены. + + + part_name + Необязательная + Строка (String) + Должна быть указана, если колонки part_id, part_mpnr или part_ipn не заполнены. + + + Колонки, начинающиеся с part_manufacturer_ + + Если требуется указать производителя компонента или уникально идентифицировать компонент на основе значения part_mpnr, должна быть указана и заполнена по крайней мере одна из следующих колонок: +
    +
  • part_manufacturer_id
  • +
  • part_manufacturer_name
  • +
+ + + + part_manufacturer_id + Необязательная + Целое число (Integer) + Целое > 0. Соответствует внутреннему числовому ID производителя. + + + part_manufacturer_name + Необязательная + Строка (String) + Должна быть указана, если колонка part_manufacturer_id не заполнена. + + + + ]]> +
+
+
+ + + project.bom_import.template.kicad_pcbnew.exptected_columns + Ожидаемые столбцы: + + + + + project.bom_import.template.kicad_pcbnew.exptected_columns.note + + Примечание: Не выполняется привязка к конкретным компонентам из управления категориями.

+ ]]> +
+
+
+ + + project.bom_import.template.kicad_pcbnew.table + + + + + Поле + Условие + Тип данных + Описание + + + + + Id + Необязательно + Целое число (Integer) + Свободный ввод. Уникальный идентификационный номер для каждого компонента. + + + Designator + Необязательно + Строка (String) + Свободный ввод. Уникальный идентификатор компонента на печатной плате, например, «R1» для резистора 1.
Добавляется в название сборочного узла записи компонента. + + + Package + Необязательно + Строка (String) + Свободный ввод. Корпус или тип компонента, например, «0805» для SMD резисторов.
Не добавляется в запись компонента. + + + Quantity + Обязательно + Целое число (Integer) + Число идентичных компонентов, необходимых для создания экземпляра сборки.
Добавляется как количество записи компонента. + + + Designation + Обязательно + Строка (String) + Описание или функция компонента, например, значение резистора «10kΩ» или значение конденсатора «100nF».
Добавляется в название записи компонента. + + + Supplier and ref + Необязательно + Строка (String) + Свободный ввод. Может содержать дистрибьюторское значение, например.
Добавляется как примечание к записи компонента. + + + + ]]> +
+
+
project.bom_import.clear_existing_bom.help @@ -12323,5 +12726,886 @@ Профиль сохранен! + + + assembly.label + Сборка + + + + + assembly.caption + Сборка + + + + + perm.assemblies + Сборки + + + + + assembly_bom_entry.label + Компоненты + + + + + assembly.labelp + Сборки + + + + + assembly.referencedAssembly.labelp + Ссылочные сборки + + + + + assembly.edit + Редактировать сборку + + + + + assembly.new + Новая сборка + + + + + assembly.edit.bom.import_bom + Импортировать компоненты + + + + + log.database_updated.failed + __log.database_updated.failed + + + + + log.database_updated.old_version + __log.database_updated.old_version + + + + + log.database_updated.new_version + __log.database_updated.new_version + + + + + tree.tools.edit.assemblies + Сборки + + + + + assembly.bom_import.flash.success + %count% компонент(ов) успешно импортировано в сборку. + + + + + assembly.bom_import.flash.invalid_entries + Ошибка валидации! Проверьте импортированный файл! + + + + + assembly.bom_import.flash.invalid_file + Не удалось импортировать файл. Убедитесь, что выбран правильный тип файла. Сообщение об ошибке: %message% + + + + + assembly.bom.quantity + Количество + + + + + assembly.bom.mountnames + Названия монтажей + + + + + assembly.bom.designator + Позиционное обозначение + + + + + assembly.bom.designator.help + Свободные позиционные обозначения (designator) + + + + + assembly.bom.instockAmount + Количество на складе + + + + + assembly.info.title + Информация о сборке + + + + + assembly.info.info.label + Информация + + + + + assembly.info.sub_assemblies.label + Подсборки + + + + + assembly.info.builds.label + Сборка + + + + + assembly.info.bom_add_parts + Добавить детали + + + + + assembly.info.bom_entries_count + Детали + + + + + assembly.info.sub_assemblies_count + Подсборки + + + + + assembly.bom.delete.confirm + Вы действительно хотите удалить этот элемент? + + + + + assembly.add_parts_to_assembly + Добавить детали в сборку + + + + + part.info.add_part_to_assembly + Добавить эту часть в сборку + + + + + assembly.bom.project + Проект + + + + + assembly.bom.referencedAssembly + Сборка + + + + + assembly.bom.name + Название + + + + + assembly.bom.name.help + Человекочитаемый заголовок записи BOM + + + + + assembly.bom.comment + Примечания + + + + + assembly.import_bom + Импортировать детали для сборки + + + + + assembly.bom.partOrAssembly + Часть или сборка + + + + + assembly.bom.identifiers + Идентификаторы + + + + + assembly.bom.add_entry + Добавить запись + + + + + assembly.bom.price + Цена + + + + + assembly.bom_import.type + Тип + + + + + assembly.bom_import.type.json + JSON для сборки + + + + + assembly.bom_import.type.csv + CSV для сборки + + + + + assembly.bom_import.type.kicad_pcbnew + CSV (KiCAD Pcbnew) + + + + + assembly.bom_import.type.kicad_schematic + KiCAD Схематический редактор BOM (CSV файл) + + + + + assembly.bom_import.clear_existing_bom + Очистить текущие данные перед импортом + + + + + assembly.bom_import.clear_existing_bom.help + Если выбрано, все существующие записи о деталях будут удалены и заменены импортированными. + + + + + assembly.import_bom.template.header.json + Шаблон импорта JSON для сборки + + + + + assembly.import_bom.template.header.csv + Шаблон импорта CSV для сборки + + + + + assembly.import_bom.template.header.kicad_pcbnew + Шаблон импорта CSV (KiCAD Pcbnew BOM) для сборки + + + + + assembly.bom_import.template.entry.name + Название детали в сборке + + + + + assembly.bom_import.template.entry.part.mpnr + Уникальный каталожный номер производителя + + + + + assembly.bom_import.template.entry.part.ipn + Уникальный IPN компонента + + + + + assembly.bom_import.template.entry.part.name + Уникальное имя компонента + + + + + assembly.bom_import.template.entry.part.manufacturer.name + Уникальное название производителя + + + + + assembly.bom_import.template.entry.part.category.name + Уникальное название категории + + + + + assembly.bom_import.template.json.table + + + + + Поле + Условие + Тип данных + Описание + + + + + quantity + Обязательное поле + Число с плавающей точкой (Float) + Должно быть заполнено и содержать число с плавающей точкой (Float) больше 0,0. + + + name + Необязательное + Строка + Если указано, должно быть непустой строкой. Имя элемента внутри сборки. + + + part + Необязательное + Объект/Массив + + Если необходимо назначить деталь, это должен быть объект/массив, и должно быть заполнено хотя бы одно из следующих полей: +
    +
  • part.id
  • +
  • part.mpnr
  • +
  • part.ipn
  • +
  • part.name
  • +
+ + + + part.id + Необязательное + Целое число + Целое число > 0. Соответствует внутреннему числовому идентификатору детали в базе данных. + + + part.mpnr + Необязательное + Строка + Непустая строка, если part.id, part.ipn или part.name не указаны. + + + part.ipn + Необязательное + Строка + Непустая строка, если part.id, part.mpnr или part.name не указаны. + + + part.name + Необязательное + Строка + Непустая строка, если part.id, part.mpnr или part.ipn не указаны. + + + part.description + Необязательное + Строка или null + Если указано, должно быть непустой строкой или null. Это значение перезаписывает существующее значение в детали. + + + part.manufacturer + Необязательное + Объект/Массив + + Если необходимо изменить производителя детали или уникально найти по значению part.mpnr, это должен быть объект/массив, и должно быть заполнено хотя бы одно из следующих полей: +
    +
  • manufacturer.id
  • +
  • manufacturer.name
  • +
+ + + + manufacturer.id + Необязательное + Целое число + Целое число > 0. Соответствует внутреннему числовому идентификатору производителя. + + + manufacturer.name + Необязательное + Строка + Непустая строка, если manufacturer.id не указано. + + + part.category + Необязательное + Объект/Массив + + Если необходимо изменить категорию детали, это должен быть объект/массив, и должно быть заполнено хотя бы одно из следующих полей: +
    +
  • category.id
  • +
  • category.name
  • +
+ + + + category.id + Необязательное + Целое число + Целое число > 0. Соответствует внутреннему числовому идентификатору категории детали. + + + category.name + Необязательное + Строка + Непустая строка, если category.id не указано. + + + + ]]> +
+
+
+ + + assembly.bom_import.template.csv.exptected_columns + Возможные столбцы: + + + + + assembly.bom_import.template.csv.table + + + + + Столбец + Условие + Тип данных + Описание + + + + + quantity + Обязательное поле + Число с плавающей точкой (Float) + Должно быть заполнено и содержать число с плавающей точкой (Float), больше 0,0. + + + name + Необязательное + Строка + Название элемента в рамках сборки. + + + Столбцы, начинающиеся с part_ + + Если необходимо назначить деталь, то хотя бы один из следующих столбцов должен быть заполнен: +
    +
  • part_id
  • +
  • part_mpnr
  • +
  • part_ipn
  • +
  • part_name
  • +
+ + + + part_id + Необязательное + Целое число + Целое число > 0. Соответствует внутреннему числовому ID детали в базе данных. + + + part_mpnr + Необязательное + Строка + Должно быть заполнено, если part_id, part_ipn или part_name не указаны. + + + part_ipn + Необязательное + Строка + Должно быть заполнено, если part_id, part_mpnr или part_name не указаны. + + + part_name + Необязательное + Строка + Должно быть заполнено, если part_id, part_mpnr или part_ipn не указаны. + + + part_description + Необязательное + Строка + Если указано, заменяет существующее значение описания деталя не пустой строкой. + + + Столбцы, начинающиеся с part_manufacturer_ + + Если необходимо указать производителя детали или найти деталь уникально по part_mpnr, должно быть заполнено хотя бы одно из следующих полей: +
    +
  • part_manufacturer_id
  • +
  • part_manufacturer_name
  • +
+ + + + part_manufacturer_id + Необязательное + Целое число + Целое число > 0. Соответствует внутреннему числовому ID производителя. + + + part_manufacturer_name + Необязательное + Строка + Должно быть заполнено, если part_manufacturer_id не указано. + + + Столбцы, начинающиеся с part_category_ + + Если необходимо изменить категорию детали, должно быть заполнено хотя бы одно из следующих полей: +
    +
  • part_category_id
  • +
  • part_category_name
  • +
+ + + + part_category_id + Необязательное + Целое число + Целое число > 0. Соответствует внутреннему числовому ID категории детали. + + + part_category_name + Необязательное + Строка + Должно быть заполнено, если part_category_id не указано. + + + + ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.exptected_columns + Ожидаемые столбцы: + + + + + assembly.bom_import.template.kicad_pcbnew.exptected_columns.note + + Примечание: Сопоставление с конкретными компонентами из управления категориями не выполняется.

+ ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.table + + + + + Поле + Условие + Тип данных + Описание + + + + + Id + Опционально + Целое + Свободное поле. Уникальный идентификационный номер для каждого компонента. + + + Package + Designator + Строка + Свободное поле. Уникальная ссылочная метка компонента на печатной плате, например, "R1" для резистора 1.
Используется как наименование позиции в компоненте сборки. + + + Package + Опционально + Строка + Свободное поле. Тип корпуса или форм-фактор компонента, например, "0805" для SMD-резисторов.
Не включается в информацию о компоненте сборки. + + + Quantity + Обязательно + Целое + Количество одинаковых компонентов, необходимых для создания одной версии сборки.
Используется как количество в информации о компоненте сборки. + + + Designation + Обязательно + Строка + Описание или функция компонента, например, значение резистора "10kΩ" или значение конденсатора "100nF".
Используется как наименование в информации о компоненте сборки. + + + Supplier and ref + Опционально + Строка + Свободное поле. Может содержать, например, информацию о конкретных поставщиках.
Используется как примечание в информации о компоненте сборки. + + + + ]]> +
+
+
+ + + assembly_list.all.title + Все сборки + + + + + assembly.edit.tab.common + Общие + + + + + assembly.edit.tab.advanced + Дополнительные параметры + + + + + assembly.edit.tab.attachments + Вложения + + + + + assembly.filter.dbId + ID базы данных + + + + + assembly.filter.ipn + Внутренний номер детали (IPN) + + + + + assembly.filter.name + Название + + + + + assembly.filter.description + Описание + + + + + assembly.filter.comment + Комментарии + + + + + assembly.filter.attachments_count + Количество вложений + + + + + assembly.filter.attachmentName + Имя вложения + + + + + assemblies.create.btn + Создать новую сборку + + + + + assembly.table.id + ID + + + + + assembly.table.name + Название + + + + + assembly.table.ipn + IPN + + + + + assembly.table.description + Описание + + + + + assembly.table.referencedAssemblies + Ссылочные сборки + + + + + assembly.table.addedDate + Добавлено + + + + + assembly.table.lastModified + Последнее изменение + + + + + assembly.table.edit + Редактировать + + + + + assembly.table.edit.title + Редактировать сборку + + + + + assembly.table.invalid_regex + Неверное регулярное выражение (regex) + + + + + assembly.bom.table.id + ID + + + + + assembly.bom.table.name + Название + + + + + assembly.bom.table.quantity + Количество + + + + + assembly.bom.table.ipn + IPN + + + + + assembly.bom.table.description + Описание + + + + + assembly.bom.table.category + Категория + + + + + assembly.bom.table.manufacturer + Производитель + + + + + assembly.bom.table.designator + Позиционное обозначение + + + + + assembly.bom.table.mountnames + Названия монтажа + + + + + assembly.bom.table.storage_location + Место хранения + + + + + assembly.bom.table.amount + Количество + + + + + assembly.bom.table.addedDate + Дата создания + + + + + assembly.bom.table.lastModified + Последнее изменение + + + + + assembly.bom.table.edit + Редактировать + + diff --git a/translations/messages.zh.xlf b/translations/messages.zh.xlf index 668c32f28..ecb2dc197 100644 --- a/translations/messages.zh.xlf +++ b/translations/messages.zh.xlf @@ -351,6 +351,24 @@ 导出所有元素 + + + export.readable.label + 可读导出 + + + + + export.readable + CSV + + + + + export.readable_bom + PDF + + Part-DB1\templates\AdminPages\EntityAdminBase.html.twig:185 @@ -4749,6 +4767,24 @@ 名称 + + + part.table.name.value.for_part + %value%(部件) + + + + + part.table.name.value.for_assembly + %value%(装配) + + + + + part.table.name.value.for_project + %value%(项目) + + Part-DB1\src\DataTables\PartsDataTable.php:178 @@ -9890,6 +9926,48 @@ Element 3 已存档 + + + assembly.edit.status + 装配状态 + + + + + assembly.edit.ipn + 内部零件号 (IPN) + + + + + assembly.status.draft + 草稿 + + + + + assembly.status.planning + 策划 + + + + + assembly.status.in_production + 生产中 + + + + + assembly.status.finished + 已完成 + + + + + assembly.status.archived + 已归档 + + part.new_build_part.error.build_part_already_exists @@ -11036,6 +11114,18 @@ Element 3 Type + + + project.bom_import.type.json + JSON + + + + + project.bom_import.type.csv + CSV + + project.bom_import.type.kicad_pcbnew @@ -11048,6 +11138,319 @@ Element 3 导入前删除现有BOM条目 + + + project.import_bom.template.header.json + JSON导入模板 + + + + + project.import_bom.template.header.csv + CSV导入模板 + + + + + project.import_bom.template.header.kicad_pcbnew + CSV导入模板(KiCAD Pcbnew BOM) + + + + + project.bom_import.template.entry.name + 项目中的组件名称 + + + + + project.bom_import.template.entry.part.mpnr + 制造商的唯一产品编号 + + + + + project.bom_import.template.entry.part.ipn + 唯一的组件IPN + + + + + project.bom_import.template.entry.part.name + 组件唯一名称 + + + + + project.bom_import.template.entry.part.manufacturer.name + 制造商唯一名称 + + + + + project.bom_import.template.json.table + + + + + 字段 + 条件 + 数据类型 + 描述 + + + + + quantity + 必填 + 小数 (Float) + 必须提供,并包含大于 0.0 的小数值 (Float)。 + + + name + 可选 + 字符串 (String) + 如果存在,必须是非空字符串。物料清单中元素的名称。 + + + part + 可选 + 对象/数组 + + 如果需要分配组件,则必须是对象/数组,并且以下字段中的至少一个必须填写: +
    +
  • part.id
  • +
  • part.mpnr
  • +
  • part.ipn
  • +
  • part.name
  • +
+ + + + part.id + 可选 + 整数 (Integer) + 整数 (Integer) > 0。对应于零件数据库 (Part-DB) 中组件的内部数字 ID。 + + + part.mpnr + 可选 + 字符串 (String) + 如果未提供 part.id、part.ipn 或 part.name,则为非空字符串。 + + + part.ipn + 可选 + 字符串 (String) + 如果未提供 part.id、part.mpnr 或 part.name,则为非空字符串。 + + + part.name + 可选 + 字符串 (String) + 如果未提供 part.id、part.mpnr 或 part.ipn,则为非空字符串。 + + + part.manufacturer + 可选 + 对象/数组 + + 如果需要调整组件的制造商,或者需要基于 part.mpnr 唯一标识组件,则必须是对象/数组,并且以下字段中的至少一个必须填写: +
    +
  • manufacturer.id
  • +
  • manufacturer.name
  • +
+ + + + manufacturer.id + 可选 + 整数 (Integer) + 整数 (Integer) > 0。对应于制造商的内部数字 ID。 + + + manufacturer.name + 可选 + 字符串 (String) + 如果未提供 manufacturer.id,则为非空字符串。 + + + + ]]> +
+
+
+ + + project.bom_import.template.csv.exptected_columns + 可能的列: + + + + + project.bom_import.template.csv.table + + + + + 列 + 条件 + 数据类型 + 描述 + + + + + quantity + 必填 + 浮点数 (Float) + 创建一个实例所需的相同组件数量。
记录为组件条目的数量。 + + + name + Optional + String + 如果可用,则必须是非空字符串。材料清单中项目的名称。 + + + 以 part_ 开头的列 + + 如果需要分配一个组件,必须提供并填写以下列之一: +
    +
  • part_id
  • +
  • part_mpnr
  • +
  • part_ipn
  • +
  • part_name
  • +
+ + + + part_id + 可选 + 整数 (Integer) + 整数 > 0。对应于零件数据库 (Part-DB) 中组件的内部数字 ID。 + + + part_mpnr + 可选 + 字符串 (String) + 如果 part_id、part_ipn 或 part_name 列未填写,则必须提供此列。 + + + part_ipn + 可选 + 字符串 (String) + 如果 part_id、part_mpnr 或 part_name 列未填写,则必须提供此列。 + + + part_name + 可选 + 字符串 (String) + 如果 part_id、part_mpnr 或 part_ipn 列未填写,则必须提供此列。 + + + 以 part_manufacturer_ 开头的列 + + 如果需要调整组件的制造商,或者组件需要根据 part_mpnr 值唯一标识,必须提供并填写以下列之一: +
    +
  • part_manufacturer_id
  • +
  • part_manufacturer_name
  • +
+ + + + part_manufacturer_id + 可选 + 整数 (Integer) + 整数 > 0。对应于制造商的内部数字 ID。 + + + part_manufacturer_name + 可选 + 字符串 (String) + 如果 part_manufacturer_id 列未填写,则必须提供此列。 + + + + ]]> +
+
+
+ + + project.bom_import.template.kicad_pcbnew.exptected_columns + 预期的列: + + + + + project.bom_import.template.kicad_pcbnew.exptected_columns.note + + 注意:分类管理中不会执行与特定组件的映射。

+ ]]> +
+
+
+ + + project.bom_import.template.kicad_pcbnew.table + + + + + 字段 + 条件 + 数据类型 + 描述 + + + + + Id + 可选 + 整数 + 自由输入。每个组件的唯一标识编号。 + + + Designator + 可选 + 字符串 (String) + 自由输入。PCB 上组件的唯一参考标识符,例如“R1”代表电阻 1。
会被采用到组件记录的装配名称中。 + + + Package + 可选 + 字符串 (String) + 自由输入。组件的封装或形状,例如 "0805" 表示 SMD 电阻。
不会被采用到组件记录中。 + + + Quantity + 必填 + 整数 + 创建组件实例所需的相同组件的数量。
会被采用为组件记录的数量。 + + + Designation + 必填 + 字符串 (String) + 组件的描述或功能,例如电阻值 “10kΩ” 或电容值 “100nF”。
会被采用到组件记录的名称中。 + + + Supplier and ref + 可选 + 字符串 (String) + 自由输入。例如,可以包含供应商的特定值。
会被采用为组件记录的备注。 + + + + ]]> +
+
+
project.bom_import.clear_existing_bom.help @@ -12208,5 +12611,886 @@ Element 3 成功创建 %COUNT% 个元素。 + + + assembly.label + 装配 + + + + + assembly.caption + 装配 + + + + + perm.assemblies + 装配列表 + + + + + assembly_bom_entry.label + 组件 + + + + + assembly.labelp + 装配列表 + + + + + assembly.referencedAssembly.labelp + 引用的程序集 + + + + + assembly.edit + 编辑装配 + + + + + assembly.new + 新装配 + + + + + assembly.edit.bom.import_bom + 导入组件 + + + + + log.database_updated.failed + __log.database_updated.failed + + + + + log.database_updated.old_version + __log.database_updated.old_version + + + + + log.database_updated.new_version + __log.database_updated.new_version + + + + + tree.tools.edit.assemblies + 装配列表 + + + + + assembly.bom_import.flash.success + 成功导入 %count% 个组件到装配中。 + + + + + assembly.bom_import.flash.invalid_entries + 验证错误!请检查导入的文件! + + + + + assembly.bom_import.flash.invalid_file + 文件导入失败。请确保选择了正确的文件格式。错误信息:%message% + + + + + assembly.bom.quantity + 数量 + + + + + assembly.bom.mountnames + 安装名称 + + + + + assembly.bom.designator + 位号 + + + + + assembly.bom.designator.help + 自由参考位号(Designator) + + + + + assembly.bom.instockAmount + 库存数量 + + + + + assembly.info.title + 装配信息 + + + + + assembly.info.info.label + 信息 + + + + + assembly.info.sub_assemblies.label + 子组件 + + + + + assembly.info.builds.label + 构建 + + + + + assembly.info.bom_add_parts + 添加零件 + + + + + assembly.info.bom_entries_count + 条目 + + + + + assembly.info.sub_assemblies_count + 子组件 + + + + + assembly.bom.delete.confirm + 您确定要删除此项目吗? + + + + + assembly.add_parts_to_assembly + 添加零件到组件 + + + + + part.info.add_part_to_assembly + 将此零件添加到装配体中 + + + + + assembly.bom.project + 项目 + + + + + assembly.bom.referencedAssembly + 组件 + + + + + assembly.bom.name + 名称 + + + + + assembly.bom.name.help + BOM 条目的可读标题 + + + + + assembly.bom.comment + 备注 + + + + + assembly.import_bom + 导入组件的零件 + + + + + assembly.bom.partOrAssembly + 部件或组件 + + + + + assembly.bom.identifiers + 标识符 + + + + + assembly.bom.add_entry + 添加条目 + + + + + assembly.bom.price + 价格 + + + + + assembly.bom_import.type + 类型 + + + + + assembly.bom_import.type.json + JSON 文件(组件) + + + + + assembly.bom_import.type.csv + 装配的CSV + + + + + assembly.bom_import.type.kicad_pcbnew + CSV 文件(KiCAD Pcbnew) + + + + + assembly.bom_import.type.kicad_schematic + KiCAD 原理图编辑器 BOM(CSV 文件) + + + + + assembly.bom_import.clear_existing_bom + 在导入前清空现有数据 + + + + + assembly.bom_import.clear_existing_bom.help + 如果选中,所有现有零件条目将被删除,新的导入数据将取而代之。 + + + + + assembly.import_bom.template.header.json + 装配 JSON 导入模板 + + + + + assembly.import_bom.template.header.csv + 用于装配的CSV导入模板 + + + + + assembly.import_bom.template.header.kicad_pcbnew + 装配 CSV 模板(KiCAD Pcbnew BOM) + + + + + assembly.bom_import.template.entry.name + 组件的零件名称 + + + + + assembly.bom_import.template.entry.part.mpnr + 唯一制造商零件编号 + + + + + assembly.bom_import.template.entry.part.ipn + 唯一 IPN 序列号 + + + + + assembly.bom_import.template.entry.part.name + 零件名称 + + + + + assembly.bom_import.template.entry.part.manufacturer.name + 制造商名称 + + + + + assembly.bom_import.template.entry.part.category.name + 类别名称 + + + + + assembly.bom_import.template.json.table + + + + + 字段 + 条件 + 数据类型 + 描述 + + + + + quantity + 必填字段 + 浮点数 (Float) + 必须填写且包含大于 0.0 的浮点数 (Float)。 + + + name + 可选 + 文本 + 如果填写,必须是非空文本。表示装配中的项目名称。 + + + part + 可选 + 对象/数组 + + 如果需要分配零件,它必须是一个对象/数组,并且至少需要填写以下字段之一: +
    +
  • part.id
  • +
  • part.mpnr
  • +
  • part.ipn
  • +
  • part.name
  • +
+ + + + part.id + 可选 + 整数 + 一个大于 0 的整数。对应数据库中零件的内部数字ID。 + + + part.mpnr + 可选 + 文本 + 如果 part.id、part.ipn 或 part.name 未填写,则必须是非空文本。 + + + part.ipn + 可选 + 文本 + 如果 part.id、part.mpnr 或 part.name 未填写,则必须是非空文本。 + + + part.name + 可选 + 文本 + 如果 part.id、part.mpnr 或 part.ipn 未填写,则必须是非空文本。 + + + part.description + 可选 + 文本或 null + 如果填写,必须是非空文本或 null。该值将替换零件中的现有值。 + + + part.manufacturer + 可选 + 对象/数组 + + 如果需要更改零件制造商或通过值 part.mpnr 唯一查找零件,它必须是一个对象/数组,并且至少需要填写以下字段之一: +
    +
  • manufacturer.id
  • +
  • manufacturer.name
  • +
+ + + + manufacturer.id + 可选 + 整数 + 一个大于 0 的整数。对应制造商的内部数字 ID。 + + + manufacturer.name + 可选 + 文本 + 如果 manufacturer.id 未填写,则必须是非空文本。 + + + part.category + 可选 + 对象/数组 + + 如果需要更改零件的类别,它必须是一个对象/数组,并且至少需要填写以下字段之一: +
    +
  • category.id
  • +
  • category.name
  • +
+ + + + category.id + 可选 + 整数 + 一个大于 0 的整数。对应零件类别的内部数字 ID。 + + + category.name + 可选 + 文本 + 如果 category.id 未填写,则必须是非空文本。 + + + + ]]> +
+
+
+ + + assembly.bom_import.template.csv.exptected_columns + 可用列: + + + + + assembly.bom_import.template.csv.table + + + + + 列名 + 条件 + 数据类型 + 描述 + + + + + quantity + 必填字段 + 浮点数 (Float) + 必须填写且包含大于 0.0 的浮点数 (Float)。 + + + name + 可选 + 文本 + 装配中的项目名称。 + + + 以 part_ 开头的列 + + 如果需要分配零件,则至少需要填写以下列之一: +
    +
  • part_id
  • +
  • part_mpnr
  • +
  • part_ipn
  • +
  • part_name
  • +
+ + + + part_id + 可选 + 整数 + 一个大于 0 的整数。对应数据库中零件的内部数字 ID。 + + + part_mpnr + 可选 + 文本 + 如果 part_id、part_ipn 或 part_name 未填写,则必须是非空文本。 + + + part_ipn + 可选 + 文本 + 如果 part_id、part_mpnr 或 part_name 未填写,则必须是非空文本。 + + + part_name + 可选 + 文本 + 如果 part_id、part_mpnr 或 part_ipn 未填写,则必须是非空文本。 + + + part_description + 可选 + 文本 + 如果指定,将取代现有描述值,且必须为非空文本。 + + + 以 part_manufacturer_ 开头的列 + + 如果需要更改零件的制造商或通过 part_mpnr 唯一查找,至少需要填写以下列之一: +
    +
  • part_manufacturer_id
  • +
  • part_manufacturer_name
  • +
+ + + + part_manufacturer_id + 可选 + 整数 + 一个大于 0 的整数。对应制造商的内部数字 ID。 + + + part_manufacturer_name + 可选 + 文本 + 如果 part_manufacturer_id 未填写,则必须是非空文本。 + + + 以 part_category_ 开头的列 + + 如果需要更改零件的类别,则至少需要填写以下列之一: +
    +
  • part_category_id
  • +
  • part_category_name
  • +
+ + + + part_category_id + 可选 + 整数 + 一个大于 0 的整数。对应零件类别的内部数字 ID。 + + + part_category_name + 可选 + 文本 + 如果 part_category_id 未填写,则必须是非空文本。 + + + + ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.exptected_columns + 预期的列: + + + + + assembly.bom_import.template.kicad_pcbnew.exptected_columns.note + + 注意: 未对类别管理中的特定组件进行映射。

+ ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.table + + + + + 字段 + 条件 + 数据类型 + 描述 + + + + + Id + 可选 + 整数 + 自由字段。每个组件的唯一标识号。 + + + Designator + 可选 + 字符串 + 自由字段。PCB上组件的唯一参考标识符,例如电阻 "R1"。
用于装配部件条目中的位置名称。 + + + Package + 可选 + 字符串 + 自由字段。组件的封装类型或外形规格,例如表面贴装电阻器 "0805"。
不包含在装配部件条目信息中。 + + + Quantity + 必填 + 整数 + 创建一个装配实例所需的相同部件的数量。
用于装配部件条目中的数量。 + + + Designation + 必填 + 字符串 + 组件的描述或功能,例如电阻的值 "10kΩ" 或电容的值 "100nF"。
用于装配部件条目中的名称。 + + + 供应商及参考 + 可选 + 字符串 + 自由字段。例如,可以包含有关供应商的特定信息。
用作装配部件信息中的备注。 + + + + ]]> +
+
+
+ + + assembly_list.all.title + 所有组件 + + + + + assembly.edit.tab.common + 通用 + + + + + assembly.edit.tab.advanced + 高级选项 + + + + + assembly.edit.tab.attachments + 附件 + + + + + assembly.filter.dbId + 数据库ID + + + + + assembly.filter.ipn + 内部零件编号(IPN) + + + + + assembly.filter.name + 名称 + + + + + assembly.filter.description + 描述 + + + + + assembly.filter.comment + 评论 + + + + + assembly.filter.attachments_count + 附件数量 + + + + + assembly.filter.attachmentName + 附件名称 + + + + + assemblies.create.btn + 创建新组件 + + + + + assembly.table.id + ID + + + + + assembly.table.name + 名称 + + + + + assembly.table.ipn + IPN + + + + + assembly.table.description + 描述 + + + + + assembly.table.referencedAssemblies + 引用的组件 + + + + + assembly.table.addedDate + 添加日期 + + + + + assembly.table.lastModified + 最后修改 + + + + + assembly.table.edit + 编辑 + + + + + assembly.table.edit.title + 编辑组件 + + + + + assembly.table.invalid_regex + 无效的正则表达式(regex) + + + + + assembly.bom.table.id + ID + + + + + assembly.bom.table.name + 名称 + + + + + assembly.bom.table.quantity + 数量 + + + + + assembly.bom.table.ipn + IPN + + + + + assembly.bom.table.description + 描述 + + + + + assembly.bom.table.category + 类别 + + + + + assembly.bom.table.manufacturer + 制造商 + + + + + assembly.bom.table.designator + 位号 + + + + + assembly.bom.table.mountnames + 装配名称 + + + + + assembly.bom.table.storage_location + 存储位置 + + + + + assembly.bom.table.amount + 数量 + + + + + assembly.bom.table.addedDate + 创建时间 + + + + + assembly.bom.table.lastModified + 最后修改 + + + + + assembly.bom.table.edit + 编辑 + + diff --git a/translations/validators.cs.xlf b/translations/validators.cs.xlf index c298266af..6af3ca0f5 100644 --- a/translations/validators.cs.xlf +++ b/translations/validators.cs.xlf @@ -239,6 +239,12 @@ Interní číslo dílu musí být jedinečné. {{ value }} se již používá! + + + assembly.ipn.must_be_unique + Interní číslo dílu musí být jedinečné. {{ value }} se již používá! + + validator.project.bom_entry.name_or_part_needed @@ -365,5 +371,113 @@ Neplatný kód. Zkontrolujte, zda je vaše ověřovací aplikace správně nastavena a zda je čas správně nastaven jak na serveru, tak na ověřovacím zařízení. + + + validator.bom_importer.invalid_import_type + Neplatný typ importu! + + + + + validator.bom_importer.invalid_file_extension + Neplatná přípona souboru "%extension%" pro typ importu "%importType%". Povolené přípony souborů: %allowedExtensions%. + + + + + assembly.bom_entry.part_already_in_bom + Tato součást již existuje ve skupině! + + + + + assembly.bom_entry.assembly_already_in_bom + Tato sestava již existuje jako položka v seznamu materiálů! + + + + + assembly.bom_entry.assembly_cycle + Byl zjištěn cyklus: Sestava "%name%" nepřímo odkazuje sama na sebe. + + + + + assembly.bom_entry.invalid_child_entry + Sestava nesmí ve svém seznamu materiálů (BOM) odkazovat na podskupinu, která je součástí její vlastní hierarchie. + + + + + assembly.bom_entry.name_already_in_bom + Již existuje součást s tímto názvem! + + + + + validator.assembly.bom_entry.name_or_part_needed + Musíte vybrat součást nebo nastavit název pro nesoučást! + + + + + validator.assembly.bom_entry.only_part_or_assembly_allowed + Je povoleno vybrat pouze jednu součástku nebo sestavu. Upravit prosím svůj výběr! + + + + + validator.bom_importer.json_csv.quantity.required + Musíte zadat množství > 0! + + + + + validator.bom_importer.json_csv.quantity.float + očekává se jako float větší než 0,0 + + + + + validator.bom_importer.json_csv.parameter.string.notEmpty + očekává se jako neprázdný řetězec + + + + + validator.bom_importer.json_csv.parameter.string.notEmpty.null + očekává se jako neprázdný řetězec nebo null + + + + + validator.bom_importer.json_csv.parameter.array + očekává se jako pole (array) + + + + + validator.bom_importer.json_csv.parameter.subproperties + musí mít alespoň jeden z následujících pod-parametrů: %propertyString% + + + + + validator.bom_importer.json_csv.parameter.notFoundFor + nenalezeno pro %value% + + + + + validator.bom_importer.json_csv.parameter.noExactMatch + se přesně neshoduje. Pro import zadáno: %importValue%, nalezeno (%foundId%): %foundValue% + + + + + validator.bom_importer.json_csv.parameter.manufacturerOrCategoryWithSubProperties + musí obsahovat jako pod-parametr buď: "id" jako celé číslo větší než 0 nebo "name" jako neprázdný řetězec + + diff --git a/translations/validators.da.xlf b/translations/validators.da.xlf index 21149f0e7..2460bb3e1 100644 --- a/translations/validators.da.xlf +++ b/translations/validators.da.xlf @@ -239,13 +239,19 @@ Det interne partnummer skal være unikt. {{ value }} værdien er allerede i brug! + + + assembly.ipn.must_be_unique + Det interne partnummer skal være unikt. {{ value }} værdien er allerede i brug! + + validator.project.bom_entry.name_or_part_needed Du skal vælge en komponent eller angive et navn til en ikke-komponent styklistepost! - + project.bom_entry.name_already_in_bom Der findes allerede en BOM linie med dette navn! @@ -341,5 +347,113 @@ Denne leverandørstregkodeværdi er allerede brugt til en anden beholdning. Stregkoden skal være unik! + + + validator.bom_importer.invalid_import_type + Ugyldig importtype! + + + + + validator.bom_importer.invalid_file_extension + Ugyldig filtypenavn "%extension%" for importtypen "%importType%". Tilladte filtypenavne: %allowedExtensions%. + + + + + assembly.bom_entry.part_already_in_bom + Denne del eksisterer allerede i gruppen! + + + + + assembly.bom_entry.assembly_already_in_bom + Denne samling findes allerede som en post! + + + + + assembly.bom_entry.assembly_cycle + En cyklus blev opdaget: Samlingen "%name%" refererer indirekte til sig selv. + + + + + assembly.bom_entry.invalid_child_entry + En samling må ikke referere til en undergruppe fra sin egen hierarki i BOM-listerne. + + + + + assembly.bom_entry.name_already_in_bom + Der findes allerede en del med dette navn! + + + + + validator.assembly.bom_entry.name_or_part_needed + Du skal vælge en del eller sætte et navn for en ikke-del! + + + + + validator.assembly.bom_entry.only_part_or_assembly_allowed + Det er kun tilladt at vælge én del eller en samling. Venligst tilpas dit valg! + + + + + validator.bom_importer.json_csv.quantity.required + Du skal angive en mængde > 0! + + + + + validator.bom_importer.json_csv.quantity.float + forventet som en float større end 0,0 + + + + + validator.bom_importer.json_csv.parameter.string.notEmpty + forventet som en ikke-tom streng + + + + + validator.bom_importer.json_csv.parameter.string.notEmpty.null + forventet som en ikke-tom streng eller null + + + + + validator.bom_importer.json_csv.parameter.array + forventet som en array + + + + + validator.bom_importer.json_csv.parameter.subproperties + skal have mindst én af følgende underparametre: %propertyString% + + + + + validator.bom_importer.json_csv.parameter.notFoundFor + ikke fundet for %value% + + + + + validator.bom_importer.json_csv.parameter.noExactMatch + stemmer ikke helt overens. Givet til import: %importValue%, fundet (%foundId%): %foundValue% + + + + + validator.bom_importer.json_csv.parameter.manufacturerOrCategoryWithSubProperties + skal indeholde som en underparameter enten: "id" som et heltal større end 0 eller "name" som en ikke-tom streng + + diff --git a/translations/validators.de.xlf b/translations/validators.de.xlf index 5cccd3887..06764efde 100644 --- a/translations/validators.de.xlf +++ b/translations/validators.de.xlf @@ -239,10 +239,16 @@ Die Internal Part Number (IPN) muss einzigartig sein. Der Wert {{value}} wird bereits benutzt! + + + assembly.ipn.must_be_unique + Die Internal Part Number (IPN) muss einzigartig sein. Der Wert {{value}} wird bereits benutzt! + + validator.project.bom_entry.name_or_part_needed - Sie müssen ein Bauteil auswählen, oder einen Namen für ein nicht-Bauteil BOM-Eintrag setzen! + Sie müssen ein Bauteil bzw. eine Baugruppe auswählen, oder einen Namen für ein nicht-Bauteil BOM-Eintrag setzen! @@ -365,5 +371,113 @@ Ungültiger Code. Überprüfen Sie, ob die Authenticator App korrekt eingerichtet ist und ob der Server und das Gerät beide die korrekte Uhrzeit eingestellt haben. + + + validator.bom_importer.invalid_import_type + Ungültiger Importtyp! + + + + + validator.bom_importer.invalid_file_extension + Ungültige Dateierweiterung "%extension%" für den Importtyp "%importType%". Erlaubte Dateierweiterungen: %allowedExtensions%. + + + + + assembly.bom_entry.part_already_in_bom + Dieses Bauteil existiert bereits in der Gruppe! + + + + + assembly.bom_entry.assembly_already_in_bom + Diese Baugruppe existiert bereits als Eintrag! + + + + + assembly.bom_entry.assembly_cycle + Ein Zyklus wurde entdeckt: Die Baugruppe "%name%" referenziert sich indirekt selbst. + + + + + assembly.bom_entry.invalid_child_entry + Eine Baugruppe darf keine Unterbaugruppe aus seiner eigenen Hierarchie in den BOM-Einträgen referenzieren. + + + + + assembly.bom_entry.name_already_in_bom + Es gibt bereits einen Bauteil mit diesem Namen! + + + + + validator.assembly.bom_entry.name_or_part_needed + Sie müssen ein Bauteil auswählen, oder einen Namen für den Eintrag setzen! + + + + + validator.assembly.bom_entry.only_part_or_assembly_allowed + Es darf nur ein Bauteil oder eine Baugruppe ausgewählt werden. Bitte passen Sie Ihre Auswahl an! + + + + + validator.bom_importer.json_csv.quantity.required + Sie müssen eine Stückzahl > 0 angeben! + + + + + validator.bom_importer.json_csv.quantity.float + wird als float größer als 0.0 erwartet + + + + + validator.bom_importer.json_csv.parameter.string.notEmpty + als nicht leere Zeichenkette erwartet + + + + + validator.bom_importer.json_csv.parameter.string.notEmpty.null + als nicht leere Zeichenkette oder null erwartet + + + + + validator.bom_importer.json_csv.parameter.array + als array erwartet + + + + + validator.bom_importer.json_csv.parameter.subproperties + muss mindestens eines der folgenden Unter-Parameter haben: %propertyString% + + + + + validator.bom_importer.json_csv.parameter.notFoundFor + nicht gefunden für %value% + + + + + validator.bom_importer.json_csv.parameter.noExactMatch + stimmt nicht genau überein. Für den Import gegeben: %importValue%, gefunden (%foundId%): %foundValue% + + + + + validator.bom_importer.json_csv.parameter.manufacturerOrCategoryWithSubProperties + muss entweder als Unter-Parameter zugewiesen haben: "id" als Ganzzahl größer als 0 oder "name" als nicht leere Zeichenfolge + + diff --git a/translations/validators.el.xlf b/translations/validators.el.xlf index 9ef5b3de4..320155fff 100644 --- a/translations/validators.el.xlf +++ b/translations/validators.el.xlf @@ -7,5 +7,119 @@ Ο εσωτερικός αριθμός εξαρτήματος πρέπει να είναι μοναδικός. {{ value }} χρησιμοποιείται ήδη! + + + assembly.ipn.must_be_unique + Ο εσωτερικός αριθμός εξαρτήματος πρέπει να είναι μοναδικός. {{ value }} χρησιμοποιείται ήδη! + + + + + validator.bom_importer.invalid_import_type + Μη έγκυρος τύπος εισαγωγής! + + + + + validator.bom_importer.invalid_file_extension + Μη έγκυρη επέκταση αρχείου "%extension%" για τον τύπο εισαγωγής "%importType%". Επιτρεπόμενες επεκτάσεις αρχείων: %allowedExtensions%. + + + + + assembly.bom_entry.part_already_in_bom + Αυτό το εξάρτημα υπάρχει ήδη στην ομάδα! + + + + + assembly.bom_entry.assembly_already_in_bom + Αυτή η συναρμολόγηση υπάρχει ήδη ως εγγραφή! + + + + + assembly.bom_entry.assembly_cycle + Εντοπίστηκε κύκλος: Η συναρμολόγηση "%name%" αναφέρεται έμμεσα στον εαυτό της. + + + + + assembly.bom_entry.invalid_child_entry + Μία συναρμολόγηση δεν πρέπει να αναφέρεται σε μία υποσυναρμολόγηση από την ίδια την ιεραρχία της στη λίστα BOM. + + + + + assembly.bom_entry.name_already_in_bom + Υπάρχει ήδη ένα εξάρτημα με αυτό το όνομα! + + + + + validator.assembly.bom_entry.name_or_part_needed + Πρέπει να επιλέξετε ένα εξάρτημα ή να βάλετε ένα όνομα για ένα μη εξάρτημα! + + + + + validator.assembly.bom_entry.only_part_or_assembly_allowed + Det er kun tilladt at vælge én del eller en samling. Venligst tilpas dit valg! + + + + + validator.bom_importer.json_csv.quantity.required + Πρέπει να εισαγάγετε ποσότητα > 0! + + + + + validator.bom_importer.json_csv.quantity.float + αναμένεται ως δεκαδικός αριθμός (float) μεγαλύτερος από 0,0 + + + + + validator.bom_importer.json_csv.parameter.string.notEmpty + αναμένεται ως μη κενή συμβολοσειρά + + + + + validator.bom_importer.json_csv.parameter.string.notEmpty.null + αναμένεται ως μη κενή συμβολοσειρά ή null + + + + + validator.bom_importer.json_csv.parameter.array + αναμένεται ως array + + + + + validator.bom_importer.json_csv.parameter.subproperties + πρέπει να έχει τουλάχιστον μία από τις ακόλουθες υπο-παραμέτρους: %propertyString% + + + + + validator.bom_importer.json_csv.parameter.notFoundFor + δεν βρέθηκε για %value% + + + + + validator.bom_importer.json_csv.parameter.noExactMatch + δεν ταιριάζει απόλυτα. Δόθηκε για εισαγωγή: %importValue%, βρέθηκε (%foundId%): %foundValue% + + + + + validator.bom_importer.json_csv.parameter.manufacturerOrCategoryWithSubProperties + πρέπει να περιέχει ως υπο-παράμετρο είτε: "id" ως ακέραιο αριθμό μεγαλύτερο από 0 είτε "name" ως μη κενή συμβολοσειρά + + diff --git a/translations/validators.en.xlf b/translations/validators.en.xlf index 6ad144607..95a558bff 100644 --- a/translations/validators.en.xlf +++ b/translations/validators.en.xlf @@ -239,10 +239,16 @@ The internal part number must be unique. {{ value }} is already in use! + + + assembly.ipn.must_be_unique + The internal part number must be unique. {{ value }} is already in use! + + validator.project.bom_entry.name_or_part_needed - You have to choose a part for a part BOM entry or set a name for a non-part BOM entry. + You have to select a part or assembly, or set a name for a non-component Bom entry! @@ -365,5 +371,113 @@ Invalid code. Check that your authenticator app is set up correctly and that both the server and authentication device has the time set correctly. + + + validator.bom_importer.invalid_import_type + Invalid import type! + + + + + validator.bom_importer.invalid_file_extension + Invalid file extension "%extension%" for import type %importType%". Allowed file extensions: %allowedExtensions%. + + + + + assembly.bom_entry.part_already_in_bom + This part already exists in the list! + + + + + assembly.bom_entry.assembly_already_in_bom + This assembly already exists as an entry! + + + + + assembly.bom_entry.assembly_cycle + A cycle was detected: the assembly "%name%" indirectly references itself. + + + + + assembly.bom_entry.invalid_child_entry + An assembly must not reference a subassembly from its own hierarchy in the BOM entries. + + + + + assembly.bom_entry.name_already_in_bom + There is already a part with this name! + + + + + validator.assembly.bom_entry.name_or_part_needed + You must select a part or set a name for the entry! + + + + + validator.assembly.bom_entry.only_part_or_assembly_allowed + Only one part or assembly may be selected. Please modify your selection! + + + + + validator.bom_importer.json_csv.quantity.required + you must specify a quantity > 0! + + + + + validator.bom_importer.json_csv.quantity.float + expected as float greater than 0.0 + + + + + validator.bom_importer.json_csv.parameter.string.notEmpty + expected as non-empty string + + + + + validator.bom_importer.json_csv.parameter.string.notEmpty.null + als nicht leere Zeichenkette oder null erwartet + + + + + validator.bom_importer.json_csv.parameter.array + expectd as array + + + + + validator.bom_importer.json_csv.parameter.subproperties + must have at least one of the following sub-properties: %propertyString% + + + + + validator.bom_importer.json_csv.parameter.notFoundFor + not found for %value% + + + + + validator.bom_importer.json_csv.parameter.noExactMatch + does not match exactly. Given for import: %importValue%, found (%foundId%): %foundValue% + + + + + validator.bom_importer.json_csv.parameter.manufacturerOrCategoryWithSubProperties + must have either assigned as sub-property: "id" as an integer greater than 0, or "name" as a non-empty string + + diff --git a/translations/validators.fr.xlf b/translations/validators.fr.xlf index e86ab9ccc..d8e824af9 100644 --- a/translations/validators.fr.xlf +++ b/translations/validators.fr.xlf @@ -203,5 +203,113 @@ L'emplacement de stockage a été marqué comme "Composant seul", par conséquent aucun nouveau composant ne peut être ajouté. + + + validator.bom_importer.invalid_import_type + Type d'importation invalide ! + + + + + validator.bom_importer.invalid_file_extension + Extension de fichier "%extension%" invalide pour le type d'importation "%importType%". Extensions de fichier autorisées : %allowedExtensions%. + + + + + assembly.bom_entry.part_already_in_bom + Cette pièce existe déjà dans le groupe! + + + + + assembly.bom_entry.assembly_already_in_bom + Cet assemblage existe déjà en tant qu'entrée ! + + + + + assembly.bom_entry.assembly_cycle + Un cycle a été détecté : L'assemblage "%name%" se réfère indirectement à lui-même. + + + + + assembly.bom_entry.invalid_child_entry + Un assemblage ne doit pas référencer un sous-assemblage de sa propre hiérarchie dans les entrées de la nomenclature (BOM). + + + + + assembly.bom_entry.name_already_in_bom + Il existe déjà une pièce avec ce nom! + + + + + validator.assembly.bom_entry.name_or_part_needed + Vous devez sélectionner une pièce ou attribuer un nom pour un non-élément! + + + + + validator.assembly.bom_entry.only_part_or_assembly_allowed + Seule une pièce ou un assemblage peut être sélectionné. Veuillez ajuster votre sélection! + + + + + validator.bom_importer.json_csv.quantity.required + Vous devez entrer une quantité > 0 ! + + + + + validator.bom_importer.json_csv.quantity.float + attendu comme un nombre décimal (float) supérieur à 0,0 + + + + + validator.bom_importer.json_csv.parameter.string.notEmpty + attendu comme une chaîne de caractères non vide + + + + + validator.bom_importer.json_csv.parameter.string.notEmpty.null + attendu comme une chaîne de caractères non vide ou null + + + + + validator.bom_importer.json_csv.parameter.array + attendu comme un tableau (array) + + + + + validator.bom_importer.json_csv.parameter.subproperties + doit contenir au moins l'un des sous-paramètres suivants : %propertyString% + + + + + validator.bom_importer.json_csv.parameter.notFoundFor + non trouvé pour %value% + + + + + validator.bom_importer.json_csv.parameter.noExactMatch + ne correspond pas exactement. Donné pour l'importation : %importValue%, trouvé (%foundId%) : %foundValue% + + + + + validator.bom_importer.json_csv.parameter.manufacturerOrCategoryWithSubProperties + doit contenir comme sous-paramètre soit : "id" comme entier supérieur à 0 ou "name" comme chaîne de caractères non vide + + diff --git a/translations/validators.hr.xlf b/translations/validators.hr.xlf index 29e32a16c..23ea0e849 100644 --- a/translations/validators.hr.xlf +++ b/translations/validators.hr.xlf @@ -239,6 +239,12 @@ Internal part number (IPN) mora biti jedinstven. {{ value }} je već u uporabi! + + + assembly.ipn.must_be_unique + Internal part number (IPN) mora biti jedinstven. {{ value }} je već u uporabi! + + validator.project.bom_entry.name_or_part_needed @@ -359,5 +365,113 @@ Neispravan kod. Provjerite je li vaša aplikacija za autentifikaciju ispravno postavljena i jesu li poslužitelj i uređaj za autentifikaciju ispravno postavili vrijeme. + + + validator.bom_importer.invalid_import_type + Nevažeći tip uvoza! + + + + + validator.bom_importer.invalid_file_extension + Nevažeća ekstenzija datoteke "%extension%" za tip uvoza "%importType%". Dopuštene ekstenzije datoteka: %allowedExtensions%. + + + + + assembly.bom_entry.part_already_in_bom + Ovaj dio već postoji u grupi! + + + + + assembly.bom_entry.assembly_already_in_bom + Ova se montaža već nalazi kao zapis! + + + + + assembly.bom_entry.assembly_cycle + Otkriven je ciklus: Sklop "%name%" neizravno referencira samog sebe. + + + + + assembly.bom_entry.invalid_child_entry + Sklop ne smije referencirati podsklop iz vlastite hijerarhije u unosima BOM-a. + + + + + assembly.bom_entry.name_already_in_bom + Već postoji dio s tim nazivom! + + + + + validator.assembly.bom_entry.name_or_part_needed + Morate odabrati dio ili unijeti naziv za nedio! + + + + + validator.assembly.bom_entry.only_part_or_assembly_allowed + Dozvoljeno je odabrati samo jednu komponentu ili sklop. Molimo prilagodite svoj odabir! + + + + + validator.bom_importer.json_csv.quantity.required + Morate unijeti količinu > 0! + + + + + validator.bom_importer.json_csv.quantity.float + očekuje se decimalni broj (float) veći od 0,0 + + + + + validator.bom_importer.json_csv.parameter.string.notEmpty + očekuje se kao neprazan niz znakova + + + + + validator.bom_importer.json_csv.parameter.string.notEmpty.null + očekuje se kao neprazan niz znakova ili null + + + + + validator.bom_importer.json_csv.parameter.array + očekuje se kao niz + + + + + validator.bom_importer.json_csv.parameter.subproperties + mora sadržavati barem jedan od sljedećih pod-parametara: %propertyString% + + + + + validator.bom_importer.json_csv.parameter.notFoundFor + nije pronađeno za %value% + + + + + validator.bom_importer.json_csv.parameter.noExactMatch + ne podudara se točno. Uneseno za uvoz: %importValue%, pronađeno (%foundId%): %foundValue% + + + + + validator.bom_importer.json_csv.parameter.manufacturerOrCategoryWithSubProperties + mora sadržavati kao pod-parametar bilo: "id" kao cijeli broj veći od 0 ili "name" kao neprazan niz znakova + + diff --git a/translations/validators.it.xlf b/translations/validators.it.xlf index 7043f4f34..4851ab6eb 100644 --- a/translations/validators.it.xlf +++ b/translations/validators.it.xlf @@ -239,6 +239,12 @@ Il codice interno (IPN) deve essere univoco. Il valore {{value}} è già in uso! + + + assembly.ipn.must_be_unique + Il codice interno (IPN) deve essere univoco. Il valore {{value}} è già in uso! + + validator.project.bom_entry.name_or_part_needed @@ -359,5 +365,113 @@ Codice non valido. Controlla che la tua app di autenticazione sia impostata correttamente e che sia il server che il dispositivo di autenticazione abbiano l'ora impostata correttamente. + + + validator.bom_importer.invalid_import_type + Tipo di importazione non valido! + + + + + validator.bom_importer.invalid_file_extension + Estensione del file "%extension%" non valida per il tipo di importazione "%importType%". Estensioni consentite: %allowedExtensions%. + + + + + assembly.bom_entry.part_already_in_bom + Questa parte è già presente nel gruppo! + + + + + assembly.bom_entry.assembly_already_in_bom + Questo assemblaggio è già presente come voce! + + + + + assembly.bom_entry.assembly_cycle + È stato rilevato un ciclo: L'assemblaggio "%name%" fa riferimento indirettamente a sé stesso. + + + + + assembly.bom_entry.invalid_child_entry + Un assemblaggio non deve fare riferimento a un sottoassemblaggio nella propria gerarchia nelle voci della distinta base (BOM). + + + + + assembly.bom_entry.name_already_in_bom + Esiste già una parte con questo nome! + + + + + validator.assembly.bom_entry.name_or_part_needed + È necessario selezionare una parte o inserire un nome per un non-parte! + + + + + validator.assembly.bom_entry.only_part_or_assembly_allowed + È consentito selezionare solo una parte o un assieme. Si prega di modificare la selezione! + + + + + validator.bom_importer.json_csv.quantity.required + Devi inserire una quantità > 0! + + + + + validator.bom_importer.json_csv.quantity.float + atteso come numero decimale (float) maggiore di 0,0 + + + + + validator.bom_importer.json_csv.parameter.string.notEmpty + atteso come stringa non vuota + + + + + validator.bom_importer.json_csv.parameter.string.notEmpty.null + atteso come stringa non vuota o null + + + + + validator.bom_importer.json_csv.parameter.array + atteso come array + + + + + validator.bom_importer.json_csv.parameter.subproperties + deve avere almeno uno dei seguenti sotto-parametri: %propertyString% + + + + + validator.bom_importer.json_csv.parameter.notFoundFor + non trovato per %value% + + + + + validator.bom_importer.json_csv.parameter.noExactMatch + non corrisponde esattamente. Valore dato per l'importazione: %importValue%, trovato (%foundId%): %foundValue% + + + + + validator.bom_importer.json_csv.parameter.manufacturerOrCategoryWithSubProperties + deve contenere come sotto-parametro: "id" come intero maggiore di 0 o "name" come stringa non vuota + + diff --git a/translations/validators.ja.xlf b/translations/validators.ja.xlf index 01cc3f77b..aed026eac 100644 --- a/translations/validators.ja.xlf +++ b/translations/validators.ja.xlf @@ -203,5 +203,113 @@ 新しい部品を追加できません。保管場所は「1つの部品のみ」とマークされています。 + + + validator.bom_importer.invalid_import_type + 無効なインポートタイプです! + + + + + validator.bom_importer.invalid_file_extension + インポートタイプ "%importType%" に対して無効なファイル拡張子 "%extension%"。許可されているファイル拡張子: %allowedExtensions%。 + + + + + assembly.bom_entry.part_already_in_bom + この部品はすでにグループに存在します! + + + + + assembly.bom_entry.assembly_already_in_bom + このアセンブリはすでにエントリとして存在します! + + + + + assembly.bom_entry.assembly_cycle + 循環が検出されました: アセンブリ「%name%」が間接的に自身を参照しています。 + + + + + assembly.bom_entry.invalid_child_entry + アセンブリは、BOMエントリで自身の階層内のサブアセンブリを参照してはいけません。 + + + + + assembly.bom_entry.name_already_in_bom + この名前の部品はすでに存在します! + + + + + validator.assembly.bom_entry.name_or_part_needed + 部品を選択するか、非部品の名前を入力する必要があります! + + + + + validator.assembly.bom_entry.only_part_or_assembly_allowed + 部品またはアセンブリのみ選択可能です。選択内容を調整してください! + + + + + validator.bom_importer.json_csv.quantity.required + 数量 > 0 を入力する必要があります! + + + + + validator.bom_importer.json_csv.quantity.float + 0.0 より大きい小数 (float) である必要があります + + + + + validator.bom_importer.json_csv.parameter.string.notEmpty + 空でない文字列が期待されます + + + + + validator.bom_importer.json_csv.parameter.string.notEmpty.null + 空でない文字列または null が期待されます + + + + + validator.bom_importer.json_csv.parameter.array + 配列として期待されます + + + + + validator.bom_importer.json_csv.parameter.subproperties + 以下のサブパラメーターのいずれかを含む必要があります:%propertyString% + + + + + validator.bom_importer.json_csv.parameter.notFoundFor + %value% に対する項目が見つかりません + + + + + validator.bom_importer.json_csv.parameter.noExactMatch + 完全には一致しません。インポートされた値:%importValue%、見つかった値 (%foundId%):%foundValue% + + + + + validator.bom_importer.json_csv.parameter.manufacturerOrCategoryWithSubProperties + サブパラメーターとして次のいずれかを含む必要があります:"id" は 0 より大きい整数、または "name" は空でない文字列 + + diff --git a/translations/validators.pl.xlf b/translations/validators.pl.xlf index 6c9977983..68d65a4ad 100644 --- a/translations/validators.pl.xlf +++ b/translations/validators.pl.xlf @@ -239,6 +239,12 @@ Wewnętrzny numer części musi być unikalny. {{value }} jest już w użyciu! + + + assembly.ipn.must_be_unique + Wewnętrzny numer części musi być unikalny. {{value }} jest już w użyciu! + + validator.project.bom_entry.name_or_part_needed @@ -359,5 +365,113 @@ Nieprawidłowy kod. Sprawdź, czy aplikacja uwierzytelniająca jest poprawnie skonfigurowana i czy zarówno serwer, jak i urządzenie uwierzytelniające mają poprawnie ustawiony czas. + + + validator.bom_importer.invalid_import_type + Nieprawidłowy typ importu! + + + + + validator.bom_importer.invalid_file_extension + Nieprawidłowe rozszerzenie pliku "%extension%" dla typu importu "%importType%". Dozwolone rozszerzenia plików: %allowedExtensions%. + + + + + assembly.bom_entry.part_already_in_bom + Ten element już istnieje w grupie! + + + + + assembly.bom_entry.assembly_already_in_bom + To zestawienie jest już dodane jako wpis! + + + + + assembly.bom_entry.assembly_cycle + 循環が検出されました: アセンブリ「%name%」が間接的に自身を参照しています。 + + + + + assembly.bom_entry.invalid_child_entry + Zespół nie może odwoływać się do podzespołu w swojej własnej hierarchii w wpisach BOM. + + + + + assembly.bom_entry.name_already_in_bom + Element o tej nazwie już istnieje! + + + + + validator.assembly.bom_entry.name_or_part_needed + Musisz wybrać element lub przypisać nazwę dla elementu niestandardowego! + + + + + validator.assembly.bom_entry.only_part_or_assembly_allowed + Można wybrać tylko jedną część lub zespół. Proszę dostosować swój wybór! + + + + + validator.bom_importer.json_csv.quantity.required + Musisz wprowadzić ilość > 0! + + + + + validator.bom_importer.json_csv.quantity.float + oczekiwano liczby zmiennoprzecinkowej (float) większej od 0,0 + + + + + validator.bom_importer.json_csv.parameter.string.notEmpty + oczekiwano jako niepusty ciąg znaków + + + + + validator.bom_importer.json_csv.parameter.string.notEmpty.null + oczekiwano jako niepusty ciąg znaków lub null + + + + + validator.bom_importer.json_csv.parameter.array + oczekiwano jako tablicę + + + + + validator.bom_importer.json_csv.parameter.subproperties + musi zawierać co najmniej jeden z następujących podparametrów: %propertyString% + + + + + validator.bom_importer.json_csv.parameter.notFoundFor + nie znaleziono dla %value% + + + + + validator.bom_importer.json_csv.parameter.noExactMatch + brak dokładnego dopasowania. Wprowadzone do importu: %importValue%, znalezione (%foundId%): %foundValue% + + + + + validator.bom_importer.json_csv.parameter.manufacturerOrCategoryWithSubProperties + musi zawierać jako podparametr: "id" jako liczbę całkowitą większą od 0 lub "name" jako niepusty ciąg znaków + + diff --git a/translations/validators.ru.xlf b/translations/validators.ru.xlf index 0f97c4781..f80d91d72 100644 --- a/translations/validators.ru.xlf +++ b/translations/validators.ru.xlf @@ -239,6 +239,12 @@ Внутренний номер детали (IPN) должен быть уникальным. Значение {{value}} уже используется! + + + assembly.ipn.must_be_unique + Внутренний номер детали (IPN) должен быть уникальным. Значение {{value}} уже используется! + + validator.project.bom_entry.name_or_part_needed @@ -359,5 +365,113 @@ Неверный код. Проверьте, что приложение аутентификации настроено правильно и что на сервере и устройстве аутентификации установлено правильное время. + + + validator.bom_importer.invalid_import_type + Недопустимый тип импорта! + + + + + validator.bom_importer.invalid_file_extension + Недопустимое расширение файла "%extension%" для типа импорта "%importType%". Допустимые расширения файлов: %allowedExtensions%. + + + + + assembly.bom_entry.part_already_in_bom + Эта деталь уже существует в группе! + + + + + assembly.bom_entry.assembly_already_in_bom + Этот сборочный узел уже добавлен как запись! + + + + + assembly.bom_entry.assembly_cycle + Обнаружен цикл: Сборка «%name%» косвенно ссылается на саму себя. + + + + + assembly.bom_entry.invalid_child_entry + Сборка не должна ссылаться на подсборку внутри своей собственной иерархии в записях спецификации (BOM). + + + + + assembly.bom_entry.name_already_in_bom + Деталь с таким названием уже существует! + + + + + validator.assembly.bom_entry.name_or_part_needed + Необходимо выбрать деталь или ввести название для недетали! + + + + + validator.assembly.bom_entry.only_part_or_assembly_allowed + Можно выбрать только деталь или сборку. Пожалуйста, измените ваш выбор! + + + + + validator.bom_importer.json_csv.quantity.required + Необходимо указать количество > 0! + + + + + validator.bom_importer.json_csv.quantity.float + ожидается число с плавающей запятой (float), большее 0,0 + + + + + validator.bom_importer.json_csv.parameter.string.notEmpty + ожидается непустая строка + + + + + validator.bom_importer.json_csv.parameter.string.notEmpty.null + ожидается непустая строка или null + + + + + validator.bom_importer.json_csv.parameter.array + ожидается массив + + + + + validator.bom_importer.json_csv.parameter.subproperties + должен содержать хотя бы один из следующих под-параметров: %propertyString% + + + + + validator.bom_importer.json_csv.parameter.notFoundFor + не найдено для %value% + + + + + validator.bom_importer.json_csv.parameter.noExactMatch + точное совпадение отсутствует. Указано для импорта: %importValue%, найдено (%foundId%): %foundValue% + + + + + validator.bom_importer.json_csv.parameter.manufacturerOrCategoryWithSubProperties + должен содержать под-параметр: "id" как целое число больше 0 или "name" как непустая строка + + diff --git a/translations/validators.zh.xlf b/translations/validators.zh.xlf index 08c9f014e..80a12e93b 100644 --- a/translations/validators.zh.xlf +++ b/translations/validators.zh.xlf @@ -239,13 +239,19 @@ 内部部件号是唯一的。{{ value }} 已被使用! + + + assembly.ipn.must_be_unique + 内部部件号是唯一的。{{ value }} 已被使用! + + validator.project.bom_entry.name_or_part_needed 您必须为 BOM 条目选择部件,或为非部件 BOM 条目设置名称。 - + project.bom_entry.name_already_in_bom 已存在具有该名称的 BOM 条目。 @@ -347,5 +353,113 @@ 由于技术限制,在32位系统中无法选择2038年1月19日之后的日期! + + + validator.bom_importer.invalid_import_type + 无效的导入类型! + + + + + validator.bom_importer.invalid_file_extension + 导入类型“%importType%”的文件扩展名“%extension%”无效。允许的扩展名: %allowedExtensions%。 + + + + + assembly.bom_entry.part_already_in_bom + 此零件已存在于组中! + + + + + assembly.bom_entry.assembly_already_in_bom + 此装配已经作为条目存在! + + + + + assembly.bom_entry.assembly_cycle + 检测到循环:装配体“%name%”间接引用了其自身。 + + + + + assembly.bom_entry.invalid_child_entry + Сборка не должна ссылаться на подсборку внутри своей собственной иерархии в записях спецификации (BOM). + + + + + assembly.bom_entry.name_already_in_bom + 具有此名称的零件已存在! + + + + + validator.assembly.bom_entry.name_or_part_needed + 必须选择零件或为非零件指定名称! + + + + + validator.assembly.bom_entry.only_part_or_assembly_allowed + 只能选择一个零件或组件。请修改您的选择! + + + + + validator.bom_importer.json_csv.quantity.required + 必须输入数量 > 0! + + + + + validator.bom_importer.json_csv.quantity.float + 应为大于 0.0 的浮点数 (float) + + + + + validator.bom_importer.json_csv.parameter.string.notEmpty + 应为非空字符串 + + + + + validator.bom_importer.json_csv.parameter.string.notEmpty.null + 应为非空字符串或 null + + + + + validator.bom_importer.json_csv.parameter.array + 应为数组 + + + + + validator.bom_importer.json_csv.parameter.subproperties + 必须包含以下子参数之一:%propertyString% + + + + + validator.bom_importer.json_csv.parameter.notFoundFor + 未找到对应值 %value% + + + + + validator.bom_importer.json_csv.parameter.noExactMatch + 未精确匹配。用于导入的值:%importValue%,找到的值 (%foundId%):%foundValue% + + + + + validator.bom_importer.json_csv.parameter.manufacturerOrCategoryWithSubProperties + 必须包含子参数:"id" 为大于 0 的整数,或 "name" 为非空字符串 + +