mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2026-01-18 08:09:34 +00:00
Merge remote-tracking branch 'origin/feature/create-assemblies' into feature/all-features
# Conflicts: # migrations/Version20250304154507.php # src/Controller/TypeaheadController.php # templates/assemblies/build/_form.html.twig
This commit is contained in:
commit
1345974954
50 changed files with 105 additions and 3832 deletions
|
|
@ -1,70 +0,0 @@
|
||||||
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 '<span>' + (data.image ? "<img style='height: 1.5rem; margin-right: 5px;' ' src='" + data.image + "'/>" : "") + escape(data.name) + '</span>';
|
|
||||||
},
|
|
||||||
option: (data, escape) => {
|
|
||||||
if(data.text) {
|
|
||||||
return '<span>' + escape(data.text) + '</span>';
|
|
||||||
}
|
|
||||||
|
|
||||||
let tmp = '<div class="row m-0">' +
|
|
||||||
"<div class='col-2 p-0 d-flex align-items-center' style='max-width: 80px;'>" +
|
|
||||||
(data.image ? "<img class='typeahead-image' src='" + data.image + "'/>" : "") +
|
|
||||||
"</div>" +
|
|
||||||
"<div class='col-10'>" +
|
|
||||||
'<h6 class="m-0">' + escape(data.name) + '</h6>' +
|
|
||||||
(data.description ? '<p class="m-0">' + marked.parseInline(data.description) + '</p>' : "") +
|
|
||||||
(data.category ? '<p class="m-0"><span class="fa-solid fa-tags fa-fw"></span> ' + escape(data.category) : "");
|
|
||||||
|
|
||||||
return tmp + '</p>' +
|
|
||||||
'</div></div>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -6,7 +6,6 @@ namespace DoctrineMigrations;
|
||||||
|
|
||||||
use App\Migration\AbstractMultiPlatformMigration;
|
use App\Migration\AbstractMultiPlatformMigration;
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
use Doctrine\Migrations\AbstractMigration;
|
|
||||||
|
|
||||||
final class Version20250304154507 extends AbstractMultiPlatformMigration
|
final class Version20250304154507 extends AbstractMultiPlatformMigration
|
||||||
{
|
{
|
||||||
|
|
@ -26,6 +25,8 @@ final class Version20250304154507 extends AbstractMultiPlatformMigration
|
||||||
$this->addSql(<<<'SQL'
|
$this->addSql(<<<'SQL'
|
||||||
CREATE UNIQUE INDEX UNIQ_6940A7FECC660B3C ON parts (built_assembly_id)
|
CREATE UNIQUE INDEX UNIQ_6940A7FECC660B3C ON parts (built_assembly_id)
|
||||||
SQL);
|
SQL);
|
||||||
|
|
||||||
|
// reverted in Version20251016124311, because built_assembly_id isn't required after testing time
|
||||||
}
|
}
|
||||||
|
|
||||||
public function mySQLDown(Schema $schema): void
|
public function mySQLDown(Schema $schema): void
|
||||||
|
|
@ -43,382 +44,21 @@ final class Version20250304154507 extends AbstractMultiPlatformMigration
|
||||||
|
|
||||||
public function sqLiteUp(Schema $schema): void
|
public function sqLiteUp(Schema $schema): void
|
||||||
{
|
{
|
||||||
$this->addSql(<<<'SQL'
|
// nothing do to, built_assembly_id not required
|
||||||
CREATE TEMPORARY TABLE __temp__parts AS
|
|
||||||
SELECT
|
|
||||||
id,
|
|
||||||
id_preview_attachment,
|
|
||||||
id_category,
|
|
||||||
id_footprint,
|
|
||||||
id_part_unit,
|
|
||||||
id_manufacturer,
|
|
||||||
order_orderdetails_id,
|
|
||||||
built_project_id,
|
|
||||||
datetime_added,
|
|
||||||
name,
|
|
||||||
last_modified,
|
|
||||||
needs_review,
|
|
||||||
tags,
|
|
||||||
mass,
|
|
||||||
description,
|
|
||||||
comment,
|
|
||||||
visible,
|
|
||||||
favorite,
|
|
||||||
minamount,
|
|
||||||
manufacturer_product_url,
|
|
||||||
manufacturer_product_number,
|
|
||||||
manufacturing_status,
|
|
||||||
order_quantity,
|
|
||||||
manual_order,
|
|
||||||
ipn,
|
|
||||||
provider_reference_provider_key,
|
|
||||||
provider_reference_provider_id,
|
|
||||||
provider_reference_provider_url,
|
|
||||||
provider_reference_last_updated,
|
|
||||||
eda_info_reference_prefix,
|
|
||||||
eda_info_value,
|
|
||||||
eda_info_invisible,
|
|
||||||
eda_info_exclude_from_bom,
|
|
||||||
eda_info_exclude_from_board,
|
|
||||||
eda_info_exclude_from_sim,
|
|
||||||
eda_info_kicad_symbol,
|
|
||||||
eda_info_kicad_footprint
|
|
||||||
FROM parts
|
|
||||||
SQL);
|
|
||||||
$this->addSql('DROP TABLE parts');
|
|
||||||
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE TABLE "parts"
|
|
||||||
(
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
||||||
id_preview_attachment INTEGER DEFAULT NULL,
|
|
||||||
id_category INTEGER NOT NULL,
|
|
||||||
id_footprint INTEGER DEFAULT NULL,
|
|
||||||
id_part_unit INTEGER DEFAULT NULL,
|
|
||||||
id_manufacturer INTEGER DEFAULT NULL,
|
|
||||||
order_orderdetails_id INTEGER DEFAULT NULL,
|
|
||||||
built_project_id INTEGER DEFAULT NULL,
|
|
||||||
built_assembly_id INTEGER DEFAULT NULL,
|
|
||||||
datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
|
||||||
name VARCHAR(255) NOT NULL,
|
|
||||||
last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
|
||||||
needs_review BOOLEAN NOT NULL,
|
|
||||||
tags CLOB NOT NULL,
|
|
||||||
mass DOUBLE PRECISION DEFAULT NULL,
|
|
||||||
description CLOB NOT NULL,
|
|
||||||
comment CLOB NOT NULL,
|
|
||||||
visible BOOLEAN NOT NULL,
|
|
||||||
favorite BOOLEAN NOT NULL,
|
|
||||||
minamount DOUBLE PRECISION NOT NULL,
|
|
||||||
manufacturer_product_url CLOB NOT NULL,
|
|
||||||
manufacturer_product_number VARCHAR(255) NOT NULL,
|
|
||||||
manufacturing_status VARCHAR(255) DEFAULT NULL,
|
|
||||||
order_quantity INTEGER NOT NULL,
|
|
||||||
manual_order BOOLEAN NOT NULL,
|
|
||||||
ipn VARCHAR(100) DEFAULT NULL,
|
|
||||||
provider_reference_provider_key VARCHAR(255) DEFAULT NULL,
|
|
||||||
provider_reference_provider_id VARCHAR(255) DEFAULT NULL,
|
|
||||||
provider_reference_provider_url VARCHAR(255) DEFAULT NULL,
|
|
||||||
provider_reference_last_updated DATETIME DEFAULT NULL,
|
|
||||||
eda_info_reference_prefix VARCHAR(255) DEFAULT NULL,
|
|
||||||
eda_info_value VARCHAR(255) DEFAULT NULL,
|
|
||||||
eda_info_invisible BOOLEAN DEFAULT NULL,
|
|
||||||
eda_info_exclude_from_bom BOOLEAN DEFAULT NULL,
|
|
||||||
eda_info_exclude_from_board BOOLEAN DEFAULT NULL,
|
|
||||||
eda_info_exclude_from_sim BOOLEAN DEFAULT NULL,
|
|
||||||
eda_info_kicad_symbol VARCHAR(255) DEFAULT NULL,
|
|
||||||
eda_info_kicad_footprint VARCHAR(255) DEFAULT NULL,
|
|
||||||
CONSTRAINT FK_6940A7FEEA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES "attachments" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE,
|
|
||||||
CONSTRAINT FK_6940A7FE5697F554 FOREIGN KEY (id_category) REFERENCES "categories" (id) NOT DEFERRABLE INITIALLY IMMEDIATE,
|
|
||||||
CONSTRAINT FK_6940A7FE7E371A10 FOREIGN KEY (id_footprint) REFERENCES "footprints" (id) NOT DEFERRABLE INITIALLY IMMEDIATE,
|
|
||||||
CONSTRAINT FK_6940A7FE2626CEF9 FOREIGN KEY (id_part_unit) REFERENCES "measurement_units" (id) NOT DEFERRABLE INITIALLY IMMEDIATE,
|
|
||||||
CONSTRAINT FK_6940A7FE1ECB93AE FOREIGN KEY (id_manufacturer) REFERENCES "manufacturers" (id) NOT DEFERRABLE INITIALLY IMMEDIATE,
|
|
||||||
CONSTRAINT FK_6940A7FE81081E9B FOREIGN KEY (order_orderdetails_id) REFERENCES "orderdetails" (id) NOT DEFERRABLE INITIALLY IMMEDIATE,
|
|
||||||
CONSTRAINT FK_6940A7FEE8AE70D9 FOREIGN KEY (built_project_id) REFERENCES projects (id) NOT DEFERRABLE INITIALLY IMMEDIATE,
|
|
||||||
CONSTRAINT FK_6940A7FECC660B3C FOREIGN KEY (built_assembly_id) REFERENCES assemblies (id) NOT DEFERRABLE INITIALLY IMMEDIATE
|
|
||||||
)
|
|
||||||
SQL);
|
|
||||||
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
INSERT INTO parts (
|
|
||||||
id,
|
|
||||||
id_preview_attachment,
|
|
||||||
id_category,
|
|
||||||
id_footprint,
|
|
||||||
id_part_unit,
|
|
||||||
id_manufacturer,
|
|
||||||
order_orderdetails_id,
|
|
||||||
built_project_id,
|
|
||||||
datetime_added,
|
|
||||||
name,
|
|
||||||
last_modified,
|
|
||||||
needs_review,
|
|
||||||
tags,
|
|
||||||
mass,
|
|
||||||
description,
|
|
||||||
comment,
|
|
||||||
visible,
|
|
||||||
favorite,
|
|
||||||
minamount,
|
|
||||||
manufacturer_product_url,
|
|
||||||
manufacturer_product_number,
|
|
||||||
manufacturing_status,
|
|
||||||
order_quantity,
|
|
||||||
manual_order,
|
|
||||||
ipn,
|
|
||||||
provider_reference_provider_key,
|
|
||||||
provider_reference_provider_id,
|
|
||||||
provider_reference_provider_url,
|
|
||||||
provider_reference_last_updated,
|
|
||||||
eda_info_reference_prefix,
|
|
||||||
eda_info_value,
|
|
||||||
eda_info_invisible,
|
|
||||||
eda_info_exclude_from_bom,
|
|
||||||
eda_info_exclude_from_board,
|
|
||||||
eda_info_exclude_from_sim,
|
|
||||||
eda_info_kicad_symbol,
|
|
||||||
eda_info_kicad_footprint
|
|
||||||
) SELECT * FROM __temp__parts
|
|
||||||
SQL);
|
|
||||||
$this->addSql('DROP TABLE __temp__parts');
|
|
||||||
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE INDEX IDX_6940A7FE1ECB93AE ON "parts" (id_manufacturer)
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE INDEX IDX_6940A7FE2626CEF9 ON "parts" (id_part_unit)
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE INDEX IDX_6940A7FE5697F554 ON "parts" (id_category)
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE INDEX IDX_6940A7FE7E371A10 ON "parts" (id_footprint)
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE INDEX IDX_6940A7FEEA7100A1 ON "parts" (id_preview_attachment)
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE UNIQUE INDEX UNIQ_6940A7FE3D721C14 ON "parts" (ipn)
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE UNIQUE INDEX UNIQ_6940A7FE81081E9B ON "parts" (order_orderdetails_id)
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE UNIQUE INDEX UNIQ_6940A7FEE8AE70D9 ON "parts" (built_project_id)
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE UNIQUE INDEX UNIQ_6940A7FECC660B3C ON "parts" (built_assembly_id)
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE INDEX parts_idx_datet_name_last_id_needs ON "parts" (datetime_added, name, last_modified, id, needs_review)
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE INDEX parts_idx_ipn ON "parts" (ipn)
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE INDEX parts_idx_name ON "parts" (name)
|
|
||||||
SQL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function sqLiteDown(Schema $schema): void
|
public function sqLiteDown(Schema $schema): void
|
||||||
{
|
{
|
||||||
$this->addSql(<<<'SQL'
|
// nothing do to, built_assembly_id not required
|
||||||
CREATE TEMPORARY TABLE __temp__parts AS
|
|
||||||
SELECT
|
|
||||||
id,
|
|
||||||
id_preview_attachment,
|
|
||||||
id_category,
|
|
||||||
id_footprint,
|
|
||||||
id_part_unit,
|
|
||||||
id_manufacturer,
|
|
||||||
order_orderdetails_id,
|
|
||||||
built_project_id,
|
|
||||||
datetime_added,
|
|
||||||
name,
|
|
||||||
last_modified,
|
|
||||||
needs_review,
|
|
||||||
tags,
|
|
||||||
mass,
|
|
||||||
description,
|
|
||||||
comment,
|
|
||||||
visible,
|
|
||||||
favorite,
|
|
||||||
minamount,
|
|
||||||
manufacturer_product_url,
|
|
||||||
manufacturer_product_number,
|
|
||||||
manufacturing_status,
|
|
||||||
order_quantity,
|
|
||||||
manual_order,
|
|
||||||
ipn,
|
|
||||||
provider_reference_provider_key,
|
|
||||||
provider_reference_provider_id,
|
|
||||||
provider_reference_provider_url,
|
|
||||||
provider_reference_last_updated,
|
|
||||||
eda_info_reference_prefix,
|
|
||||||
eda_info_value,
|
|
||||||
eda_info_invisible,
|
|
||||||
eda_info_exclude_from_bom,
|
|
||||||
eda_info_exclude_from_board,
|
|
||||||
eda_info_exclude_from_sim,
|
|
||||||
eda_info_kicad_symbol,
|
|
||||||
eda_info_kicad_footprint
|
|
||||||
FROM parts
|
|
||||||
SQL);
|
|
||||||
|
|
||||||
$this->addSql('DROP TABLE parts');
|
|
||||||
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE TABLE "parts"
|
|
||||||
(
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
||||||
id_preview_attachment INTEGER DEFAULT NULL,
|
|
||||||
id_category INTEGER NOT NULL,
|
|
||||||
id_footprint INTEGER DEFAULT NULL,
|
|
||||||
id_part_unit INTEGER DEFAULT NULL,
|
|
||||||
id_manufacturer INTEGER DEFAULT NULL,
|
|
||||||
order_orderdetails_id INTEGER DEFAULT NULL,
|
|
||||||
built_project_id INTEGER DEFAULT NULL,
|
|
||||||
datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
|
||||||
name VARCHAR(255) NOT NULL,
|
|
||||||
last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
|
||||||
needs_review BOOLEAN NOT NULL,
|
|
||||||
tags CLOB NOT NULL,
|
|
||||||
mass DOUBLE PRECISION DEFAULT NULL,
|
|
||||||
description CLOB NOT NULL,
|
|
||||||
comment CLOB NOT NULL,
|
|
||||||
visible BOOLEAN NOT NULL,
|
|
||||||
favorite BOOLEAN NOT NULL,
|
|
||||||
minamount DOUBLE PRECISION NOT NULL,
|
|
||||||
manufacturer_product_url CLOB NOT NULL,
|
|
||||||
manufacturer_product_number VARCHAR(255) NOT NULL,
|
|
||||||
manufacturing_status VARCHAR(255) DEFAULT NULL,
|
|
||||||
order_quantity INTEGER NOT NULL,
|
|
||||||
manual_order BOOLEAN NOT NULL,
|
|
||||||
ipn VARCHAR(100) DEFAULT NULL,
|
|
||||||
provider_reference_provider_key VARCHAR(255) DEFAULT NULL,
|
|
||||||
provider_reference_provider_id VARCHAR(255) DEFAULT NULL,
|
|
||||||
provider_reference_provider_url VARCHAR(255) DEFAULT NULL,
|
|
||||||
provider_reference_last_updated DATETIME DEFAULT NULL,
|
|
||||||
eda_info_reference_prefix VARCHAR(255) DEFAULT NULL,
|
|
||||||
eda_info_value VARCHAR(255) DEFAULT NULL,
|
|
||||||
eda_info_invisible BOOLEAN DEFAULT NULL,
|
|
||||||
eda_info_exclude_from_bom BOOLEAN DEFAULT NULL,
|
|
||||||
eda_info_exclude_from_board BOOLEAN DEFAULT NULL,
|
|
||||||
eda_info_exclude_from_sim BOOLEAN DEFAULT NULL,
|
|
||||||
eda_info_kicad_symbol VARCHAR(255) DEFAULT NULL,
|
|
||||||
eda_info_kicad_footprint VARCHAR(255) DEFAULT NULL,
|
|
||||||
CONSTRAINT FK_6940A7FEEA7100A1 FOREIGN KEY (id_preview_attachment) REFERENCES "attachments" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE,
|
|
||||||
CONSTRAINT FK_6940A7FE5697F554 FOREIGN KEY (id_category) REFERENCES "categories" (id) NOT DEFERRABLE INITIALLY IMMEDIATE,
|
|
||||||
CONSTRAINT FK_6940A7FE7E371A10 FOREIGN KEY (id_footprint) REFERENCES "footprints" (id) NOT DEFERRABLE INITIALLY IMMEDIATE,
|
|
||||||
CONSTRAINT FK_6940A7FE2626CEF9 FOREIGN KEY (id_part_unit) REFERENCES "measurement_units" (id) NOT DEFERRABLE INITIALLY IMMEDIATE,
|
|
||||||
CONSTRAINT FK_6940A7FE1ECB93AE FOREIGN KEY (id_manufacturer) REFERENCES "manufacturers" (id) NOT DEFERRABLE INITIALLY IMMEDIATE,
|
|
||||||
CONSTRAINT FK_6940A7FE81081E9B FOREIGN KEY (order_orderdetails_id) REFERENCES "orderdetails" (id) NOT DEFERRABLE INITIALLY IMMEDIATE,
|
|
||||||
CONSTRAINT FK_6940A7FEE8AE70D9 FOREIGN KEY (built_project_id) REFERENCES projects (id) NOT DEFERRABLE INITIALLY IMMEDIATE
|
|
||||||
)
|
|
||||||
SQL);
|
|
||||||
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
INSERT INTO parts (
|
|
||||||
id,
|
|
||||||
id_preview_attachment,
|
|
||||||
id_category,
|
|
||||||
id_footprint,
|
|
||||||
id_part_unit,
|
|
||||||
id_manufacturer,
|
|
||||||
order_orderdetails_id,
|
|
||||||
built_project_id,
|
|
||||||
datetime_added,
|
|
||||||
name,
|
|
||||||
last_modified,
|
|
||||||
needs_review,
|
|
||||||
tags,
|
|
||||||
mass,
|
|
||||||
description,
|
|
||||||
comment,
|
|
||||||
visible,
|
|
||||||
favorite,
|
|
||||||
minamount,
|
|
||||||
manufacturer_product_url,
|
|
||||||
manufacturer_product_number,
|
|
||||||
manufacturing_status,
|
|
||||||
order_quantity,
|
|
||||||
manual_order,
|
|
||||||
ipn,
|
|
||||||
provider_reference_provider_key,
|
|
||||||
provider_reference_provider_id,
|
|
||||||
provider_reference_provider_url,
|
|
||||||
provider_reference_last_updated,
|
|
||||||
eda_info_reference_prefix,
|
|
||||||
eda_info_value,
|
|
||||||
eda_info_invisible,
|
|
||||||
eda_info_exclude_from_bom,
|
|
||||||
eda_info_exclude_from_board,
|
|
||||||
eda_info_exclude_from_sim,
|
|
||||||
eda_info_kicad_symbol,
|
|
||||||
eda_info_kicad_footprint
|
|
||||||
) SELECT * FROM __temp__parts
|
|
||||||
SQL);
|
|
||||||
|
|
||||||
$this->addSql('DROP TABLE __temp__parts');
|
|
||||||
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE INDEX IDX_6940A7FE1ECB93AE ON "parts" (id_manufacturer)
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE INDEX IDX_6940A7FE2626CEF9 ON "parts" (id_part_unit)
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE INDEX IDX_6940A7FE5697F554 ON "parts" (id_category)
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE INDEX IDX_6940A7FE7E371A10 ON "parts" (id_footprint)
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE INDEX IDX_6940A7FEEA7100A1 ON "parts" (id_preview_attachment)
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE UNIQUE INDEX UNIQ_6940A7FE3D721C14 ON "parts" (ipn)
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE UNIQUE INDEX UNIQ_6940A7FE81081E9B ON "parts" (order_orderdetails_id)
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE UNIQUE INDEX UNIQ_6940A7FEE8AE70D9 ON "parts" (built_project_id)
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE INDEX parts_idx_datet_name_last_id_needs ON "parts" (datetime_added, name, last_modified, id, needs_review)
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE INDEX parts_idx_ipn ON "parts" (ipn)
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE INDEX parts_idx_name ON "parts" (name)
|
|
||||||
SQL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function postgreSQLUp(Schema $schema): void
|
public function postgreSQLUp(Schema $schema): void
|
||||||
{
|
{
|
||||||
$this->addSql(<<<'SQL'
|
// nothing do to, built_assembly_id not required
|
||||||
ALTER TABLE parts ADD built_assembly_id INT DEFAULT NULL
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
ALTER TABLE parts ADD CONSTRAINT FK_6940A7FECC660B3C FOREIGN KEY (built_assembly_id) REFERENCES assemblies (id) NOT DEFERRABLE INITIALLY IMMEDIATE
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE UNIQUE INDEX UNIQ_6940A7FECC660B3C ON parts (built_assembly_id)
|
|
||||||
SQL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function postgreSQLDown(Schema $schema): void
|
public function postgreSQLDown(Schema $schema): void
|
||||||
{
|
{
|
||||||
$this->addSql(<<<'SQL'
|
// nothing do to, built_assembly_id not required
|
||||||
ALTER TABLE "parts" DROP CONSTRAINT FK_6940A7FECC660B3C
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
DROP INDEX UNIQ_6940A7FECC660B3C
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
ALTER TABLE "parts" DROP built_assembly_id
|
|
||||||
SQL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
54
migrations/Version20251016124311.php
Normal file
54
migrations/Version20251016124311.php
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use App\Migration\AbstractMultiPlatformMigration;
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
|
||||||
|
final class Version20251016124311 extends AbstractMultiPlatformMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'Remove built_assembly_id from parts table';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function mySQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
ALTER TABLE parts DROP FOREIGN KEY FK_6940A7FECC660B3C
|
||||||
|
SQL);
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
DROP INDEX UNIQ_6940A7FECC660B3C ON parts
|
||||||
|
SQL);
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
ALTER TABLE `parts` DROP built_assembly_id
|
||||||
|
SQL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function mySQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
// nothing do to, built_assembly_id not required
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sqLiteUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
// nothing do to, built_assembly_id not required, already removed from Version20250304154507
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sqLiteDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
// nothing do to, built_assembly_id not required, already removed from Version20250304154507
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
// nothing do to, built_assembly_id not required, already removed from Version20250304154507
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postgreSQLDown(Schema $schema): void
|
||||||
|
{
|
||||||
|
// nothing do to, built_assembly_id not required, already removed from Version20250304154507
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -31,11 +31,8 @@ use App\Entity\AssemblySystem\AssemblyBOMEntry;
|
||||||
use App\Entity\Parts\Part;
|
use App\Entity\Parts\Part;
|
||||||
use App\Exceptions\InvalidRegexException;
|
use App\Exceptions\InvalidRegexException;
|
||||||
use App\Form\AssemblySystem\AssemblyAddPartsType;
|
use App\Form\AssemblySystem\AssemblyAddPartsType;
|
||||||
use App\Form\AssemblySystem\AssemblyBuildType;
|
|
||||||
use App\Form\Filters\AssemblyFilterType;
|
use App\Form\Filters\AssemblyFilterType;
|
||||||
use App\Helpers\Assemblies\AssemblyBuildRequest;
|
|
||||||
use App\Services\ImportExportSystem\BOMImporter;
|
use App\Services\ImportExportSystem\BOMImporter;
|
||||||
use App\Services\AssemblySystem\AssemblyBuildHelper;
|
|
||||||
use App\Services\Trees\NodesListBuilder;
|
use App\Services\Trees\NodesListBuilder;
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use Doctrine\DBAL\Exception\DriverException;
|
use Doctrine\DBAL\Exception\DriverException;
|
||||||
|
|
@ -132,7 +129,7 @@ class AssemblyController extends AbstractController
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route(path: '/{id}/info', name: 'assembly_info', requirements: ['id' => '\d+'])]
|
#[Route(path: '/{id}/info', name: 'assembly_info', requirements: ['id' => '\d+'])]
|
||||||
public function info(Assembly $assembly, Request $request, AssemblyBuildHelper $buildHelper): Response
|
public function info(Assembly $assembly, Request $request): Response
|
||||||
{
|
{
|
||||||
$this->denyAccessUnlessGranted('read', $assembly);
|
$this->denyAccessUnlessGranted('read', $assembly);
|
||||||
|
|
||||||
|
|
@ -144,56 +141,11 @@ class AssemblyController extends AbstractController
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->render('assemblies/info/info.html.twig', [
|
return $this->render('assemblies/info/info.html.twig', [
|
||||||
'buildHelper' => $buildHelper,
|
|
||||||
'datatable' => $table,
|
'datatable' => $table,
|
||||||
'assembly' => $assembly,
|
'assembly' => $assembly,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route(path: '/{id}/build', name: 'assembly_build', requirements: ['id' => '\d+'])]
|
|
||||||
public function build(Assembly $assembly, Request $request, AssemblyBuildHelper $buildHelper, EntityManagerInterface $entityManager): Response
|
|
||||||
{
|
|
||||||
$this->denyAccessUnlessGranted('read', $assembly);
|
|
||||||
|
|
||||||
//If no number of builds is given (or it is invalid), just assume 1
|
|
||||||
$number_of_builds = $request->query->getInt('n', 1);
|
|
||||||
if ($number_of_builds < 1) {
|
|
||||||
$number_of_builds = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
$assemblyBuildRequest = new AssemblyBuildRequest($assembly, $number_of_builds);
|
|
||||||
$form = $this->createForm(AssemblyBuildType::class, $assemblyBuildRequest);
|
|
||||||
|
|
||||||
$form->handleRequest($request);
|
|
||||||
if ($form->isSubmitted()) {
|
|
||||||
if ($form->isValid()) {
|
|
||||||
//Ensure that the user can withdraw stock from all parts
|
|
||||||
$this->denyAccessUnlessGranted('@parts_stock.withdraw');
|
|
||||||
|
|
||||||
//We have to do a flush already here, so that the newly created partLot gets an ID and can be logged to DB later.
|
|
||||||
$entityManager->flush();
|
|
||||||
$buildHelper->doBuild($assemblyBuildRequest);
|
|
||||||
$entityManager->flush();
|
|
||||||
$this->addFlash('success', 'assembly.build.flash.success');
|
|
||||||
|
|
||||||
return $this->redirect(
|
|
||||||
$request->get('_redirect',
|
|
||||||
$this->generateUrl('assembly_info', ['id' => $assembly->getID()]
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->addFlash('error', 'assembly.build.flash.invalid_input');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->render('assemblies/build/build.html.twig', [
|
|
||||||
'buildHelper' => $buildHelper,
|
|
||||||
'assembly' => $assembly,
|
|
||||||
'build_request' => $assemblyBuildRequest,
|
|
||||||
'number_of_builds' => $number_of_builds,
|
|
||||||
'form' => $form,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[Route(path: '/{id}/import_bom', name: 'assembly_import_bom', requirements: ['id' => '\d+'])]
|
#[Route(path: '/{id}/import_bom', name: 'assembly_import_bom', requirements: ['id' => '\d+'])]
|
||||||
public function importBOM(Request $request, EntityManagerInterface $entityManager, Assembly $assembly,
|
public function importBOM(Request $request, EntityManagerInterface $entityManager, Assembly $assembly,
|
||||||
BOMImporter $BOMImporter, ValidatorInterface $validator): Response
|
BOMImporter $BOMImporter, ValidatorInterface $validator): Response
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,6 @@ use App\Services\LogSystem\TimeTravel;
|
||||||
use App\Services\Parameters\ParameterExtractor;
|
use App\Services\Parameters\ParameterExtractor;
|
||||||
use App\Services\Parts\PartLotWithdrawAddHelper;
|
use App\Services\Parts\PartLotWithdrawAddHelper;
|
||||||
use App\Services\Parts\PricedetailHelper;
|
use App\Services\Parts\PricedetailHelper;
|
||||||
use App\Services\AssemblySystem\AssemblyBuildPartHelper;
|
|
||||||
use App\Services\ProjectSystem\ProjectBuildPartHelper;
|
use App\Services\ProjectSystem\ProjectBuildPartHelper;
|
||||||
use App\Settings\BehaviorSettings\PartInfoSettings;
|
use App\Settings\BehaviorSettings\PartInfoSettings;
|
||||||
use App\Settings\MiscSettings\IpnSuggestSettings;
|
use App\Settings\MiscSettings\IpnSuggestSettings;
|
||||||
|
|
@ -209,17 +208,14 @@ final class PartController extends AbstractController
|
||||||
#[Route(path: '/new', name: 'part_new')]
|
#[Route(path: '/new', name: 'part_new')]
|
||||||
#[Route(path: '/{id}/clone', name: 'part_clone')]
|
#[Route(path: '/{id}/clone', name: 'part_clone')]
|
||||||
#[Route(path: '/new_build_part_project/{project_id}', name: 'part_new_build_part_project')]
|
#[Route(path: '/new_build_part_project/{project_id}', name: 'part_new_build_part_project')]
|
||||||
#[Route(path: '/new_build_part_assembly/{assembly_id}', name: 'part_new_build_part_assembly')]
|
|
||||||
public function new(
|
public function new(
|
||||||
Request $request,
|
Request $request,
|
||||||
EntityManagerInterface $em,
|
EntityManagerInterface $em,
|
||||||
TranslatorInterface $translator,
|
TranslatorInterface $translator,
|
||||||
AttachmentSubmitHandler $attachmentSubmitHandler,
|
AttachmentSubmitHandler $attachmentSubmitHandler,
|
||||||
ProjectBuildPartHelper $projectBuildPartHelper,
|
ProjectBuildPartHelper $projectBuildPartHelper,
|
||||||
AssemblyBuildPartHelper $assemblyBuildPartHelper,
|
|
||||||
#[MapEntity(mapping: ['id' => 'id'])] ?Part $part = null,
|
#[MapEntity(mapping: ['id' => 'id'])] ?Part $part = null,
|
||||||
#[MapEntity(mapping: ['project_id' => 'id'])] ?Project $project = null,
|
#[MapEntity(mapping: ['project_id' => 'id'])] ?Project $project = null
|
||||||
#[MapEntity(mapping: ['assembly_id' => 'id'])] ?Assembly $assembly = null
|
|
||||||
): Response {
|
): Response {
|
||||||
|
|
||||||
if ($part instanceof Part) {
|
if ($part instanceof Part) {
|
||||||
|
|
@ -233,14 +229,6 @@ final class PartController extends AbstractController
|
||||||
return $this->redirectToRoute('part_edit', ['id' => $project->getBuildPart()->getID()]);
|
return $this->redirectToRoute('part_edit', ['id' => $project->getBuildPart()->getID()]);
|
||||||
}
|
}
|
||||||
$new_part = $projectBuildPartHelper->getPartInitialization($project);
|
$new_part = $projectBuildPartHelper->getPartInitialization($project);
|
||||||
} elseif ($assembly instanceof Assembly) {
|
|
||||||
//Initialize a new part for a build part from the given assembly
|
|
||||||
//Ensure that the assembly has not already a build part
|
|
||||||
if ($assembly->getBuildPart() instanceof Part) {
|
|
||||||
$this->addFlash('error', 'part.new_build_part.error.build_part_already_exists');
|
|
||||||
return $this->redirectToRoute('part_edit', ['id' => $project->getBuildPart()->getID()]);
|
|
||||||
}
|
|
||||||
$new_part = $assemblyBuildPartHelper->getPartInitialization($assembly);
|
|
||||||
} else { //Create an empty part from scratch
|
} else { //Create an empty part from scratch
|
||||||
$new_part = new Part();
|
$new_part = new Part();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ use Symfony\Component\Routing\Attribute\Route;
|
||||||
use Symfony\Component\Serializer\Encoder\JsonEncoder;
|
use Symfony\Component\Serializer\Encoder\JsonEncoder;
|
||||||
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
|
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
|
||||||
use Symfony\Component\Serializer\Serializer;
|
use Symfony\Component\Serializer\Serializer;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In this controller the endpoints for the typeaheads are collected.
|
* In this controller the endpoints for the typeaheads are collected.
|
||||||
|
|
@ -115,19 +116,22 @@ class TypeaheadController extends AbstractController
|
||||||
'group' => GroupParameter::class,
|
'group' => GroupParameter::class,
|
||||||
'measurement_unit' => MeasurementUnitParameter::class,
|
'measurement_unit' => MeasurementUnitParameter::class,
|
||||||
'currency' => Currency::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')]
|
#[Route(path: '/parts/search/{query}', name: 'typeahead_parts')]
|
||||||
public function parts(EntityManagerInterface $entityManager, PartPreviewGenerator $previewGenerator,
|
public function parts(
|
||||||
AttachmentURLGenerator $attachmentURLGenerator, string $query = ""): JsonResponse
|
EntityManagerInterface $entityManager,
|
||||||
{
|
PartPreviewGenerator $previewGenerator,
|
||||||
|
AttachmentURLGenerator $attachmentURLGenerator,
|
||||||
|
string $query = ""
|
||||||
|
): JsonResponse {
|
||||||
$this->denyAccessUnlessGranted('@parts.read');
|
$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 = [];
|
$data = [];
|
||||||
foreach ($parts as $part) {
|
foreach ($parts as $part) {
|
||||||
|
|
@ -147,7 +151,7 @@ class TypeaheadController extends AbstractController
|
||||||
'footprint' => $part->getFootprint() instanceof Footprint ? $part->getFootprint()->getName() : '',
|
'footprint' => $part->getFootprint() instanceof Footprint ? $part->getFootprint()->getName() : '',
|
||||||
'description' => mb_strimwidth($part->getDescription(), 0, 127, '...'),
|
'description' => mb_strimwidth($part->getDescription(), 0, 127, '...'),
|
||||||
'image' => $preview_url,
|
'image' => $preview_url,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
return new JsonResponse($data);
|
return new JsonResponse($data);
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,8 @@ class AssemblyBomEntriesDataTable implements DataTableTypeInterface
|
||||||
return htmlspecialchars((string) $context->getName());
|
return htmlspecialchars((string) $context->getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$tmp = $context->getName();
|
||||||
|
|
||||||
if ($context->getPart() !== null) {
|
if ($context->getPart() !== null) {
|
||||||
$tmp = $this->partDataTableHelper->renderName($context->getPart());
|
$tmp = $this->partDataTableHelper->renderName($context->getPart());
|
||||||
$tmp = $this->translator->trans('part.table.name.value.for_part', ['%value%' => $tmp]);
|
$tmp = $this->translator->trans('part.table.name.value.for_part', ['%value%' => $tmp]);
|
||||||
|
|
|
||||||
|
|
@ -135,17 +135,6 @@ class AssemblySearchFilter implements FilterInterface
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isCategory(): bool
|
|
||||||
{
|
|
||||||
return $this->category;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setCategory(bool $category): AssemblySearchFilter
|
|
||||||
{
|
|
||||||
$this->category = $category;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isDescription(): bool
|
public function isDescription(): bool
|
||||||
{
|
{
|
||||||
return $this->description;
|
return $this->description;
|
||||||
|
|
|
||||||
|
|
@ -141,13 +141,6 @@ class Assembly extends AbstractStructuralDBElement
|
||||||
#[Length(max: 100)]
|
#[Length(max: 100)]
|
||||||
protected ?string $ipn = null;
|
protected ?string $ipn = null;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var Part|null The (optional) part that represents the builds of this assembly in the stock
|
|
||||||
*/
|
|
||||||
#[ORM\OneToOne(mappedBy: 'built_assembly', targetEntity: Part::class, cascade: ['persist'], orphanRemoval: true)]
|
|
||||||
#[Groups(['assembly:read', 'assembly:write'])]
|
|
||||||
protected ?Part $build_part = null;
|
|
||||||
|
|
||||||
#[ORM\Column(type: Types::BOOLEAN)]
|
#[ORM\Column(type: Types::BOOLEAN)]
|
||||||
protected bool $order_only_missing_parts = false;
|
protected bool $order_only_missing_parts = false;
|
||||||
|
|
||||||
|
|
@ -338,59 +331,9 @@ class Assembly extends AbstractStructuralDBElement
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if this assembly has an associated part representing the builds of this assembly in the stock.
|
|
||||||
*/
|
|
||||||
public function hasBuildPart(): bool
|
|
||||||
{
|
|
||||||
return $this->build_part instanceof Part;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the part representing the builds of this assembly in the stock, if it is existing
|
|
||||||
*/
|
|
||||||
public function getBuildPart(): ?Part
|
|
||||||
{
|
|
||||||
return $this->build_part;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the part representing the builds of this assembly in the stock.
|
|
||||||
*/
|
|
||||||
public function setBuildPart(?Part $build_part): void
|
|
||||||
{
|
|
||||||
$this->build_part = $build_part;
|
|
||||||
if ($build_part instanceof Part) {
|
|
||||||
$build_part->setBuiltAssembly($this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[Assert\Callback]
|
#[Assert\Callback]
|
||||||
public function validate(ExecutionContextInterface $context, $payload): void
|
public function validate(ExecutionContextInterface $context, $payload): void
|
||||||
{
|
{
|
||||||
//If this assembly has subassemblies, and these have builds part, they must be included in the BOM
|
|
||||||
foreach ($this->getChildren() as $child) {
|
|
||||||
if (!$child->getBuildPart() instanceof Part) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
//We have to search all bom entries for the build part
|
|
||||||
$found = false;
|
|
||||||
foreach ($this->getBomEntries() as $bom_entry) {
|
|
||||||
if ($bom_entry->getPart() === $child->getBuildPart()) {
|
|
||||||
$found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//When the build part is not found, we have to add an error
|
|
||||||
if (!$found) {
|
|
||||||
$context->buildViolation('assembly.bom_has_to_include_all_subelement_parts')
|
|
||||||
->atPath('bom_entries')
|
|
||||||
->setParameter('%assembly_name%', $child->getName())
|
|
||||||
->setParameter('%part_name%', $child->getBuildPart()->getName())
|
|
||||||
->addViolation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -326,22 +326,6 @@ class AssemblyBOMEntry extends AbstractDBElement implements UniqueValidatableInt
|
||||||
if (!$this->part instanceof Part) {
|
if (!$this->part instanceof Part) {
|
||||||
$this->quantity = round($this->quantity);
|
$this->quantity = round($this->quantity);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Check that the part is not the build representation part of this assembly or one of its parents
|
|
||||||
if ($this->part && $this->part->getBuiltAssembly() instanceof Assembly) {
|
|
||||||
//Get the associated assembly
|
|
||||||
$associated_assembly = $this->part->getBuiltAssembly();
|
|
||||||
//Check that it is not the same as the current assembly neither one of its parents
|
|
||||||
$current_assembly = $this->assembly;
|
|
||||||
while ($current_assembly) {
|
|
||||||
if ($associated_assembly === $current_assembly) {
|
|
||||||
$context->buildViolation('assembly.bom_entry.can_not_add_own_builds_part')
|
|
||||||
->atPath('part')
|
|
||||||
->addViolation();
|
|
||||||
}
|
|
||||||
$current_assembly = $current_assembly->getParent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,13 +18,6 @@ trait AssemblyTrait
|
||||||
#[ORM\OneToMany(mappedBy: 'part', targetEntity: AssemblyBOMEntry::class, cascade: ['remove'], orphanRemoval: true)]
|
#[ORM\OneToMany(mappedBy: 'part', targetEntity: AssemblyBOMEntry::class, cascade: ['remove'], orphanRemoval: true)]
|
||||||
protected Collection $assembly_bom_entries;
|
protected Collection $assembly_bom_entries;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var Assembly|null If a assembly is set here, then this part is special and represents the builds of an assembly.
|
|
||||||
*/
|
|
||||||
#[ORM\OneToOne(inversedBy: 'build_part', targetEntity: Assembly::class)]
|
|
||||||
#[ORM\JoinColumn]
|
|
||||||
protected ?Assembly $built_assembly = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all AssemblyBOMEntry that use this part.
|
* Returns all AssemblyBOMEntry that use this part.
|
||||||
*
|
*
|
||||||
|
|
@ -35,36 +28,6 @@ trait AssemblyTrait
|
||||||
return $this->assembly_bom_entries;
|
return $this->assembly_bom_entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether this part represents the builds of a assembly
|
|
||||||
* @return bool True if it represents the builds, false if not
|
|
||||||
*/
|
|
||||||
#[Groups(['part:read'])]
|
|
||||||
public function isAssemblyBuildPart(): bool
|
|
||||||
{
|
|
||||||
return $this->built_assembly !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the assembly that this part represents the builds of, or null if it doesn't
|
|
||||||
*/
|
|
||||||
public function getBuiltAssembly(): ?Assembly
|
|
||||||
{
|
|
||||||
return $this->built_assembly;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the assembly that this part represents the builds of
|
|
||||||
* @param Assembly|null $built_assembly The assembly that this part represents the builds of, or null if it is not a build part
|
|
||||||
*/
|
|
||||||
public function setBuiltAssembly(?Assembly $built_assembly): self
|
|
||||||
{
|
|
||||||
$this->built_assembly = $built_assembly;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all assemblies which uses this part.
|
* Get all assemblies which uses this part.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ class AssemblyAdminForm extends BaseEntityAdminForm
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected Security $security,
|
protected Security $security,
|
||||||
protected EventCommentNeededHelper $eventCommentNeededHelper,
|
protected EventCommentNeededHelper $eventCommentNeededHelper,
|
||||||
protected AssemblySettings $assemblySettings,
|
protected ?AssemblySettings $assemblySettings = null,
|
||||||
) {
|
) {
|
||||||
parent::__construct($security, $eventCommentNeededHelper, $assemblySettings);
|
parent::__construct($security, $eventCommentNeededHelper, $assemblySettings);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ class BaseEntityAdminForm extends AbstractType
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected Security $security,
|
protected Security $security,
|
||||||
protected EventCommentNeededHelper $eventCommentNeededHelper,
|
protected EventCommentNeededHelper $eventCommentNeededHelper,
|
||||||
protected AssemblySettings $assemblySettings,
|
protected ?AssemblySettings $assemblySettings = null,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,7 +74,7 @@ class BaseEntityAdminForm extends AbstractType
|
||||||
->add('name', TextType::class, [
|
->add('name', TextType::class, [
|
||||||
'empty_data' => '',
|
'empty_data' => '',
|
||||||
'label' => 'name.label',
|
'label' => 'name.label',
|
||||||
'data' => $is_new && $entity instanceof Assembly && $this->assemblySettings->useIpnPlaceholderInName ? '%%ipn%%' : $entity->getName(),
|
'data' => $is_new && $entity instanceof Assembly && $this->assemblySettings !== null && $this->assemblySettings->useIpnPlaceholderInName ? '%%ipn%%' : $entity->getName(),
|
||||||
'attr' => [
|
'attr' => [
|
||||||
'placeholder' => 'part.name.placeholder',
|
'placeholder' => 'part.name.placeholder',
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ use App\Form\Type\AssemblySelectType;
|
||||||
use App\Form\Type\BigDecimalNumberType;
|
use App\Form\Type\BigDecimalNumberType;
|
||||||
use App\Form\Type\CurrencyEntityType;
|
use App\Form\Type\CurrencyEntityType;
|
||||||
use App\Form\Type\PartSelectType;
|
use App\Form\Type\PartSelectType;
|
||||||
use App\Form\Type\ProjectSelectType;
|
|
||||||
use App\Form\Type\RichTextEditorType;
|
use App\Form\Type\RichTextEditorType;
|
||||||
use App\Form\Type\SIUnitType;
|
use App\Form\Type\SIUnitType;
|
||||||
use Symfony\Component\Form\AbstractType;
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
|
|
||||||
|
|
@ -1,182 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
|
||||||
*
|
|
||||||
* Copyright (C) 2019 - 2023 Jan Böhmer (https://github.com/jbtronics)
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published
|
|
||||||
* by the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
namespace App\Form\AssemblySystem;
|
|
||||||
|
|
||||||
use App\Helpers\Assemblies\AssemblyBuildRequest;
|
|
||||||
use Symfony\Bundle\SecurityBundle\Security;
|
|
||||||
use App\Entity\Parts\Part;
|
|
||||||
use App\Entity\Parts\PartLot;
|
|
||||||
use App\Form\Type\PartLotSelectType;
|
|
||||||
use App\Form\Type\SIUnitType;
|
|
||||||
use Symfony\Component\Form\AbstractType;
|
|
||||||
use Symfony\Component\Form\DataMapperInterface;
|
|
||||||
use Symfony\Component\Form\Event\PreSetDataEvent;
|
|
||||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
|
||||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
|
||||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
|
||||||
use Symfony\Component\Form\FormEvents;
|
|
||||||
use Symfony\Component\Form\FormInterface;
|
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
|
||||||
|
|
||||||
class AssemblyBuildType extends AbstractType implements DataMapperInterface
|
|
||||||
{
|
|
||||||
public function __construct(private readonly Security $security)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function configureOptions(OptionsResolver $resolver): void
|
|
||||||
{
|
|
||||||
$resolver->setDefaults([
|
|
||||||
'compound' => true,
|
|
||||||
'data_class' => AssemblyBuildRequest::class
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
|
||||||
{
|
|
||||||
$builder->setDataMapper($this);
|
|
||||||
|
|
||||||
$builder->add('submit', SubmitType::class, [
|
|
||||||
'label' => 'assembly.build.btn_build',
|
|
||||||
'disabled' => !$this->security->isGranted('@parts_stock.withdraw'),
|
|
||||||
]);
|
|
||||||
|
|
||||||
$builder->add('dontCheckQuantity', CheckboxType::class, [
|
|
||||||
'label' => 'assembly.build.dont_check_quantity',
|
|
||||||
'help' => 'assembly.build.dont_check_quantity.help',
|
|
||||||
'required' => false,
|
|
||||||
'attr' => [
|
|
||||||
'data-controller' => 'pages--dont-check-quantity-checkbox'
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
|
|
||||||
$builder->add('comment', TextType::class, [
|
|
||||||
'label' => 'part.info.withdraw_modal.comment',
|
|
||||||
'help' => 'part.info.withdraw_modal.comment.hint',
|
|
||||||
'empty_data' => '',
|
|
||||||
'required' => false,
|
|
||||||
]);
|
|
||||||
|
|
||||||
//The form is initially empty, define the fields after we know the data
|
|
||||||
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (PreSetDataEvent $event) {
|
|
||||||
$form = $event->getForm();
|
|
||||||
/** @var AssemblyBuildRequest $assemblyBuildRequest */
|
|
||||||
$assemblyBuildRequest = $event->getData();
|
|
||||||
|
|
||||||
$form->add('addBuildsToBuildsPart', CheckboxType::class, [
|
|
||||||
'label' => 'assembly.build.add_builds_to_builds_part',
|
|
||||||
'required' => false,
|
|
||||||
'disabled' => !$assemblyBuildRequest->getAssembly()->getBuildPart() instanceof Part,
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($assemblyBuildRequest->getAssembly()->getBuildPart() instanceof Part) {
|
|
||||||
$form->add('buildsPartLot', PartLotSelectType::class, [
|
|
||||||
'label' => 'assembly.build.builds_part_lot',
|
|
||||||
'required' => false,
|
|
||||||
'part' => $assemblyBuildRequest->getAssembly()->getBuildPart(),
|
|
||||||
'placeholder' => 'assembly.build.buildsPartLot.new_lot'
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($assemblyBuildRequest->getPartBomEntries() as $bomEntry) {
|
|
||||||
//Every part lot has a field to specify the number of parts to take from this lot
|
|
||||||
foreach ($assemblyBuildRequest->getPartLotsForBOMEntry($bomEntry) as $lot) {
|
|
||||||
$form->add('lot_' . $lot->getID(), SIUnitType::class, [
|
|
||||||
'label' => false,
|
|
||||||
'measurement_unit' => $bomEntry->getPart()->getPartUnit(),
|
|
||||||
'max' => min($assemblyBuildRequest->getNeededAmountForBOMEntry($bomEntry), $lot->getAmount()),
|
|
||||||
'disabled' => !$this->security->isGranted('withdraw', $lot),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public function mapDataToForms($data, \Traversable $forms): void
|
|
||||||
{
|
|
||||||
if (!$data instanceof AssemblyBuildRequest) {
|
|
||||||
throw new \RuntimeException('Data must be an instance of ' . AssemblyBuildRequest::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @var FormInterface[] $forms */
|
|
||||||
$forms = iterator_to_array($forms);
|
|
||||||
foreach ($forms as $key => $form) {
|
|
||||||
//Extract the lot id from the form name
|
|
||||||
$matches = [];
|
|
||||||
if (preg_match('/^lot_(\d+)$/', $key, $matches)) {
|
|
||||||
$lot_id = (int) $matches[1];
|
|
||||||
$form->setData($data->getLotWithdrawAmount($lot_id));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$forms['comment']->setData($data->getComment());
|
|
||||||
$forms['dontCheckQuantity']->setData($data->isDontCheckQuantity());
|
|
||||||
$forms['addBuildsToBuildsPart']->setData($data->getAddBuildsToBuildsPart());
|
|
||||||
if (isset($forms['buildsPartLot'])) {
|
|
||||||
$forms['buildsPartLot']->setData($data->getBuildsPartLot());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function mapFormsToData(\Traversable $forms, &$data): void
|
|
||||||
{
|
|
||||||
if (!$data instanceof AssemblyBuildRequest) {
|
|
||||||
throw new \RuntimeException('Data must be an instance of ' . AssemblyBuildRequest::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @var FormInterface[] $forms */
|
|
||||||
$forms = iterator_to_array($forms);
|
|
||||||
|
|
||||||
foreach ($forms as $key => $form) {
|
|
||||||
//Extract the lot id from the form name
|
|
||||||
$matches = [];
|
|
||||||
if (preg_match('/^lot_(\d+)$/', $key, $matches)) {
|
|
||||||
$lot_id = (int) $matches[1];
|
|
||||||
$data->setLotWithdrawAmount($lot_id, (float) $form->getData());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$data->setComment($forms['comment']->getData());
|
|
||||||
$data->setDontCheckQuantity($forms['dontCheckQuantity']->getData());
|
|
||||||
|
|
||||||
if (isset($forms['buildsPartLot'])) {
|
|
||||||
$lot = $forms['buildsPartLot']->getData();
|
|
||||||
if (!$lot) { //When the user selected "Create new lot", create a new lot
|
|
||||||
$lot = new PartLot();
|
|
||||||
$description = 'Build ' . date('Y-m-d H:i:s');
|
|
||||||
if ($data->getComment() !== '') {
|
|
||||||
$description .= ' (' . $data->getComment() . ')';
|
|
||||||
}
|
|
||||||
$lot->setDescription($description);
|
|
||||||
|
|
||||||
$data->getAssembly()->getBuildPart()->addPartLot($lot);
|
|
||||||
}
|
|
||||||
|
|
||||||
$data->setBuildsPartLot($lot);
|
|
||||||
}
|
|
||||||
//This has to be set after the builds part lot, so that it can disable the option
|
|
||||||
$data->setAddBuildsToBuildsPart($forms['addBuildsToBuildsPart']->getData());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -114,6 +114,8 @@ class LogFilterType extends AbstractType
|
||||||
LogTargetType::CATEGORY => 'category.label',
|
LogTargetType::CATEGORY => 'category.label',
|
||||||
LogTargetType::PROJECT => 'project.label',
|
LogTargetType::PROJECT => 'project.label',
|
||||||
LogTargetType::BOM_ENTRY => 'project_bom_entry.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::FOOTPRINT => 'footprint.label',
|
||||||
LogTargetType::GROUP => 'group.label',
|
LogTargetType::GROUP => 'group.label',
|
||||||
LogTargetType::MANUFACTURER => 'manufacturer.label',
|
LogTargetType::MANUFACTURER => 'manufacturer.label',
|
||||||
|
|
|
||||||
|
|
@ -1,124 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace App\Form\Type;
|
|
||||||
|
|
||||||
use App\Entity\Attachments\Attachment;
|
|
||||||
use App\Entity\ProjectSystem\Project;
|
|
||||||
use App\Services\Attachments\ProjectPreviewGenerator;
|
|
||||||
use App\Services\Attachments\AttachmentURLGenerator;
|
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
|
||||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
|
||||||
use Symfony\Component\Form\AbstractType;
|
|
||||||
use Symfony\Component\Form\ChoiceList\ChoiceList;
|
|
||||||
use Symfony\Component\Form\DataMapperInterface;
|
|
||||||
use Symfony\Component\Form\Event\PreSetDataEvent;
|
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
|
||||||
use Symfony\Component\Form\FormEvent;
|
|
||||||
use Symfony\Component\Form\FormEvents;
|
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
|
||||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
|
||||||
|
|
||||||
class ProjectSelectType extends AbstractType implements DataMapperInterface
|
|
||||||
{
|
|
||||||
public function __construct(private readonly UrlGeneratorInterface $urlGenerator, private readonly EntityManagerInterface $em, private readonly ProjectPreviewGenerator $previewGenerator, private readonly AttachmentURLGenerator $attachmentURLGenerator)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
|
||||||
{
|
|
||||||
//At initialization, we have to fill the form element with our selected data, so the user can see it
|
|
||||||
$builder->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' => Project::class,
|
|
||||||
'choice_label' => 'name',
|
|
||||||
'compound' => true,
|
|
||||||
'error_bubbling' => false,
|
|
||||||
]);
|
|
||||||
|
|
||||||
error_log($this->urlGenerator->generate('typeahead_projects', ['query' => '__QUERY__']));
|
|
||||||
|
|
||||||
$resolver->setDefaults([
|
|
||||||
'attr' => [
|
|
||||||
'data-controller' => 'elements--project-select',
|
|
||||||
'data-autocomplete' => $this->urlGenerator->generate('typeahead_projects', ['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 (?Project $project) {
|
|
||||||
if($project instanceof Project) {
|
|
||||||
//Determine the picture to show:
|
|
||||||
$preview_attachment = $this->previewGenerator->getTablePreviewAttachment($project);
|
|
||||||
if ($preview_attachment instanceof Attachment) {
|
|
||||||
$preview_url = $this->attachmentURLGenerator->getThumbnailURL($preview_attachment,
|
|
||||||
'thumbnail_sm');
|
|
||||||
} else {
|
|
||||||
$preview_url = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $project instanceof Project ? [
|
|
||||||
'data-description' => $project->getDescription() ? mb_strimwidth($project->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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,306 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
|
||||||
*
|
|
||||||
* Copyright (C) 2019 - 2023 Jan Böhmer (https://github.com/jbtronics)
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published
|
|
||||||
* by the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
namespace App\Helpers\Assemblies;
|
|
||||||
|
|
||||||
use App\Entity\Parts\Part;
|
|
||||||
use App\Entity\Parts\PartLot;
|
|
||||||
use App\Entity\AssemblySystem\Assembly;
|
|
||||||
use App\Entity\AssemblySystem\AssemblyBOMEntry;
|
|
||||||
use App\Validator\Constraints\AssemblySystem\ValidAssemblyBuildRequest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see \App\Tests\Helpers\Assemblies\AssemblyBuildRequestTest
|
|
||||||
*/
|
|
||||||
#[ValidAssemblyBuildRequest]
|
|
||||||
final class AssemblyBuildRequest
|
|
||||||
{
|
|
||||||
private readonly int $number_of_builds;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array<int, float>
|
|
||||||
*/
|
|
||||||
private array $withdraw_amounts = [];
|
|
||||||
|
|
||||||
private string $comment = '';
|
|
||||||
|
|
||||||
private ?PartLot $builds_lot = null;
|
|
||||||
|
|
||||||
private bool $add_build_to_builds_part = false;
|
|
||||||
|
|
||||||
private bool $dont_check_quantity = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Assembly $assembly The assembly that should be build
|
|
||||||
* @param int $number_of_builds The number of builds that should be created
|
|
||||||
*/
|
|
||||||
public function __construct(private readonly Assembly $assembly, int $number_of_builds)
|
|
||||||
{
|
|
||||||
if ($number_of_builds < 1) {
|
|
||||||
throw new \InvalidArgumentException('Number of builds must be at least 1!');
|
|
||||||
}
|
|
||||||
$this->number_of_builds = $number_of_builds;
|
|
||||||
|
|
||||||
$this->initializeArray();
|
|
||||||
|
|
||||||
//By default, use the first available lot of builds part if there is one.
|
|
||||||
if($assembly->getBuildPart() instanceof Part) {
|
|
||||||
$this->add_build_to_builds_part = true;
|
|
||||||
foreach( $assembly->getBuildPart()->getPartLots() as $lot) {
|
|
||||||
if (!$lot->isInstockUnknown()) {
|
|
||||||
$this->builds_lot = $lot;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function initializeArray(): void
|
|
||||||
{
|
|
||||||
//Completely reset the array
|
|
||||||
$this->withdraw_amounts = [];
|
|
||||||
|
|
||||||
//Now create an array for each BOM entry
|
|
||||||
foreach ($this->getPartBomEntries() as $bom_entry) {
|
|
||||||
$remaining_amount = $this->getNeededAmountForBOMEntry($bom_entry);
|
|
||||||
foreach($this->getPartLotsForBOMEntry($bom_entry) as $lot) {
|
|
||||||
//If the lot has instock use it for the build
|
|
||||||
$this->withdraw_amounts[$lot->getID()] = min($remaining_amount, $lot->getAmount());
|
|
||||||
$remaining_amount -= max(0, $this->withdraw_amounts[$lot->getID()]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensure that the assemblyBOMEntry belongs to the assembly, otherwise throw an exception.
|
|
||||||
*/
|
|
||||||
private function ensureBOMEntryValid(AssemblyBOMEntry $entry): void
|
|
||||||
{
|
|
||||||
if ($entry->getAssembly() !== $this->assembly) {
|
|
||||||
throw new \InvalidArgumentException('The given BOM entry does not belong to the assembly!');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the partlot where the builds should be added to, or null if it should not be added to any lot.
|
|
||||||
*/
|
|
||||||
public function getBuildsPartLot(): ?PartLot
|
|
||||||
{
|
|
||||||
return $this->builds_lot;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return if the builds should be added to the builds part of this assembly as new stock
|
|
||||||
*/
|
|
||||||
public function getAddBuildsToBuildsPart(): bool
|
|
||||||
{
|
|
||||||
return $this->add_build_to_builds_part;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set if the builds should be added to the builds part of this assembly as new stock
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setAddBuildsToBuildsPart(bool $new_value): self
|
|
||||||
{
|
|
||||||
$this->add_build_to_builds_part = $new_value;
|
|
||||||
|
|
||||||
if ($new_value === false) {
|
|
||||||
$this->builds_lot = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the partlot where the builds should be added to, or null if it should not be added to any lot.
|
|
||||||
* The part lot must belong to the assembly build part, or an exception is thrown!
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setBuildsPartLot(?PartLot $new_part_lot): self
|
|
||||||
{
|
|
||||||
//Ensure that this new_part_lot belongs to the assembly
|
|
||||||
if (($new_part_lot instanceof PartLot && $new_part_lot->getPart() !== $this->assembly->getBuildPart()) || !$this->assembly->getBuildPart() instanceof Part) {
|
|
||||||
throw new \InvalidArgumentException('The given part lot does not belong to the assemblies build part!');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($new_part_lot instanceof PartLot) {
|
|
||||||
$this->setAddBuildsToBuildsPart(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->builds_lot = $new_part_lot;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the comment where the user can write additional information about the build.
|
|
||||||
*/
|
|
||||||
public function getComment(): string
|
|
||||||
{
|
|
||||||
return $this->comment;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the comment where the user can write additional information about the build.
|
|
||||||
*/
|
|
||||||
public function setComment(string $comment): void
|
|
||||||
{
|
|
||||||
$this->comment = $comment;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the amount of parts that should be withdrawn from the given lot for the corresponding BOM entry.
|
|
||||||
* @param PartLot|int $lot The part lot (or the ID of the part lot) for which the withdrawal amount should be got
|
|
||||||
*/
|
|
||||||
public function getLotWithdrawAmount(PartLot|int $lot): float
|
|
||||||
{
|
|
||||||
$lot_id = $lot instanceof PartLot ? $lot->getID() : $lot;
|
|
||||||
|
|
||||||
if (! array_key_exists($lot_id, $this->withdraw_amounts)) {
|
|
||||||
throw new \InvalidArgumentException('The given lot is not in the withdraw amounts array!');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->withdraw_amounts[$lot_id];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the amount of parts that should be withdrawn from the given lot for the corresponding BOM entry.
|
|
||||||
* @param PartLot|int $lot The part lot (or the ID of the part lot) for which the withdrawal amount should be got
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setLotWithdrawAmount(PartLot|int $lot, float $amount): self
|
|
||||||
{
|
|
||||||
if ($lot instanceof PartLot) {
|
|
||||||
$lot_id = $lot->getID();
|
|
||||||
} elseif (is_int($lot)) {
|
|
||||||
$lot_id = $lot;
|
|
||||||
} else {
|
|
||||||
throw new \InvalidArgumentException('The given lot must be an instance of PartLot or an ID of a PartLot!');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->withdraw_amounts[$lot_id] = $amount;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the sum of all withdraw amounts for the given BOM entry.
|
|
||||||
*/
|
|
||||||
public function getWithdrawAmountSum(AssemblyBOMEntry $entry): float
|
|
||||||
{
|
|
||||||
$this->ensureBOMEntryValid($entry);
|
|
||||||
|
|
||||||
$sum = 0;
|
|
||||||
foreach ($this->getPartLotsForBOMEntry($entry) as $lot) {
|
|
||||||
$sum += $this->getLotWithdrawAmount($lot);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($entry->getPart() && !$entry->getPart()->useFloatAmount()) {
|
|
||||||
$sum = round($sum);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of available lots to take stock from for the given BOM entry.
|
|
||||||
* @return PartLot[]|null Returns null if the entry is a non-part BOM entry
|
|
||||||
*/
|
|
||||||
public function getPartLotsForBOMEntry(AssemblyBOMEntry $assemblyBOMEntry): ?array
|
|
||||||
{
|
|
||||||
$this->ensureBOMEntryValid($assemblyBOMEntry);
|
|
||||||
|
|
||||||
if (!$assemblyBOMEntry->getPart() instanceof Part) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Filter out all lots which have unknown instock
|
|
||||||
return $assemblyBOMEntry->getPart()->getPartLots()->filter(fn (PartLot $lot) => !$lot->isInstockUnknown())->toArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the needed amount of parts for the given BOM entry.
|
|
||||||
*/
|
|
||||||
public function getNeededAmountForBOMEntry(AssemblyBOMEntry $entry): float
|
|
||||||
{
|
|
||||||
$this->ensureBOMEntryValid($entry);
|
|
||||||
|
|
||||||
return $entry->getQuantity() * $this->number_of_builds;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the list of all bom entries.
|
|
||||||
* @return AssemblyBOMEntry[]
|
|
||||||
*/
|
|
||||||
public function getBomEntries(): array
|
|
||||||
{
|
|
||||||
return $this->assembly->getBomEntries()->toArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns all part bom entries.
|
|
||||||
* @return AssemblyBOMEntry[]
|
|
||||||
*/
|
|
||||||
public function getPartBomEntries(): array
|
|
||||||
{
|
|
||||||
return $this->assembly->getBomEntries()->filter(fn(AssemblyBOMEntry $entry) => $entry->isPartBomEntry())->toArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns which assembly should be build
|
|
||||||
*/
|
|
||||||
public function getAssembly(): Assembly
|
|
||||||
{
|
|
||||||
return $this->assembly;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of builds that should be created.
|
|
||||||
*/
|
|
||||||
public function getNumberOfBuilds(): int
|
|
||||||
{
|
|
||||||
return $this->number_of_builds;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If Set to true, the given withdraw amounts are used without any checks for requirements.
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isDontCheckQuantity(): bool
|
|
||||||
{
|
|
||||||
return $this->dont_check_quantity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set to true, the given withdraw amounts are used without any checks for requirements.
|
|
||||||
* @param bool $dont_check_quantity
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setDontCheckQuantity(bool $dont_check_quantity): AssemblyBuildRequest
|
|
||||||
{
|
|
||||||
$this->dont_check_quantity = $dont_check_quantity;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -45,7 +45,7 @@ use App\Entity\AssemblySystem\Assembly;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @template TEntityClass of Assembly
|
* @template TEntityClass of Assembly
|
||||||
* @extends DBElementRepository<TEntityClass>
|
* @extends StructuralDBElementRepository<TEntityClass>
|
||||||
*/
|
*/
|
||||||
class AssemblyRepository extends StructuralDBElementRepository
|
class AssemblyRepository extends StructuralDBElementRepository
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -51,22 +51,4 @@ class DeviceRepository extends StructuralDBElementRepository
|
||||||
//Prevent user from deleting devices, to not accidentally remove filled devices from old versions
|
//Prevent user from deleting devices, to not accidentally remove filled devices from old versions
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Project[]
|
|
||||||
*/
|
|
||||||
public function autocompleteSearch(string $query, int $max_limits = 50): array
|
|
||||||
{
|
|
||||||
$qb = $this->createQueryBuilder('project');
|
|
||||||
$qb->select('project')
|
|
||||||
->where('ILIKE(project.name, :query) = TRUE')
|
|
||||||
->orWhere('ILIKE(project.description, :query) = TRUE');
|
|
||||||
|
|
||||||
$qb->setParameter('query', '%'.$query.'%');
|
|
||||||
|
|
||||||
$qb->setMaxResults($max_limits);
|
|
||||||
$qb->orderBy('NATSORT(project.name)', 'ASC');
|
|
||||||
|
|
||||||
return $qb->getQuery()->getResult();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,166 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
|
||||||
*
|
|
||||||
* Copyright (C) 2019 - 2023 Jan Böhmer (https://github.com/jbtronics)
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published
|
|
||||||
* by the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
namespace App\Services\AssemblySystem;
|
|
||||||
|
|
||||||
use App\Entity\AssemblySystem\Assembly;
|
|
||||||
use App\Entity\AssemblySystem\AssemblyBOMEntry;
|
|
||||||
use App\Entity\Parts\Part;
|
|
||||||
use App\Helpers\Assemblies\AssemblyBuildRequest;
|
|
||||||
use App\Services\Parts\PartLotWithdrawAddHelper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see \App\Tests\Services\AssemblySystem\AssemblyBuildHelperTest
|
|
||||||
*/
|
|
||||||
class AssemblyBuildHelper
|
|
||||||
{
|
|
||||||
public function __construct(
|
|
||||||
private readonly PartLotWithdrawAddHelper $withdraw_add_helper
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the maximum buildable amount of the given BOM entry based on the stock of the used parts.
|
|
||||||
* This function only works for BOM entries that are associated with a part.
|
|
||||||
*/
|
|
||||||
public function getMaximumBuildableCountForBOMEntry(AssemblyBOMEntry $assemblyBOMEntry): int
|
|
||||||
{
|
|
||||||
$part = $assemblyBOMEntry->getPart();
|
|
||||||
|
|
||||||
if (!$part instanceof Part) {
|
|
||||||
throw new \InvalidArgumentException('This function cannot determine the maximum buildable count for a BOM entry without a part!');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($assemblyBOMEntry->getQuantity() <= 0) {
|
|
||||||
throw new \RuntimeException('The quantity of the BOM entry must be greater than 0!');
|
|
||||||
}
|
|
||||||
|
|
||||||
$amount_sum = $part->getAmountSum();
|
|
||||||
|
|
||||||
return (int) floor($amount_sum / $assemblyBOMEntry->getQuantity());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the maximum buildable amount of the given assembly, based on the stock of the used parts in the BOM.
|
|
||||||
*/
|
|
||||||
public function getMaximumBuildableCount(Assembly $assembly): int
|
|
||||||
{
|
|
||||||
$maximum_buildable_count = PHP_INT_MAX;
|
|
||||||
/** @var AssemblyBOMEntry $bom_entry */
|
|
||||||
foreach ($assembly->getBomEntries() as $bom_entry) {
|
|
||||||
//Skip BOM entries without a part (as we can not determine that)
|
|
||||||
if (!$bom_entry->isPartBomEntry() && !$bom_entry->isAssemblyBomEntry()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//The maximum buildable count for the whole assembly is the minimum of all BOM entries
|
|
||||||
if ($bom_entry->getPart() !== null) {
|
|
||||||
$maximum_buildable_count = min($maximum_buildable_count, $this->getMaximumBuildableCountForBOMEntry($bom_entry));
|
|
||||||
} elseif ($bom_entry->getReferencedAssembly() !== null) {
|
|
||||||
$maximum_buildable_count = min($maximum_buildable_count, $this->getMaximumBuildableCount($bom_entry->getReferencedAssembly()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $maximum_buildable_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the given assembly can be built with the current stock.
|
|
||||||
* This means that the maximum buildable count is greater or equal than the requested $number_of_assemblies
|
|
||||||
* @param int $number_of_builds
|
|
||||||
*/
|
|
||||||
public function isAssemblyBuildable(Assembly $assembly, int $number_of_builds = 1): bool
|
|
||||||
{
|
|
||||||
return $this->getMaximumBuildableCount($assembly) >= $number_of_builds;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the given BOM entry can be built with the current stock.
|
|
||||||
* This means that the maximum buildable count is greater or equal than the requested $number_of_assemblies
|
|
||||||
*/
|
|
||||||
public function isBOMEntryBuildable(AssemblyBOMEntry $bom_entry, int $number_of_builds = 1): bool
|
|
||||||
{
|
|
||||||
return $this->getMaximumBuildableCountForBOMEntry($bom_entry) >= $number_of_builds;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the referenced assembly BOM entries for which parts are missing in the stock for the given number of builds
|
|
||||||
* @param Assembly $assembly The assembly for which the BOM entries should be checked
|
|
||||||
* @param int $number_of_builds How often should the assembly be build?
|
|
||||||
* @return AssemblyBOMEntry[]
|
|
||||||
*/
|
|
||||||
public function getNonBuildableAssemblyBomEntries(Assembly $assembly, int $number_of_builds = 1): array
|
|
||||||
{
|
|
||||||
if ($number_of_builds < 1) {
|
|
||||||
throw new \InvalidArgumentException('The number of builds must be greater than 0!');
|
|
||||||
}
|
|
||||||
|
|
||||||
$nonBuildableEntries = [];
|
|
||||||
|
|
||||||
/** @var AssemblyBOMEntry $bomEntry */
|
|
||||||
foreach ($assembly->getBomEntries() as $bomEntry) {
|
|
||||||
$part = $bomEntry->getPart();
|
|
||||||
|
|
||||||
//Skip BOM entries without a part (as we can not determine that)
|
|
||||||
if (!$part instanceof Part && $bomEntry->getReferencedAssembly() === null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($bomEntry->getPart() !== null) {
|
|
||||||
$amount_sum = $part->getAmountSum();
|
|
||||||
|
|
||||||
if ($amount_sum < $bomEntry->getQuantity() * $number_of_builds) {
|
|
||||||
$nonBuildableEntries[] = $bomEntry;
|
|
||||||
}
|
|
||||||
} elseif ($bomEntry->getReferencedAssembly() !== null) {
|
|
||||||
$nonBuildableAssemblyEntries = $this->getNonBuildableAssemblyBomEntries($bomEntry->getReferencedAssembly(), $number_of_builds);
|
|
||||||
$nonBuildableEntries = array_merge($nonBuildableEntries, $nonBuildableAssemblyEntries);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $nonBuildableEntries;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Withdraw the parts from the stock using the given AssemblyBuildRequest and create the build parts entries, if needed.
|
|
||||||
* The AssemblyBuildRequest has to be validated before!!
|
|
||||||
* You have to flush changes to DB afterward
|
|
||||||
*/
|
|
||||||
public function doBuild(AssemblyBuildRequest $buildRequest): void
|
|
||||||
{
|
|
||||||
$message = $buildRequest->getComment();
|
|
||||||
$message .= ' (Assembly build: '.$buildRequest->getAssembly()->getName().')';
|
|
||||||
|
|
||||||
foreach ($buildRequest->getPartBomEntries() as $bom_entry) {
|
|
||||||
foreach ($buildRequest->getPartLotsForBOMEntry($bom_entry) as $part_lot) {
|
|
||||||
$amount = $buildRequest->getLotWithdrawAmount($part_lot);
|
|
||||||
if ($amount > 0) {
|
|
||||||
$this->withdraw_add_helper->withdraw($part_lot, $amount, $message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($buildRequest->getAddBuildsToBuildsPart()) {
|
|
||||||
$this->withdraw_add_helper->add($buildRequest->getBuildsPartLot(), $buildRequest->getNumberOfBuilds(), $message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace App\Services\AssemblySystem;
|
|
||||||
|
|
||||||
use App\Entity\AssemblySystem\Assembly;
|
|
||||||
use App\Entity\Parts\Part;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see \App\Tests\Services\AssemblySystem\AssemblyBuildPartHelperTest
|
|
||||||
*/
|
|
||||||
class AssemblyBuildPartHelper
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Returns a part that represents the builds of a assembly. This part is not saved to the database, and can be used
|
|
||||||
* as initial data for the new part form.
|
|
||||||
*/
|
|
||||||
public function getPartInitialization(Assembly $assembly): Part
|
|
||||||
{
|
|
||||||
$part = new Part();
|
|
||||||
|
|
||||||
//Associate the part with the assembly
|
|
||||||
$part->setBuiltAssembly($assembly);
|
|
||||||
|
|
||||||
//Set the name of the part to the name of the assembly
|
|
||||||
$part->setName($assembly->getName());
|
|
||||||
|
|
||||||
//Set the description of the part to the description of the assembly
|
|
||||||
$part->setDescription($assembly->getDescription());
|
|
||||||
|
|
||||||
//Add a tag to the part that indicates that it is a build part
|
|
||||||
$part->setTags('assembly-build');
|
|
||||||
|
|
||||||
//Associate the part with the assembly
|
|
||||||
$assembly->setBuildPart($part);
|
|
||||||
|
|
||||||
return $part;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,93 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
|
||||||
*
|
|
||||||
* Copyright (C) 2019 - 2022 Jan Böhmer (https://github.com/jbtronics)
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published
|
|
||||||
* by the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace App\Services\Attachments;
|
|
||||||
|
|
||||||
use App\Entity\Attachments\Attachment;
|
|
||||||
use App\Entity\ProjectSystem\Project;
|
|
||||||
|
|
||||||
class ProjectPreviewGenerator
|
|
||||||
{
|
|
||||||
public function __construct(protected AttachmentManager $attachmentHelper)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a list of attachments that can be used for previewing the project ordered by priority.
|
|
||||||
*
|
|
||||||
* @param Project $project the project for which the attachments should be determined
|
|
||||||
*
|
|
||||||
* @return (Attachment|null)[]
|
|
||||||
*
|
|
||||||
* @psalm-return list<Attachment|null>
|
|
||||||
*/
|
|
||||||
public function getPreviewAttachments(Project $project): array
|
|
||||||
{
|
|
||||||
$list = [];
|
|
||||||
|
|
||||||
//Master attachment has top priority
|
|
||||||
$attachment = $project->getMasterPictureAttachment();
|
|
||||||
if ($this->isAttachmentValidPicture($attachment)) {
|
|
||||||
$list[] = $attachment;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Then comes the other images of the project
|
|
||||||
foreach ($project->getAttachments() as $attachment) {
|
|
||||||
//Dont show the master attachment twice
|
|
||||||
if ($this->isAttachmentValidPicture($attachment) && $attachment !== $project->getMasterPictureAttachment()) {
|
|
||||||
$list[] = $attachment;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $list;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines what attachment should be used for previewing a project (especially in project table).
|
|
||||||
* The returned attachment is guaranteed to be existing and be a picture.
|
|
||||||
*
|
|
||||||
* @param Project $project The project for which the attachment should be determined
|
|
||||||
*/
|
|
||||||
public function getTablePreviewAttachment(Project $project): ?Attachment
|
|
||||||
{
|
|
||||||
$attachment = $project->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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -513,8 +513,10 @@ class BOMImporter
|
||||||
|
|
||||||
//Convert column name into hierarchy
|
//Convert column name into hierarchy
|
||||||
$path = explode('_', $column);
|
$path = explode('_', $column);
|
||||||
|
/** @var array<string, mixed> $temp */
|
||||||
$temp = &$entry;
|
$temp = &$entry;
|
||||||
|
|
||||||
|
/** @var lowercase-string $step */
|
||||||
foreach ($path as $step) {
|
foreach ($path as $step) {
|
||||||
if (!isset($temp[$step])) {
|
if (!isset($temp[$step])) {
|
||||||
$temp[$step] = [];
|
$temp[$step] = [];
|
||||||
|
|
@ -526,7 +528,7 @@ class BOMImporter
|
||||||
//If there is no value, skip
|
//If there is no value, skip
|
||||||
if (isset($values[$index]) && $values[$index] !== '') {
|
if (isset($values[$index]) && $values[$index] !== '') {
|
||||||
//Check whether the value is numerical
|
//Check whether the value is numerical
|
||||||
if (is_numeric($values[$index]) && !in_array($column, ['name','description','manufacturer','designator'])) {
|
if (is_numeric($values[$index]) && !in_array($column, ['name','description','manufacturer','designator'], true)) {
|
||||||
//Convert to integer or float
|
//Convert to integer or float
|
||||||
$temp = (str_contains($values[$index], '.'))
|
$temp = (str_contains($values[$index], '.'))
|
||||||
? floatval($values[$index])
|
? floatval($values[$index])
|
||||||
|
|
@ -577,7 +579,7 @@ class BOMImporter
|
||||||
$bomEntry->setMountnames(trim($entry['designator']) === '' ? '' : trim($entry['designator']));
|
$bomEntry->setMountnames(trim($entry['designator']) === '' ? '' : trim($entry['designator']));
|
||||||
}
|
}
|
||||||
|
|
||||||
$bomEntry->setQuantity((float) $entry['quantity'] ?? 0);
|
$bomEntry->setQuantity((float) $entry['quantity']);
|
||||||
|
|
||||||
$result->addBomEntry($bomEntry);
|
$result->addBomEntry($bomEntry);
|
||||||
}
|
}
|
||||||
|
|
@ -706,7 +708,7 @@ class BOMImporter
|
||||||
$result->addViolation($this->buildJsonViolation(
|
$result->addViolation($this->buildJsonViolation(
|
||||||
'validator.bom_importer.json_csv.parameter.array',
|
'validator.bom_importer.json_csv.parameter.array',
|
||||||
'entry[$key].part.manufacturer',
|
'entry[$key].part.manufacturer',
|
||||||
$entry['part']['manufacturer']) ?? null
|
$entry['part']['manufacturer'])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -728,8 +730,8 @@ class BOMImporter
|
||||||
if (($manufacturerIdValid || $manufacturerNameValid) && $manufacturer === null) {
|
if (($manufacturerIdValid || $manufacturerNameValid) && $manufacturer === null) {
|
||||||
$value = sprintf(
|
$value = sprintf(
|
||||||
'manufacturer.id: %s, manufacturer.name: %s',
|
'manufacturer.id: %s, manufacturer.name: %s',
|
||||||
isset($entry['part']['manufacturer']['id']) && $entry['part']['manufacturer']['id'] !== null ? '<strong>' . $entry['part']['manufacturer']['id'] . '</strong>' : '-',
|
isset($entry['part']['manufacturer']['id']) && $entry['part']['manufacturer']['id'] != null ? '<strong>' . $entry['part']['manufacturer']['id'] . '</strong>' : '-',
|
||||||
isset($entry['part']['manufacturer']['name']) && $entry['part']['manufacturer']['name'] !== null ? '<strong>' . $entry['part']['manufacturer']['name'] . '</strong>' : '-'
|
isset($entry['part']['manufacturer']['name']) && $entry['part']['manufacturer']['name'] != null ? '<strong>' . $entry['part']['manufacturer']['name'] . '</strong>' : '-'
|
||||||
);
|
);
|
||||||
|
|
||||||
$result->addViolation($this->buildJsonViolation(
|
$result->addViolation($this->buildJsonViolation(
|
||||||
|
|
@ -760,7 +762,7 @@ class BOMImporter
|
||||||
$result->addViolation($this->buildJsonViolation(
|
$result->addViolation($this->buildJsonViolation(
|
||||||
'validator.bom_importer.json_csv.parameter.array',
|
'validator.bom_importer.json_csv.parameter.array',
|
||||||
'entry[$key].part.category',
|
'entry[$key].part.category',
|
||||||
$entry['part']['category']) ?? null
|
$entry['part']['category'])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -782,8 +784,8 @@ class BOMImporter
|
||||||
if (($categoryIdValid || $categoryNameValid)) {
|
if (($categoryIdValid || $categoryNameValid)) {
|
||||||
$value = sprintf(
|
$value = sprintf(
|
||||||
'category.id: %s, category.name: %s',
|
'category.id: %s, category.name: %s',
|
||||||
isset($entry['part']['category']['id']) && $entry['part']['category']['id'] !== null ? '<strong>' . $entry['part']['category']['id'] . '</strong>' : '-',
|
isset($entry['part']['category']['id']) && $entry['part']['category']['id'] != null ? '<strong>' . $entry['part']['category']['id'] . '</strong>' : '-',
|
||||||
isset($entry['part']['category']['name']) && $entry['part']['category']['name'] !== null ? '<strong>' . $entry['part']['category']['name'] . '</strong>' : '-'
|
isset($entry['part']['category']['name']) && $entry['part']['category']['name'] != null ? '<strong>' . $entry['part']['category']['name'] . '</strong>' : '-'
|
||||||
);
|
);
|
||||||
|
|
||||||
$result->addViolation($this->buildJsonViolation(
|
$result->addViolation($this->buildJsonViolation(
|
||||||
|
|
@ -816,11 +818,13 @@ class BOMImporter
|
||||||
$part->setDescription($partDescription);
|
$part->setDescription($partDescription);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @var Manufacturer|null $manufacturer */
|
||||||
if ($manufacturer !== null && $manufacturer->getID() !== $part->getManufacturer()->getID()) {
|
if ($manufacturer !== null && $manufacturer->getID() !== $part->getManufacturer()->getID()) {
|
||||||
//When updating the associated parts, take over to a assembly of the manufacturer of the part.
|
//When updating the associated parts, take over to a assembly of the manufacturer of the part.
|
||||||
$part->setManufacturer($manufacturer);
|
$part->setManufacturer($manufacturer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @var Category|null $category */
|
||||||
if ($category !== null && $category->getID() !== $part->getCategory()->getID()) {
|
if ($category !== null && $category->getID() !== $part->getCategory()->getID()) {
|
||||||
//When updating the associated parts to a assembly, take over the category of the part.
|
//When updating the associated parts to a assembly, take over the category of the part.
|
||||||
$part->setCategory($category);
|
$part->setCategory($category);
|
||||||
|
|
|
||||||
|
|
@ -414,7 +414,7 @@ class EntityExporter
|
||||||
'ProjectFullName' => $this->getFullName($entity),
|
'ProjectFullName' => $this->getFullName($entity),
|
||||||
|
|
||||||
//BOM relevant attributes
|
//BOM relevant attributes
|
||||||
'Quantity' => $bomEntry->getQuantity() ?? '',
|
'Quantity' => $bomEntry->getQuantity(),
|
||||||
'PartId' => $bomEntry->getPart()?->getId() ?? '',
|
'PartId' => $bomEntry->getPart()?->getId() ?? '',
|
||||||
'PartName' => $bomEntry->getPart()?->getName() ?? '',
|
'PartName' => $bomEntry->getPart()?->getName() ?? '',
|
||||||
'Ipn' => $bomEntry->getPart()?->getIpn() ?? '',
|
'Ipn' => $bomEntry->getPart()?->getIpn() ?? '',
|
||||||
|
|
@ -582,7 +582,7 @@ class EntityExporter
|
||||||
'AssemblyFullName' => $this->getFullName($assembly),
|
'AssemblyFullName' => $this->getFullName($assembly),
|
||||||
|
|
||||||
//BOM relevant attributes
|
//BOM relevant attributes
|
||||||
'Quantity' => $bomEntry->getQuantity() ?? '',
|
'Quantity' => $bomEntry->getQuantity(),
|
||||||
'PartId' => $bomEntry->getPart()?->getId() ?? '-',
|
'PartId' => $bomEntry->getPart()?->getId() ?? '-',
|
||||||
'PartName' => $bomEntry->getPart()?->getName() ?? '-',
|
'PartName' => $bomEntry->getPart()?->getName() ?? '-',
|
||||||
'Ipn' => $bomEntry->getPart()?->getIpn() ?? '-',
|
'Ipn' => $bomEntry->getPart()?->getIpn() ?? '-',
|
||||||
|
|
|
||||||
|
|
@ -132,10 +132,10 @@ class AssemblyCycleValidator extends ConstraintValidator
|
||||||
* The process involves reflection to access private or protected properties of violation objects.
|
* The process involves reflection to access private or protected properties of violation objects.
|
||||||
*
|
*
|
||||||
* @param mixed $value The value that triggered the violation.
|
* @param mixed $value The value that triggered the violation.
|
||||||
* @param Constraint $constraint The constraint containing the validation details.
|
* @param AssemblyCycle $constraint The constraint containing the validation details.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private function addViolation(mixed $value, Constraint $constraint): void
|
private function addViolation(mixed $value, AssemblyCycle $constraint): void
|
||||||
{
|
{
|
||||||
/** @var ConstraintViolationBuilder $buildViolation */
|
/** @var ConstraintViolationBuilder $buildViolation */
|
||||||
$buildViolation = $this->context->buildViolation($constraint->message)
|
$buildViolation = $this->context->buildViolation($constraint->message)
|
||||||
|
|
|
||||||
|
|
@ -97,19 +97,6 @@ class AssemblyInvalidBomEntryValidator extends ConstraintValidator
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function isOnSameLevel(Assembly $assembly1, Assembly $assembly2): bool
|
|
||||||
{
|
|
||||||
$parent1 = $assembly1->getParent();
|
|
||||||
$parent2 = $assembly2->getParent();
|
|
||||||
|
|
||||||
if ($parent1 === null || $parent2 === null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Beide Assemblies teilen denselben Parent
|
|
||||||
return $parent1 !== null && $parent2 !== null && $parent1->getId() === $parent2->getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a violation to the current context if it hasn’t already been added.
|
* Adds a violation to the current context if it hasn’t already been added.
|
||||||
*
|
*
|
||||||
|
|
@ -117,11 +104,11 @@ class AssemblyInvalidBomEntryValidator extends ConstraintValidator
|
||||||
* already exists in the context. If such a violation is found, the current violation is not added again.
|
* 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.
|
* The process involves reflection to access private or protected properties of violation objects.
|
||||||
*
|
*
|
||||||
* @param mixed $value The value that triggered the violation.
|
* @param mixed $value The value that triggered the violation.
|
||||||
* @param Constraint $constraint The constraint containing the validation details.
|
* @param AssemblyInvalidBomEntry $constraint The constraint containing the validation details.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private function addViolation($value, Constraint $constraint): void
|
private function addViolation($value, AssemblyInvalidBomEntry $constraint): void
|
||||||
{
|
{
|
||||||
/** @var ConstraintViolationBuilder $buildViolation */
|
/** @var ConstraintViolationBuilder $buildViolation */
|
||||||
$buildViolation = $this->context->buildViolation($constraint->message)
|
$buildViolation = $this->context->buildViolation($constraint->message)
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ class UniqueReferencedAssemblyValidator extends ConstraintValidator
|
||||||
public function validate($value, Constraint $constraint)
|
public function validate($value, Constraint $constraint)
|
||||||
{
|
{
|
||||||
$assemblies = [];
|
$assemblies = [];
|
||||||
|
|
||||||
foreach ($value as $entry) {
|
foreach ($value as $entry) {
|
||||||
$referencedAssemblyId = $entry->getReferencedAssembly()?->getId();
|
$referencedAssemblyId = $entry->getReferencedAssembly()?->getId();
|
||||||
if ($referencedAssemblyId === null) {
|
if ($referencedAssemblyId === null) {
|
||||||
|
|
@ -37,6 +38,7 @@ class UniqueReferencedAssemblyValidator extends ConstraintValidator
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($assemblies[$referencedAssemblyId])) {
|
if (isset($assemblies[$referencedAssemblyId])) {
|
||||||
|
/** @var UniqueReferencedAssembly $constraint */
|
||||||
$this->context->buildViolation($constraint->message)
|
$this->context->buildViolation($constraint->message)
|
||||||
->atPath('referencedAssembly')
|
->atPath('referencedAssembly')
|
||||||
->addViolation();
|
->addViolation();
|
||||||
|
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
|
||||||
*
|
|
||||||
* Copyright (C) 2019 - 2023 Jan Böhmer (https://github.com/jbtronics)
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published
|
|
||||||
* by the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
namespace App\Validator\Constraints\AssemblySystem;
|
|
||||||
|
|
||||||
use Symfony\Component\Validator\Constraint;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This constraint checks that the given ValidAssemblyBuildRequest is valid.
|
|
||||||
*/
|
|
||||||
#[\Attribute(\Attribute::TARGET_CLASS)]
|
|
||||||
class ValidAssemblyBuildRequest extends Constraint
|
|
||||||
{
|
|
||||||
public function getTargets(): string
|
|
||||||
{
|
|
||||||
return self::CLASS_CONSTRAINT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,84 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
|
||||||
*
|
|
||||||
* Copyright (C) 2019 - 2023 Jan Böhmer (https://github.com/jbtronics)
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published
|
|
||||||
* by the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
namespace App\Validator\Constraints\AssemblySystem;
|
|
||||||
|
|
||||||
use App\Entity\Parts\PartLot;
|
|
||||||
use App\Helpers\Assemblies\AssemblyBuildRequest;
|
|
||||||
use Symfony\Component\Validator\Constraint;
|
|
||||||
use Symfony\Component\Validator\ConstraintValidator;
|
|
||||||
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
|
||||||
use Symfony\Component\Validator\Violation\ConstraintViolationBuilderInterface;
|
|
||||||
|
|
||||||
class ValidAssemblyBuildRequestValidator extends ConstraintValidator
|
|
||||||
{
|
|
||||||
private function buildViolationForLot(PartLot $partLot, string $message): ConstraintViolationBuilderInterface
|
|
||||||
{
|
|
||||||
return $this->context->buildViolation($message)
|
|
||||||
->atPath('lot_' . $partLot->getID())
|
|
||||||
->setParameter('{{ lot }}', $partLot->getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function validate($value, Constraint $constraint): void
|
|
||||||
{
|
|
||||||
if (!$constraint instanceof ValidAssemblyBuildRequest) {
|
|
||||||
throw new UnexpectedTypeException($constraint, ValidAssemblyBuildRequest::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null === $value || '' === $value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$value instanceof AssemblyBuildRequest) {
|
|
||||||
throw new UnexpectedTypeException($value, AssemblyBuildRequest::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($value->getPartBomEntries() as $bom_entry) {
|
|
||||||
$withdraw_sum = $value->getWithdrawAmountSum($bom_entry);
|
|
||||||
$needed_amount = $value->getNeededAmountForBOMEntry($bom_entry);
|
|
||||||
|
|
||||||
foreach ($value->getPartLotsForBOMEntry($bom_entry) as $lot) {
|
|
||||||
$withdraw_amount = $value->getLotWithdrawAmount($lot);
|
|
||||||
|
|
||||||
if ($withdraw_amount < 0) {
|
|
||||||
$this->buildViolationForLot($lot, 'validator.assembly_build.lot_must_not_smaller_0')
|
|
||||||
->addViolation();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($withdraw_amount > $lot->getAmount()) {
|
|
||||||
$this->buildViolationForLot($lot, 'validator.assembly_build.lot_must_not_bigger_than_stock')
|
|
||||||
->addViolation();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($withdraw_sum > $needed_amount && $value->isDontCheckQuantity() === false) {
|
|
||||||
$this->buildViolationForLot($lot, 'validator.assembly_build.lot_bigger_than_needed')
|
|
||||||
->addViolation();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($withdraw_sum < $needed_amount && $value->isDontCheckQuantity() === false) {
|
|
||||||
$this->buildViolationForLot($lot, 'validator.assembly_build.lot_smaller_than_needed')
|
|
||||||
->addViolation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,90 +0,0 @@
|
||||||
{% import "helper.twig" as helper %}
|
|
||||||
|
|
||||||
{{ form_start(form) }}
|
|
||||||
|
|
||||||
<table class="table table-sm table-responsive table-hover">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>
|
|
||||||
<div class="form-check">
|
|
||||||
<input class="form-check-input" type="checkbox" value="" data-multicheck-name="lots_check" {{ stimulus_controller('pages/checkbox_multicheck') }}>
|
|
||||||
</div>
|
|
||||||
</th>
|
|
||||||
<th>{% trans %}part.table.name{% endtrans %}</th>
|
|
||||||
<th>{% trans %}assembly.bom.mountnames{% endtrans %}</th>
|
|
||||||
<th class="text-end">{% trans %}assembly.build.required_qty{% endtrans %}</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for bom_entry in build_request.bomEntries %}
|
|
||||||
{# 1st row basic infos about the BOM entry #}
|
|
||||||
<tr class="{% if bom_entry.part is null or buildHelper.bOMEntryBuildable(bom_entry, number_of_builds) %}table-primary{% else %}table-danger{% endif %}">
|
|
||||||
<td style="width: 20px;">
|
|
||||||
<div class="form-check">
|
|
||||||
<input class="form-check-input" type="checkbox" value="" data-multicheck-name="lots_check" required>
|
|
||||||
{# <label class="form-check-label" for="checkbox_{{ loop.index }}"> #}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td >
|
|
||||||
{% if bom_entry.part %}
|
|
||||||
<b><a target="_blank" href="{{ entity_url(bom_entry.part) }}">{{ bom_entry.part.name }}</a></b> {% if bom_entry.name %}({{ bom_entry.name }}){% endif %}
|
|
||||||
{% elseif bom_entry.referencedAssembly %}
|
|
||||||
<b><a target="_blank" href="{{ entity_url(bom_entry.referencedAssembly) }}">{{ 'assembly.build.form.referencedAssembly'|trans({'%name%': bom_entry.referencedAssembly.name}) }}</a></b> {% if bom_entry.name %}({{ bom_entry.name }}){% endif %}
|
|
||||||
{% else %}
|
|
||||||
<b>{{ bom_entry.name }}</b>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{% for tag in bom_entry.mountnames|split(',') %}
|
|
||||||
<span class="badge bg-secondary badge-secondary" >{{ tag | trim }}</span>
|
|
||||||
{% endfor %}
|
|
||||||
</td>
|
|
||||||
<td class="text-end">
|
|
||||||
<b>{{ build_request.neededAmountForBOMEntry(bom_entry) | format_amount(bom_entry.part.partUnit ?? null) }}</b> {% trans %}assembly.builds.needed{% endtrans %}
|
|
||||||
(= {{ number_of_builds }} x {{ bom_entry.quantity | format_amount(bom_entry.part.partUnit ?? null) }})
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="4">
|
|
||||||
{% set lots = build_request.partLotsForBOMEntry(bom_entry) %}
|
|
||||||
{% if lots is not null %}
|
|
||||||
{% for lot in lots %}
|
|
||||||
{# @var lot \App\Entity\Parts\PartLot #}
|
|
||||||
<div class="mb-2 row">
|
|
||||||
<label class="col-form-label col-sm-4" for="category_admin_form_parent">
|
|
||||||
{% if lot.storageLocation %}
|
|
||||||
<small>{{ helper.structural_entity_link(lot.storageLocation) }}</small>
|
|
||||||
{% endif %}
|
|
||||||
{% if lot.name is not empty %}
|
|
||||||
(<small>{{ lot.name }}</small>)
|
|
||||||
{% endif %}
|
|
||||||
</label>
|
|
||||||
<div class="col-sm-6">
|
|
||||||
{{ form_errors(form["lot_"~lot.id]) }}
|
|
||||||
{{ form_widget(form["lot_"~lot.id]) }}
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-2 mt-1 text-end">
|
|
||||||
/ <b>{{ lot.amount | format_amount(lot.part.partUnit) }}</b> {% trans %}assembly.builds.stocked{% endtrans %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
{{ form_row(form.comment) }}
|
|
||||||
<div {{ stimulus_controller('pages/dont_check_quantity_checkbox') }}>
|
|
||||||
{{ form_row(form.dontCheckQuantity) }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{ form_row(form.addBuildsToBuildsPart) }}
|
|
||||||
{% if form.buildsPartLot is defined %}
|
|
||||||
{{ form_row(form.buildsPartLot) }}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{{ form_row(form.submit) }}
|
|
||||||
|
|
||||||
{{ form_end(form) }}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
{% extends "main_card.html.twig" %}
|
|
||||||
|
|
||||||
{% block title %}{% trans %}assembly.info.builds.label{% endtrans %}: {{ number_of_builds }}x {{ assembly.name }}{% endblock %}
|
|
||||||
|
|
||||||
{% block card_title %}
|
|
||||||
<i class="fa-solid fa-bolt fa-fw"></i>
|
|
||||||
{% trans %}assembly.info.builds.label{% endtrans %}: <b>{{ number_of_builds }}x</b> <i>{{ assembly.name }}</i>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block card_content %}
|
|
||||||
{% set can_build = buildHelper.assemblyBuildable(assembly, number_of_builds) %}
|
|
||||||
{% import "components/assemblies.macro.html.twig" as assembly_macros %}
|
|
||||||
|
|
||||||
{% if assembly.status is not empty and assembly.status != "in_production" %}
|
|
||||||
<div class="alert alert-warning" role="alert">
|
|
||||||
<i class="fa-solid fa-triangle-exclamation fa-fw"></i> {% trans with {"%assembly_status%": ('assembly.status.'~assembly.status)|trans } %}assembly.builds.check_assembly_status{% endtrans %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div class="alert {% if can_build %}alert-success{% else %}alert-danger{% endif %}" role="alert">
|
|
||||||
{% if not can_build %}
|
|
||||||
<h5><i class="fa-solid fa-circle-exclamation fa-fw"></i> {% trans %}assembly.builds.build_not_possible{% endtrans %}</h5>
|
|
||||||
<b>{% trans with {"%number_of_builds%": number_of_builds} %}assembly.builds.following_bom_entries_miss_instock_n{% endtrans %}</b>
|
|
||||||
<ul>
|
|
||||||
{% for bom_entry in buildHelper.nonBuildableAssemblyBomEntries(assembly, number_of_builds) %}
|
|
||||||
<li>{{ assembly_macros.assembly_bom_entry_with_missing_instock(bom_entry, number_of_builds) }}</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
{% else %}
|
|
||||||
<h5><i class="fa-solid fa-circle-check fa-fw"></i> {% trans %}assembly.builds.build_possible{% endtrans %}</h5>
|
|
||||||
<span>{% trans with {"%max_builds%": number_of_builds} %}assembly.builds.number_of_builds_possible{% endtrans %}</span>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p class="text-muted">{% trans %}assembly.build.help{% endtrans %}</p>
|
|
||||||
|
|
||||||
{% include 'assemblies/build/_form.html.twig' %}
|
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
{% set can_build = buildHelper.assemblyBuildable(assembly) %}
|
|
||||||
|
|
||||||
{% import "components/assemblies.macro.html.twig" as assembly_macros %}
|
|
||||||
|
|
||||||
{% if assembly.status is not empty and assembly.status != "in_production" %}
|
|
||||||
<div class="alert mt-2 alert-warning" role="alert">
|
|
||||||
<i class="fa-solid fa-triangle-exclamation fa-fw"></i> {% trans with {"%assembly_status%": ('assembly.status.'~assembly.status)|trans } %}assembly.builds.check_assembly_status{% endtrans %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div class="alert mt-2 {% if can_build %}alert-success{% else %}alert-danger{% endif %}" role="alert">
|
|
||||||
{% if not can_build %}
|
|
||||||
<h5><i class="fa-solid fa-circle-exclamation fa-fw"></i> {% trans %}assembly.builds.build_not_possible{% endtrans %}</h5>
|
|
||||||
<b>{% trans %}assembly.builds.following_bom_entries_miss_instock{% endtrans %}</b>
|
|
||||||
<ul>
|
|
||||||
{% for bom_entry in buildHelper.nonBuildableAssemblyBomEntries(assembly) %}
|
|
||||||
<li>{{ assembly_macros.assembly_bom_entry_with_missing_instock(bom_entry) }}</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
{% else %}
|
|
||||||
<h5><i class="fa-solid fa-circle-check fa-fw"></i> {% trans %}assembly.builds.build_possible{% endtrans %}</h5>
|
|
||||||
<span>{% trans with {"%max_builds%": buildHelper.maximumBuildableCount(assembly)} %}assembly.builds.number_of_builds_possible{% endtrans %}</span>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form method="get" action="{{ path('assembly_build', {"id": assembly.iD }) }}">
|
|
||||||
<div class="row mt-2">
|
|
||||||
<div class="col-4">
|
|
||||||
<div class="input-group mb-3">
|
|
||||||
<input type="number" min="1" class="form-control" placeholder="{% trans %}assembly.builds.number_of_builds{% endtrans %}" name="n" required>
|
|
||||||
<input type="hidden" name="_redirect" value="{{ uri_without_host(app.request) }}">
|
|
||||||
<button class="btn btn-outline-secondary" type="submit" id="button-addon2">{% trans %}assembly.build.btn_build{% endtrans %}</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{% if assembly.buildPart %}
|
|
||||||
<p><b>{% trans %}assembly.builds.no_stocked_builds{% endtrans %}:</b> <a href="{{ entity_url(assembly.buildPart) }}">{{ assembly.buildPart.amountSum }}</a></p>
|
|
||||||
{% endif %}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
{% macro assembly_bom_entry_with_missing_instock(assembly_bom_entry, number_of_builds = 1) %}
|
|
||||||
{# @var \App\Entity\AssemblySystem\AssemblyBOMEntry assembly_bom_entry #}
|
|
||||||
<b><a href="{{ entity_url(assembly_bom_entry.part) }}">{{ assembly_bom_entry.part.name }}</a></b>
|
|
||||||
{% if assembly_bom_entry.name %} ({{ assembly_bom_entry.name }}){% endif %}:
|
|
||||||
<b>{{ assembly_bom_entry.part.amountSum | format_amount(assembly_bom_entry.part.partUnit) }}</b> {% trans %}assembly.builds.stocked{% endtrans %}
|
|
||||||
/
|
|
||||||
<b>{{ (assembly_bom_entry.quantity * number_of_builds) | format_amount(assembly_bom_entry.part.partUnit) }}</b> {% trans %}assembly.builds.needed{% endtrans %}
|
|
||||||
{% endmacro %}
|
|
||||||
|
|
@ -1,177 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
|
||||||
*
|
|
||||||
* Copyright (C) 2019 - 2023 Jan Böhmer (https://github.com/jbtronics)
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published
|
|
||||||
* by the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
namespace App\Tests\Helpers\Assemblies;
|
|
||||||
|
|
||||||
use App\Entity\Parts\MeasurementUnit;
|
|
||||||
use App\Entity\Parts\Part;
|
|
||||||
use App\Entity\Parts\PartLot;
|
|
||||||
use App\Entity\AssemblySystem\Assembly;
|
|
||||||
use App\Entity\AssemblySystem\AssemblyBOMEntry;
|
|
||||||
use App\Helpers\Assemblies\AssemblyBuildRequest;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class AssemblyBuildRequestTest extends TestCase
|
|
||||||
{
|
|
||||||
|
|
||||||
/** @var MeasurementUnit $float_unit */
|
|
||||||
private MeasurementUnit $float_unit;
|
|
||||||
|
|
||||||
/** @var Assembly */
|
|
||||||
private Assembly $assembly1;
|
|
||||||
/** @var AssemblyBOMEntry */
|
|
||||||
private AssemblyBOMEntry $bom_entry1a;
|
|
||||||
/** @var AssemblyBOMEntry */
|
|
||||||
private AssemblyBOMEntry $bom_entry1b;
|
|
||||||
/** @var AssemblyBOMEntry */
|
|
||||||
private AssemblyBOMEntry $bom_entry1c;
|
|
||||||
|
|
||||||
private PartLot $lot1a;
|
|
||||||
private PartLot $lot1b;
|
|
||||||
private PartLot $lot2;
|
|
||||||
|
|
||||||
/** @var Part */
|
|
||||||
private Part $part1;
|
|
||||||
/** @var Part */
|
|
||||||
private Part $part2;
|
|
||||||
|
|
||||||
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
$this->float_unit = new MeasurementUnit();
|
|
||||||
$this->float_unit->setName('float');
|
|
||||||
$this->float_unit->setUnit('f');
|
|
||||||
$this->float_unit->setIsInteger(false);
|
|
||||||
$this->float_unit->setUseSIPrefix(true);
|
|
||||||
|
|
||||||
//Setup some example parts and part lots
|
|
||||||
$this->part1 = new Part();
|
|
||||||
$this->part1->setName('Part 1');
|
|
||||||
$this->lot1a = new class extends PartLot {
|
|
||||||
public function getID(): ?int
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
$this->part1->addPartLot($this->lot1a);
|
|
||||||
$this->lot1a->setAmount(10);
|
|
||||||
$this->lot1a->setDescription('Lot 1a');
|
|
||||||
|
|
||||||
$this->lot1b = new class extends PartLot {
|
|
||||||
public function getID(): ?int
|
|
||||||
{
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
$this->part1->addPartLot($this->lot1b);
|
|
||||||
$this->lot1b->setAmount(20);
|
|
||||||
$this->lot1b->setDescription('Lot 1b');
|
|
||||||
|
|
||||||
$this->part2 = new Part();
|
|
||||||
|
|
||||||
$this->part2->setName('Part 2');
|
|
||||||
$this->part2->setPartUnit($this->float_unit);
|
|
||||||
$this->lot2 = new PartLot();
|
|
||||||
$this->part2->addPartLot($this->lot2);
|
|
||||||
$this->lot2->setAmount(2.5);
|
|
||||||
$this->lot2->setDescription('Lot 2');
|
|
||||||
|
|
||||||
$this->bom_entry1a = new AssemblyBOMEntry();
|
|
||||||
$this->bom_entry1a->setPart($this->part1);
|
|
||||||
$this->bom_entry1a->setQuantity(2);
|
|
||||||
|
|
||||||
$this->bom_entry1b = new AssemblyBOMEntry();
|
|
||||||
$this->bom_entry1b->setPart($this->part2);
|
|
||||||
$this->bom_entry1b->setQuantity(1.5);
|
|
||||||
|
|
||||||
$this->bom_entry1c = new AssemblyBOMEntry();
|
|
||||||
$this->bom_entry1c->setName('Non-part BOM entry');
|
|
||||||
$this->bom_entry1c->setQuantity(4);
|
|
||||||
|
|
||||||
|
|
||||||
$this->assembly1 = new Assembly();
|
|
||||||
$this->assembly1->setName('Assembly 1');
|
|
||||||
$this->assembly1->addBomEntry($this->bom_entry1a);
|
|
||||||
$this->assembly1->addBomEntry($this->bom_entry1b);
|
|
||||||
$this->assembly1->addBomEntry($this->bom_entry1c);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testInitialization(): void
|
|
||||||
{
|
|
||||||
//The values should be already prefilled correctly
|
|
||||||
$request = new AssemblyBuildRequest($this->assembly1, 10);
|
|
||||||
//We need totally 20: Take 10 from the first (maximum 10) and 10 from the second (maximum 20)
|
|
||||||
$this->assertEqualsWithDelta(10.0, $request->getLotWithdrawAmount($this->lot1a), PHP_FLOAT_EPSILON);
|
|
||||||
$this->assertEqualsWithDelta(10.0, $request->getLotWithdrawAmount($this->lot1b), PHP_FLOAT_EPSILON);
|
|
||||||
|
|
||||||
//If the needed amount is higher than the maximum, we should get the maximum
|
|
||||||
$this->assertEqualsWithDelta(2.5, $request->getLotWithdrawAmount($this->lot2), PHP_FLOAT_EPSILON);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetNumberOfBuilds(): void
|
|
||||||
{
|
|
||||||
$build_request = new AssemblyBuildRequest($this->assembly1, 5);
|
|
||||||
$this->assertSame(5, $build_request->getNumberOfBuilds());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetAssembly(): void
|
|
||||||
{
|
|
||||||
$build_request = new AssemblyBuildRequest($this->assembly1, 5);
|
|
||||||
$this->assertEquals($this->assembly1, $build_request->getAssembly());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetNeededAmountForBOMEntry(): void
|
|
||||||
{
|
|
||||||
$build_request = new AssemblyBuildRequest($this->assembly1, 5);
|
|
||||||
$this->assertEqualsWithDelta(10.0, $build_request->getNeededAmountForBOMEntry($this->bom_entry1a), PHP_FLOAT_EPSILON);
|
|
||||||
$this->assertEqualsWithDelta(7.5, $build_request->getNeededAmountForBOMEntry($this->bom_entry1b), PHP_FLOAT_EPSILON);
|
|
||||||
$this->assertEqualsWithDelta(20.0, $build_request->getNeededAmountForBOMEntry($this->bom_entry1c), PHP_FLOAT_EPSILON);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetSetLotWithdrawAmount(): void
|
|
||||||
{
|
|
||||||
$build_request = new AssemblyBuildRequest($this->assembly1, 5);
|
|
||||||
|
|
||||||
//We can set the amount for a lot either via the lot object or via the ID
|
|
||||||
$build_request->setLotWithdrawAmount($this->lot1a, 2);
|
|
||||||
$build_request->setLotWithdrawAmount($this->lot1b->getID(), 3);
|
|
||||||
|
|
||||||
//And it should be possible to get the amount via the lot object or via the ID
|
|
||||||
$this->assertEqualsWithDelta(2.0, $build_request->getLotWithdrawAmount($this->lot1a->getID()), PHP_FLOAT_EPSILON);
|
|
||||||
$this->assertEqualsWithDelta(3.0, $build_request->getLotWithdrawAmount($this->lot1b), PHP_FLOAT_EPSILON);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetWithdrawAmountSum(): void
|
|
||||||
{
|
|
||||||
//The sum of all withdraw amounts for an BOM entry (over all lots of the associated part) should be correct
|
|
||||||
$build_request = new AssemblyBuildRequest($this->assembly1, 5);
|
|
||||||
|
|
||||||
$build_request->setLotWithdrawAmount($this->lot1a, 2);
|
|
||||||
$build_request->setLotWithdrawAmount($this->lot1b, 3);
|
|
||||||
|
|
||||||
$this->assertEqualsWithDelta(5.0, $build_request->getWithdrawAmountSum($this->bom_entry1a), PHP_FLOAT_EPSILON);
|
|
||||||
$build_request->setLotWithdrawAmount($this->lot2, 1.5);
|
|
||||||
$this->assertEqualsWithDelta(1.5, $build_request->getWithdrawAmountSum($this->bom_entry1b), PHP_FLOAT_EPSILON);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,117 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
|
||||||
*
|
|
||||||
* Copyright (C) 2019 - 2023 Jan Böhmer (https://github.com/jbtronics)
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published
|
|
||||||
* by the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
namespace App\Tests\Services\AssemblySystem;
|
|
||||||
|
|
||||||
use App\Entity\AssemblySystem\Assembly;
|
|
||||||
use App\Entity\AssemblySystem\AssemblyBOMEntry;
|
|
||||||
use App\Entity\Parts\Part;
|
|
||||||
use App\Entity\Parts\PartLot;
|
|
||||||
use App\Services\AssemblySystem\AssemblyBuildHelper;
|
|
||||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
|
||||||
|
|
||||||
class AssemblyBuildHelperTest extends WebTestCase
|
|
||||||
{
|
|
||||||
/** @var AssemblyBuildHelper */
|
|
||||||
protected $service;
|
|
||||||
|
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
self::bootKernel();
|
|
||||||
$this->service = self::getContainer()->get(AssemblyBuildHelper::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetMaximumBuildableCountForBOMEntryNonPartBomEntry(): void
|
|
||||||
{
|
|
||||||
$bom_entry = new AssemblyBOMEntry();
|
|
||||||
$bom_entry->setPart(null);
|
|
||||||
$bom_entry->setQuantity(10);
|
|
||||||
$bom_entry->setName('Test');
|
|
||||||
|
|
||||||
$this->expectException(\InvalidArgumentException::class);
|
|
||||||
$this->service->getMaximumBuildableCountForBOMEntry($bom_entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetMaximumBuildableCountForBOMEntry(): void
|
|
||||||
{
|
|
||||||
$assembly_bom_entry = new AssemblyBOMEntry();
|
|
||||||
$assembly_bom_entry->setQuantity(10);
|
|
||||||
|
|
||||||
$part = new Part();
|
|
||||||
$lot1 = new PartLot();
|
|
||||||
$lot1->setAmount(120);
|
|
||||||
$lot2 = new PartLot();
|
|
||||||
$lot2->setAmount(5);
|
|
||||||
$part->addPartLot($lot1);
|
|
||||||
$part->addPartLot($lot2);
|
|
||||||
|
|
||||||
$assembly_bom_entry->setPart($part);
|
|
||||||
|
|
||||||
//We have 125 parts in stock, so we can build 12 times the assembly (125 / 10 = 12.5)
|
|
||||||
$this->assertSame(12, $this->service->getMaximumBuildableCountForBOMEntry($assembly_bom_entry));
|
|
||||||
|
|
||||||
|
|
||||||
$lot1->setAmount(0);
|
|
||||||
//We have 5 parts in stock, so we can build 0 times the assembly (5 / 10 = 0.5)
|
|
||||||
$this->assertSame(0, $this->service->getMaximumBuildableCountForBOMEntry($assembly_bom_entry));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetMaximumBuildableCount(): void
|
|
||||||
{
|
|
||||||
$assembly = new Assembly();
|
|
||||||
|
|
||||||
$assembly_bom_entry1 = new AssemblyBOMEntry();
|
|
||||||
$assembly_bom_entry1->setQuantity(10);
|
|
||||||
$part = new Part();
|
|
||||||
$lot1 = new PartLot();
|
|
||||||
$lot1->setAmount(120);
|
|
||||||
$lot2 = new PartLot();
|
|
||||||
$lot2->setAmount(5);
|
|
||||||
$part->addPartLot($lot1);
|
|
||||||
$part->addPartLot($lot2);
|
|
||||||
$assembly_bom_entry1->setPart($part);
|
|
||||||
$assembly->addBomEntry($assembly_bom_entry1);
|
|
||||||
|
|
||||||
$assembly_bom_entry2 = new AssemblyBOMEntry();
|
|
||||||
$assembly_bom_entry2->setQuantity(5);
|
|
||||||
$part2 = new Part();
|
|
||||||
$lot3 = new PartLot();
|
|
||||||
$lot3->setAmount(10);
|
|
||||||
$part2->addPartLot($lot3);
|
|
||||||
$assembly_bom_entry2->setPart($part2);
|
|
||||||
$assembly->addBomEntry($assembly_bom_entry2);
|
|
||||||
|
|
||||||
$assembly->addBomEntry((new AssemblyBOMEntry())->setName('Non part entry')->setQuantity(1));
|
|
||||||
|
|
||||||
//Restricted by the few parts in stock of part2
|
|
||||||
$this->assertSame(2, $this->service->getMaximumBuildableCount($assembly));
|
|
||||||
|
|
||||||
$lot3->setAmount(1000);
|
|
||||||
//Now the build count is restricted by the few parts in stock of part1
|
|
||||||
$this->assertSame(12, $this->service->getMaximumBuildableCount($assembly));
|
|
||||||
|
|
||||||
$lot3->setAmount(0);
|
|
||||||
//Now the build count must be 0, as we have no parts in stock
|
|
||||||
$this->assertSame(0, $this->service->getMaximumBuildableCount($assembly));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
|
||||||
*
|
|
||||||
* Copyright (C) 2019 - 2023 Jan Böhmer (https://github.com/jbtronics)
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published
|
|
||||||
* by the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
namespace App\Tests\Services\AssemblySystem;
|
|
||||||
|
|
||||||
use App\Entity\AssemblySystem\Assembly;
|
|
||||||
use App\Services\AssemblySystem\AssemblyBuildPartHelper;
|
|
||||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
|
||||||
|
|
||||||
class AssemblyBuildPartHelperTest extends WebTestCase
|
|
||||||
{
|
|
||||||
/** @var AssemblyBuildPartHelper */
|
|
||||||
protected $service;
|
|
||||||
|
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
self::bootKernel();
|
|
||||||
$this->service = self::getContainer()->get(AssemblyBuildPartHelper::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetPartInitialization(): void
|
|
||||||
{
|
|
||||||
$assembly = new Assembly();
|
|
||||||
$assembly->setName('Assembly 1');
|
|
||||||
$assembly->setDescription('Description 1');
|
|
||||||
|
|
||||||
$part = $this->service->getPartInitialization($assembly);
|
|
||||||
$this->assertSame('Assembly 1', $part->getName());
|
|
||||||
$this->assertSame('Description 1', $part->getDescription());
|
|
||||||
$this->assertSame($assembly, $part->getBuiltAssembly());
|
|
||||||
$this->assertSame($part, $assembly->getBuildPart());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -13774,24 +13774,6 @@ Vezměte prosím na vědomí, že se nemůžete vydávat za uživatele se zakáz
|
||||||
<target>Nová sestava</target>
|
<target>Nová sestava</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="M51YUE." name="assembly.edit.associated_build_part">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part</source>
|
|
||||||
<target>Přidružená součást</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nH9R9f." name="assembly.edit.associated_build_part.add">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part.add</source>
|
|
||||||
<target>Přidat součást</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="oVfOk.i" name="assembly.edit.associated_build.hint">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build.hint</source>
|
|
||||||
<target>Tato součást představuje vyrobené instance sestavy. Zadejte, pokud jsou vyrobené instance potřeba. Pokud ne, počet součástí bude použit až při sestavení daného projektu.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.edit.bom.import_bom</source>
|
<source>assembly.edit.bom.import_bom</source>
|
||||||
|
|
@ -13900,60 +13882,6 @@ Vezměte prosím na vědomí, že se nemůžete vydávat za uživatele se zakáz
|
||||||
<target>Přidat součásti</target>
|
<target>Přidat součásti</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="ZbDTUTS" name="assembly.builds.check_assembly_status">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.check_assembly_status</source>
|
|
||||||
<target><![CDATA[Aktuální stav sestavy je <b>"%assembly_status%"</b>. Měli byste zkontrolovat, zda opravdu chcete sestavu postavit s tímto stavem!]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="xq1Soad" name="assembly.builds.build_not_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_not_possible</source>
|
|
||||||
<target>Sestavení není možné: Nedostatek součástí</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="njRyDHQ" name="assembly.builds.following_bom_entries_miss_instock">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock</source>
|
|
||||||
<target>Není dostatek součástí na skladě pro postavení tohoto projektu %number_of_builds% krát. Následující součásti nejsou skladem v dostatečném množství.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="sp7Z0MS" name="assembly.builds.build_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_possible</source>
|
|
||||||
<target>Sestavení je možné</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1uZzdEl" name="assembly.builds.number_of_builds_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds_possible</source>
|
|
||||||
<target><![CDATA[Máte dostatek součástí na skladě k vytvoření <b>%max_builds%</b> kusů této sestavy.]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="pW6QLXf" name="assembly.builds.number_of_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds</source>
|
|
||||||
<target>Počet sestavení</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="mtJqT_a" name="assembly.build.btn_build">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.btn_build</source>
|
|
||||||
<target>Sestavit</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1bCA1zb" name="assembly.build.form.referencedAssembly">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.form.referencedAssembly</source>
|
|
||||||
<target>Sestava "%name%"</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="LFSVVcP" name="assembly.builds.no_stocked_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.no_stocked_builds</source>
|
|
||||||
<target>Počet skladovaných vyrobených instancí</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.info.bom_entries_count</source>
|
<source>assembly.info.bom_entries_count</source>
|
||||||
|
|
@ -13966,18 +13894,6 @@ Vezměte prosím na vědomí, že se nemůžete vydávat za uživatele se zakáz
|
||||||
<target>Podskupiny</target>
|
<target>Podskupiny</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="HZYhTlb" name="assembly.builds.stocked">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.stocked</source>
|
|
||||||
<target>skladem</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="9EG0PLW" name="assembly.builds.needed">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.needed</source>
|
|
||||||
<target>potřebné</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom.delete.confirm</source>
|
<source>assembly.bom.delete.confirm</source>
|
||||||
|
|
@ -14026,24 +13942,6 @@ Vezměte prosím na vědomí, že se nemůžete vydávat za uživatele se zakáz
|
||||||
<target>Poznámky</target>
|
<target>Poznámky</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="87YpQ_u" name="assembly.builds.following_bom_entries_miss_instock_n">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock_n</source>
|
|
||||||
<target>Není dostatek součástí na skladě pro sestavení této sestavy %number_of_builds% krát. Následující součásti nejsou skladem:</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="JlQhDdS" name="assembly.build.help">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.help</source>
|
|
||||||
<target>Vyberte, ze kterých zásob se mají brát potřebné součásti pro sestavení (a v jakém množství). Zaškrtněte políčko u každého dílu, pokud jste jej odebrali, nebo použijte horní políčko k výběru všech naráz.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="iP5_QVj" name="assembly.build.required_qty">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.required_qty</source>
|
|
||||||
<target>Požadované množství</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="UJpD7n6" name="assembly.import_bom">
|
<unit id="UJpD7n6" name="assembly.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.import_bom</source>
|
<source>assembly.import_bom</source>
|
||||||
|
|
@ -14074,24 +13972,6 @@ Vezměte prosím na vědomí, že se nemůžete vydávat za uživatele se zakáz
|
||||||
<target>Cena</target>
|
<target>Cena</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="63adIrC" name="assembly.build.dont_check_quantity">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.dont_check_quantity</source>
|
|
||||||
<target>Neověřovat množství</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="O0DP6tK" name="assembly.build.dont_check_quantity.help">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.dont_check_quantity.help</source>
|
|
||||||
<target>Pokud je tato volba vybrána, budou vybraná množství odstraněna ze skladu bez ohledu na to, zda je méně nebo více součástí, než je skutečně potřeba pro sestavení sestavy.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="9bc0nzK" name="assembly.build.add_builds_to_builds_part">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.add_builds_to_builds_part</source>
|
|
||||||
<target>Přidat vyrobené instance do součásti sestavy</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom_import.type</source>
|
<source>assembly.bom_import.type</source>
|
||||||
|
|
|
||||||
|
|
@ -12779,24 +12779,6 @@ Bemærk venligst, at du ikke kan kopiere fra deaktiveret bruger. Hvis du prøver
|
||||||
<target>Ny samling</target>
|
<target>Ny samling</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="M51YUE." name="assembly.edit.associated_build_part">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part</source>
|
|
||||||
<target>Tilknyttet komponent</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nH9R9f." name="assembly.edit.associated_build_part.add">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part.add</source>
|
|
||||||
<target>Tilføj komponent</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="oVfOk.i" name="assembly.edit.associated_build.hint">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build.hint</source>
|
|
||||||
<target>Denne komponent repræsenterer de fremstillede instanser af samlingen. Angiv, hvis fremstillede instanser er påkrævet. Hvis ikke, vil antallet af komponenter først blive anvendt ved opbygning af det pågældende projekt.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.edit.bom.import_bom</source>
|
<source>assembly.edit.bom.import_bom</source>
|
||||||
|
|
@ -12905,60 +12887,6 @@ Bemærk venligst, at du ikke kan kopiere fra deaktiveret bruger. Hvis du prøver
|
||||||
<target>Tilføj dele</target>
|
<target>Tilføj dele</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="ZbDTUTS" name="assembly.builds.check_assembly_status">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.check_assembly_status</source>
|
|
||||||
<target><![CDATA[Den aktuelle samlingsstatus er <b>"%assembly_status%"</b>. Du bør kontrollere, om du virkelig ønsker at bygge samlingen med denne status!]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="xq1Soad" name="assembly.builds.build_not_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_not_possible</source>
|
|
||||||
<target>Opbygning ikke mulig: Ikke nok komponenter til rådighed</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="njRyDHQ" name="assembly.builds.following_bom_entries_miss_instock">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock</source>
|
|
||||||
<target>Der er ikke nok dele på lager til at bygge dette projekt %number_of_builds% gange. Følgende dele mangler på lager:</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="sp7Z0MS" name="assembly.builds.build_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_possible</source>
|
|
||||||
<target>Byggeri muligt</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1uZzdEl" name="assembly.builds.number_of_builds_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds_possible</source>
|
|
||||||
<target><![CDATA[Du har nok dele på lager til at bygge <b>%max_builds%</b> eksemplarer af denne samling.]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="pW6QLXf" name="assembly.builds.number_of_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds</source>
|
|
||||||
<target>Antal opbygninger</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="mtJqT_a" name="assembly.build.btn_build">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.btn_build</source>
|
|
||||||
<target>Byg</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1bCA1zb" name="assembly.build.form.referencedAssembly">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.form.referencedAssembly</source>
|
|
||||||
<target>Samling "%name%"</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="LFSVVcP" name="assembly.builds.no_stocked_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.no_stocked_builds</source>
|
|
||||||
<target>Antal lagrede byggede enheder</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.info.bom_entries_count</source>
|
<source>assembly.info.bom_entries_count</source>
|
||||||
|
|
@ -12971,18 +12899,6 @@ Bemærk venligst, at du ikke kan kopiere fra deaktiveret bruger. Hvis du prøver
|
||||||
<target>Undergrupper</target>
|
<target>Undergrupper</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="HZYhTlb" name="assembly.builds.stocked">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.stocked</source>
|
|
||||||
<target>på lager</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="9EG0PLW" name="assembly.builds.needed">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.needed</source>
|
|
||||||
<target>nødvendig</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom.delete.confirm</source>
|
<source>assembly.bom.delete.confirm</source>
|
||||||
|
|
@ -13031,24 +12947,6 @@ Bemærk venligst, at du ikke kan kopiere fra deaktiveret bruger. Hvis du prøver
|
||||||
<target>Notater</target>
|
<target>Notater</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="87YpQ_u" name="assembly.builds.following_bom_entries_miss_instock_n">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock_n</source>
|
|
||||||
<target>Der er ikke nok dele på lager til at bygge denne samling %number_of_builds% gange. Følgende dele mangler på lager:</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="JlQhDdS" name="assembly.build.help">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.help</source>
|
|
||||||
<target>Vælg, hvilke lagre de nødvendige dele til bygningen skal tages fra (og i hvilken mængde). Marker afkrydsningsfeltet for hver delpost, når du har fjernet delene, eller brug det øverste afkrydsningsfelt for at markere alle på én gang.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="iP5_QVj" name="assembly.build.required_qty">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.required_qty</source>
|
|
||||||
<target>Krævet antal</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="UJpD7n6" name="assembly.import_bom">
|
<unit id="UJpD7n6" name="assembly.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.import_bom</source>
|
<source>assembly.import_bom</source>
|
||||||
|
|
@ -13079,24 +12977,6 @@ Bemærk venligst, at du ikke kan kopiere fra deaktiveret bruger. Hvis du prøver
|
||||||
<target>Pris</target>
|
<target>Pris</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="63adIrC" name="assembly.build.dont_check_quantity">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.dont_check_quantity</source>
|
|
||||||
<target>Tjek ikke mængder</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="O0DP6tK" name="assembly.build.dont_check_quantity.help">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.dont_check_quantity.help</source>
|
|
||||||
<target>Hvis denne mulighed vælges, fjernes de valgte mængder fra lageret, uanset om der er mere eller mindre end nødvendigt for at bygge samlingen.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="9bc0nzK" name="assembly.build.add_builds_to_builds_part">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.add_builds_to_builds_part</source>
|
|
||||||
<target>Tilføj byggede enheder til assemblies del</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom_import.type</source>
|
<source>assembly.bom_import.type</source>
|
||||||
|
|
|
||||||
|
|
@ -13608,24 +13608,6 @@ Bitte beachten Sie, dass Sie sich nicht als deaktivierter Benutzer ausgeben kön
|
||||||
<target>Neue Baugruppe</target>
|
<target>Neue Baugruppe</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="M51YUE." name="assembly.edit.associated_build_part">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part</source>
|
|
||||||
<target>Verknüpftes Bauteil</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nH9R9f." name="assembly.edit.associated_build_part.add">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part.add</source>
|
|
||||||
<target>Bauteil hinzufügen</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="oVfOk.i" name="assembly.edit.associated_build.hint">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build.hint</source>
|
|
||||||
<target>Dieses Bauteil repräsentiert die gebauten Instanzen der Baugruppe. Anzugeben, sofern gebaute Instanzen benötigt werden. Wenn nein, werden die Stückzahlen bzgl. der Baugruppe erst beim Build des jeweiligen Projektes herangezogen.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.edit.bom.import_bom</source>
|
<source>assembly.edit.bom.import_bom</source>
|
||||||
|
|
@ -13734,60 +13716,6 @@ Bitte beachten Sie, dass Sie sich nicht als deaktivierter Benutzer ausgeben kön
|
||||||
<target>Bauteile hinzufügen</target>
|
<target>Bauteile hinzufügen</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="ZbDTUTS" name="assembly.builds.check_assembly_status">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.check_assembly_status</source>
|
|
||||||
<target><![CDATA[Der aktuelle Baugruppen-Status ist <b>"%assembly_status%"</b>. Sie sollten überprüfen, ob sie die Baugruppe mit diesem Status wirklich bauen wollen!]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="xq1Soad" name="assembly.builds.build_not_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_not_possible</source>
|
|
||||||
<target>Bau nicht möglich: Nicht genügend Bauteile vorhanden</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="njRyDHQ" name="assembly.builds.following_bom_entries_miss_instock">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock</source>
|
|
||||||
<target>Es sind nicht genügend Bauteile auf Lager, um dieses Projekt %number_of_builds% mal zu bauen. Von folgenden Bauteilen ist nicht genügend auf Lager.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="sp7Z0MS" name="assembly.builds.build_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_possible</source>
|
|
||||||
<target>Bau möglich</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1uZzdEl" name="assembly.builds.number_of_builds_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds_possible</source>
|
|
||||||
<target><![CDATA[Sie haben genug Bauteile auf Lager, um <b>%max_builds%</b> Exemplare dieser Baugruppe zu bauen.]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="pW6QLXf" name="assembly.builds.number_of_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds</source>
|
|
||||||
<target>Zu bauende Anzahl</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="mtJqT_a" name="assembly.build.btn_build">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.btn_build</source>
|
|
||||||
<target>Bauen</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1bCA1zb" name="assembly.build.form.referencedAssembly">
|
|
||||||
<segment>
|
|
||||||
<source>asssembly.build.form.referencedAssembly</source>
|
|
||||||
<target>Baugruppe "%name%"</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="LFSVVcP" name="assembly.builds.no_stocked_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.no_stocked_builds</source>
|
|
||||||
<target>Anzahl gelagerter gebauter Instanzen</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.info.bom_entries_count</source>
|
<source>assembly.info.bom_entries_count</source>
|
||||||
|
|
@ -13800,18 +13728,6 @@ Bitte beachten Sie, dass Sie sich nicht als deaktivierter Benutzer ausgeben kön
|
||||||
<target>Untergruppen</target>
|
<target>Untergruppen</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="HZYhTlb" name="assembly.builds.stocked">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.stocked</source>
|
|
||||||
<target>vorhanden</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="9EG0PLW" name="assembly.builds.needed">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.needed</source>
|
|
||||||
<target>benötigt</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom.delete.confirm</source>
|
<source>assembly.bom.delete.confirm</source>
|
||||||
|
|
@ -13860,24 +13776,6 @@ Bitte beachten Sie, dass Sie sich nicht als deaktivierter Benutzer ausgeben kön
|
||||||
<target>Notizen</target>
|
<target>Notizen</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="87YpQ_u" name="assembly.builds.following_bom_entries_miss_instock_n">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock_n</source>
|
|
||||||
<target>Es sind nicht genügend Bauteile auf Lager, um diese Baugruppe %number_of_builds% mal zu bauen. Von folgenden Bauteilen ist nicht genügend auf Lager:</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="JlQhDdS" name="assembly.build.help">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.help</source>
|
|
||||||
<target>Wählen Sie aus, aus welchen Beständen die zum Bau notwendigen Bauteile genommen werden sollen (und in welcher Anzahl). Setzen Sie den Haken für jeden Part Eintrag, wenn sie die Bauteile entnommen haben, oder nutzen Sie die oberste Checkbox, um alle Haken auf einmal zu setzen.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="iP5_QVj" name="assembly.build.required_qty">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.required_qty</source>
|
|
||||||
<target>Benötigte Anzahl</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="UJpD7n6" name="assembly.import_bom">
|
<unit id="UJpD7n6" name="assembly.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.import_bom</source>
|
<source>assembly.import_bom</source>
|
||||||
|
|
@ -13908,24 +13806,6 @@ Bitte beachten Sie, dass Sie sich nicht als deaktivierter Benutzer ausgeben kön
|
||||||
<target>Preis</target>
|
<target>Preis</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="63adIrC" name="assembly.build.dont_check_quantity">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.dont_check_quantity</source>
|
|
||||||
<target>Mengen nicht überprüfen</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="O0DP6tK" name="assembly.build.dont_check_quantity.help">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.dont_check_quantity.help</source>
|
|
||||||
<target>Wenn diese Option gewählt wird, werden die gewählten Mengen aus dem Lager entfernt, egal ob mehr oder weniger Bauteile sind, als für den Bau der Baugruppe eigentlich benötigt werden.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="9bc0nzK" name="assembly.build.add_builds_to_builds_part">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.add_builds_to_builds_part</source>
|
|
||||||
<target>Gebaute Instanzen zum Bauteil der Baugruppe hinzufügen</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom_import.type</source>
|
<source>assembly.bom_import.type</source>
|
||||||
|
|
|
||||||
|
|
@ -1703,24 +1703,6 @@
|
||||||
<target>Νέο σύνολο</target>
|
<target>Νέο σύνολο</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="M51YUE." name="assembly.edit.associated_build_part">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part</source>
|
|
||||||
<target>Σχετικό μέρος</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nH9R9f." name="assembly.edit.associated_build_part.add">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part.add</source>
|
|
||||||
<target>Προσθήκη μέρους</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="oVfOk.i" name="assembly.edit.associated_build.hint">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build.hint</source>
|
|
||||||
<target>Αυτό το μέρος αντιπροσωπεύει τις κατασκευασμένες εκδόσεις του συνόλου. Καταχωρίστε το εάν απαιτούνται κατασκευασμένες εκδόσεις. Εάν όχι, οι ποσότητες θα χρησιμοποιηθούν μόνο κατά την κατασκευή του εκάστοτε έργου.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.edit.bom.import_bom</source>
|
<source>assembly.edit.bom.import_bom</source>
|
||||||
|
|
@ -1817,60 +1799,6 @@
|
||||||
<target>Προσθήκη εξαρτημάτων</target>
|
<target>Προσθήκη εξαρτημάτων</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="ZbDTUTS" name="assembly.builds.check_assembly_status">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.check_assembly_status</source>
|
|
||||||
<target><![CDATA[Η τρέχουσα κατάσταση συναρμολόγησης είναι <b>«%assembly_status%»</b>. Ελέγξτε εάν θέλετε πραγματικά να κατασκευάσετε τη συναρμολόγηση με αυτήν την κατάσταση!]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="xq1Soad" name="assembly.builds.build_not_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_not_possible</source>
|
|
||||||
<target>Η κατασκευή δεν είναι δυνατή: Δεν υπάρχουν αρκετά διαθέσιμα εξαρτήματα</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="njRyDHQ" name="assembly.builds.following_bom_entries_miss_instock">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock</source>
|
|
||||||
<target>Δεν υπάρχουν αρκετά εξαρτήματα σε απόθεμα για να κατασκευαστεί αυτό το έργο %number_of_builds% φορές. Λείπουν τα ακόλουθα εξαρτήματα:</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="sp7Z0MS" name="assembly.builds.build_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_possible</source>
|
|
||||||
<target>Κατασκευή δυνατή</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1uZzdEl" name="assembly.builds.number_of_builds_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds_possible</source>
|
|
||||||
<target><![CDATA[Διαθέτετε αρκετά εξαρτήματα σε απόθεμα για να κατασκευάσετε <b>%max_builds%</b> μονάδες αυτής της συναρμολόγησης.]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="pW6QLXf" name="assembly.builds.number_of_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds</source>
|
|
||||||
<target>Αριθμός κατασκευών</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="mtJqT_a" name="assembly.build.btn_build">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.btn_build</source>
|
|
||||||
<target>Κατασκευή</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1bCA1zb" name="assembly.build.form.referencedAssembly">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.form.referencedAssembly</source>
|
|
||||||
<target>Συναρμολόγηση "%name%"</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="LFSVVcP" name="assembly.builds.no_stocked_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.no_stocked_builds</source>
|
|
||||||
<target>Αποθηκευμένα κατασκευασμένα κομμάτια</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.info.bom_entries_count</source>
|
<source>assembly.info.bom_entries_count</source>
|
||||||
|
|
@ -1883,18 +1811,6 @@
|
||||||
<target>Υποομάδες</target>
|
<target>Υποομάδες</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="HZYhTlb" name="assembly.builds.stocked">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.stocked</source>
|
|
||||||
<target>σε απόθεμα</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="9EG0PLW" name="assembly.builds.needed">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.needed</source>
|
|
||||||
<target>απαιτούμενο</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom.delete.confirm</source>
|
<source>assembly.bom.delete.confirm</source>
|
||||||
|
|
@ -1937,24 +1853,6 @@
|
||||||
<target>Σχόλια</target>
|
<target>Σχόλια</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="87YpQ_u" name="assembly.builds.following_bom_entries_miss_instock_n">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock_n</source>
|
|
||||||
<target>Δεν υπάρχουν αρκετά εξαρτήματα σε απόθεμα για να κατασκευαστεί αυτή η συναρμολόγηση %number_of_builds% φορές. Λείπουν τα ακόλουθα εξαρτήματα:</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="JlQhDdS" name="assembly.build.help">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.help</source>
|
|
||||||
<target>Επιλέξτε από ποια αποθέματα θα αφαιρεθούν τα αναγκαία για την κατασκευή εξαρτήματα (και σε ποια ποσότητα). Σημειώστε το πλαίσιο επιλογής για κάθε εξάρτημα όταν αφαιρέσετε τα εξαρτήματα ή χρησιμοποιήστε το ανώτερο πλαίσιο επιλογής για να τα ελέγξετε όλα ταυτόχρονα.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="iP5_QVj" name="assembly.build.required_qty">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.required_qty</source>
|
|
||||||
<target>Απαιτούμενη ποσότητα</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="UJpD7n6" name="assembly.import_bom">
|
<unit id="UJpD7n6" name="assembly.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.import_bom</source>
|
<source>assembly.import_bom</source>
|
||||||
|
|
@ -1979,24 +1877,6 @@
|
||||||
<target>Τιμή</target>
|
<target>Τιμή</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="63adIrC" name="assembly.build.dont_check_quantity">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.dont_check_quantity</source>
|
|
||||||
<target>Μην ελέγχετε την ποσότητα</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="O0DP6tK" name="assembly.build.dont_check_quantity.help">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.dont_check_quantity.help</source>
|
|
||||||
<target>Εάν επιλεγεί αυτή η επιλογή, οι επιλεγμένες ποσότητες θα αφαιρεθούν από το απόθεμα ανεξάρτητα από το αν είναι περισσότερο ή λιγότερο από το απαιτούμενο για την κατασκευή της συναρμολόγησης.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="9bc0nzK" name="assembly.build.add_builds_to_builds_part">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.add_builds_to_builds_part</source>
|
|
||||||
<target>Προσθήκη κατασκευασμένων κομματιών στο τμήμα συναρμολόγησης</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom_import.type</source>
|
<source>assembly.bom_import.type</source>
|
||||||
|
|
|
||||||
|
|
@ -13609,24 +13609,6 @@ Please note, that you can not impersonate a disabled user. If you try you will g
|
||||||
<target>New assembly</target>
|
<target>New assembly</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="M51YUE." name="assembly.edit.associated_build_part">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part</source>
|
|
||||||
<target>Associated builds part</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nH9R9f." name="assembly.edit.associated_build_part.add">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part.add</source>
|
|
||||||
<target>Add builds part</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="oVfOk.i" name="assembly.edit.associated_build.hint">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build.hint</source>
|
|
||||||
<target>This part represents the builds of this assembly. To indicate if built instances are required. If not, the number of pieces regarding the assembly are only used for the build of the respective project.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.edit.bom.import_bom</source>
|
<source>assembly.edit.bom.import_bom</source>
|
||||||
|
|
@ -13735,60 +13717,6 @@ Please note, that you can not impersonate a disabled user. If you try you will g
|
||||||
<target>Add part entries</target>
|
<target>Add part entries</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="ZbDTUTS" name="assembly.builds.check_assembly_status">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.check_assembly_status</source>
|
|
||||||
<target><![CDATA[The current assembly status is <b>"%assembly_status%"</b>. You should check if you really want to build the assembly with this status!]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="xq1Soad" name="assembly.builds.build_not_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_not_possible</source>
|
|
||||||
<target>Build not possible: Parts not stocked</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="njRyDHQ" name="assembly.builds.following_bom_entries_miss_instock">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock</source>
|
|
||||||
<target>You do not have enough parts stocked to build this assembly %number_of_builds% times. The following parts have missing instock:</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="sp7Z0MS" name="assembly.builds.build_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_possible</source>
|
|
||||||
<target>Build possible</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1uZzdEl" name="assembly.builds.number_of_builds_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds_possible</source>
|
|
||||||
<target><![CDATA[You have enough stocked to build <b>%max_builds%</b> builds of this assembly.]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="pW6QLXf" name="assembly.builds.number_of_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds</source>
|
|
||||||
<target>Build amount</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="mtJqT_a" name="assembly.build.btn_build">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.btn_build</source>
|
|
||||||
<target>Build</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1bCA1zb" name="assembly.build.form.referencedAssembly">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.form.referencedAssembly</source>
|
|
||||||
<target>Assembly "%name%"</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="LFSVVcP" name="assembly.builds.no_stocked_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.no_stocked_builds</source>
|
|
||||||
<target>Number of stocked builds</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.info.bom_entries_count</source>
|
<source>assembly.info.bom_entries_count</source>
|
||||||
|
|
@ -13801,18 +13729,6 @@ Please note, that you can not impersonate a disabled user. If you try you will g
|
||||||
<target>Sub-assemblies</target>
|
<target>Sub-assemblies</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="HZYhTlb" name="assembly.builds.stocked">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.stocked</source>
|
|
||||||
<target>stocked</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="9EG0PLW" name="assembly.builds.needed">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.needed</source>
|
|
||||||
<target>needed</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom.delete.confirm</source>
|
<source>assembly.bom.delete.confirm</source>
|
||||||
|
|
@ -13861,24 +13777,6 @@ Please note, that you can not impersonate a disabled user. If you try you will g
|
||||||
<target>Notes</target>
|
<target>Notes</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="87YpQ_u" name="assembly.builds.following_bom_entries_miss_instock_n">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock_n</source>
|
|
||||||
<target>You do not have enough parts stocked to build this assembly %number_of_builds% times. The following parts have missing instock:</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="JlQhDdS" name="assembly.build.help">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.help</source>
|
|
||||||
<target>Choose from which part lots the stock to build this assembly should be taken (and in which amount). Check the checkbox for each part, when you are finished withdrawing the parts, or use the top checkbox to check all boxes at once.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="iP5_QVj" name="assembly.build.required_qty">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.required_qty</source>
|
|
||||||
<target>Required quantity</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="UJpD7n6" name="assembly.import_bom">
|
<unit id="UJpD7n6" name="assembly.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.import_bom</source>
|
<source>assembly.import_bom</source>
|
||||||
|
|
@ -13909,24 +13807,6 @@ Please note, that you can not impersonate a disabled user. If you try you will g
|
||||||
<target>Price</target>
|
<target>Price</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="63adIrC" name="assembly.build.dont_check_quantity">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.dont_check_quantity</source>
|
|
||||||
<target>Do not check quantities</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="O0DP6tK" name="assembly.build.dont_check_quantity.help">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.dont_check_quantity.help</source>
|
|
||||||
<target>If this option is selected, the given withdraw quantities are used as given, no matter if more or less parts are actually required to build this assembly.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="9bc0nzK" name="assembly.build.add_builds_to_builds_part">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.add_builds_to_builds_part</source>
|
|
||||||
<target>Add builds to assembly builds part</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom_import.type</source>
|
<source>assembly.bom_import.type</source>
|
||||||
|
|
|
||||||
|
|
@ -12927,24 +12927,6 @@ Por favor ten en cuenta que no puedes personificar a un usuario deshabilitado. S
|
||||||
<target>Nuevo ensamblaje</target>
|
<target>Nuevo ensamblaje</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="M51YUE." name="assembly.edit.associated_build_part">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part</source>
|
|
||||||
<target>Componente asociado</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nH9R9f." name="assembly.edit.associated_build_part.add">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part.add</source>
|
|
||||||
<target>Añadir componente</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="oVfOk.i" name="assembly.edit.associated_build.hint">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build.hint</source>
|
|
||||||
<target>Este componente representa las instancias fabricadas del ensamblaje. Indique si se necesitan instancias fabricadas. De lo contrario, las cantidades del componente solo se utilizarán cuando se construya el proyecto correspondiente.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.edit.bom.import_bom</source>
|
<source>assembly.edit.bom.import_bom</source>
|
||||||
|
|
@ -13053,60 +13035,6 @@ Por favor ten en cuenta que no puedes personificar a un usuario deshabilitado. S
|
||||||
<target>Añadir piezas</target>
|
<target>Añadir piezas</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="ZbDTUTS" name="assembly.builds.check_assembly_status">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.check_assembly_status</source>
|
|
||||||
<target><![CDATA[El estado actual del ensamblaje es <b>"%assembly_status%"</b>. ¡Por favor, verifica si realmente deseas construir el ensamblaje con este estado!]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="xq1Soad" name="assembly.builds.build_not_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_not_possible</source>
|
|
||||||
<target>Construcción no posible: No hay suficientes componentes disponibles</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="njRyDHQ" name="assembly.builds.following_bom_entries_miss_instock">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock</source>
|
|
||||||
<target>No hay suficientes piezas en stock para construir este proyecto %number_of_builds% veces. Faltan las siguientes piezas:</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="sp7Z0MS" name="assembly.builds.build_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_possible</source>
|
|
||||||
<target>Construcción posible</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1uZzdEl" name="assembly.builds.number_of_builds_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds_possible</source>
|
|
||||||
<target><![CDATA[Disponen de suficientes piezas en stock para construir <b>%max_builds%</b> unidades de este ensamblaje.]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="pW6QLXf" name="assembly.builds.number_of_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds</source>
|
|
||||||
<target>Número de construcciones</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="mtJqT_a" name="assembly.build.btn_build">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.btn_build</source>
|
|
||||||
<target>Construir</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1bCA1zb" name="assembly.build.form.referencedAssembly">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.form.referencedAssembly</source>
|
|
||||||
<target>Ensamblaje "%name%"</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="LFSVVcP" name="assembly.builds.no_stocked_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.no_stocked_builds</source>
|
|
||||||
<target>Unidades construidas almacenadas</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.info.bom_entries_count</source>
|
<source>assembly.info.bom_entries_count</source>
|
||||||
|
|
@ -13119,18 +13047,6 @@ Por favor ten en cuenta que no puedes personificar a un usuario deshabilitado. S
|
||||||
<target>Subconjuntos</target>
|
<target>Subconjuntos</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="HZYhTlb" name="assembly.builds.stocked">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.stocked</source>
|
|
||||||
<target>en stock</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="9EG0PLW" name="assembly.builds.needed">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.needed</source>
|
|
||||||
<target>necesario</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom.delete.confirm</source>
|
<source>assembly.bom.delete.confirm</source>
|
||||||
|
|
@ -13179,24 +13095,6 @@ Por favor ten en cuenta que no puedes personificar a un usuario deshabilitado. S
|
||||||
<target>Comentarios</target>
|
<target>Comentarios</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="87YpQ_u" name="assembly.builds.following_bom_entries_miss_instock_n">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock_n</source>
|
|
||||||
<target>No hay suficientes piezas en stock para construir este ensamblaje %number_of_builds% veces. Faltan las siguientes piezas:</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="JlQhDdS" name="assembly.build.help">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.help</source>
|
|
||||||
<target>Seleccione de qué almacenes se tomarán las piezas necesarias para la construcción (y en qué cantidad). Marque la casilla de cada entrada una vez que haya quitado las piezas, o use la casilla superior para marcarlas todas a la vez.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="iP5_QVj" name="assembly.build.required_qty">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.required_qty</source>
|
|
||||||
<target>Cantidad requerida</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="UJpD7n6" name="assembly.import_bom">
|
<unit id="UJpD7n6" name="assembly.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.import_bom</source>
|
<source>assembly.import_bom</source>
|
||||||
|
|
@ -13227,24 +13125,6 @@ Por favor ten en cuenta que no puedes personificar a un usuario deshabilitado. S
|
||||||
<target>Precio</target>
|
<target>Precio</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="63adIrC" name="assembly.build.dont_check_quantity">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.dont_check_quantity</source>
|
|
||||||
<target>No verificar cantidades</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="O0DP6tK" name="assembly.build.dont_check_quantity.help">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.dont_check_quantity.help</source>
|
|
||||||
<target>Si se selecciona esta opción, las cantidades seleccionadas se quitarán del inventario independientemente de si hay más o menos de lo necesario para construir el ensamblaje.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="9bc0nzK" name="assembly.build.add_builds_to_builds_part">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.add_builds_to_builds_part</source>
|
|
||||||
<target>Añadir unidades construidas a la parte del ensamblaje</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom_import.type</source>
|
<source>assembly.bom_import.type</source>
|
||||||
|
|
|
||||||
|
|
@ -9319,24 +9319,6 @@ exemple de ville</target>
|
||||||
<target>Nouvel assemblage</target>
|
<target>Nouvel assemblage</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="M51YUE." name="assembly.edit.associated_build_part">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part</source>
|
|
||||||
<target>Composant associé</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nH9R9f." name="assembly.edit.associated_build_part.add">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part.add</source>
|
|
||||||
<target>Ajouter un composant</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="oVfOk.i" name="assembly.edit.associated_build.hint">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build.hint</source>
|
|
||||||
<target>Ce composant représente les instances fabriquées de l'assemblage. Indiquez si des instances fabriquées sont nécessaires. Sinon, les quantités des composants ne seront appliquées que lors de la construction du projet correspondant.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.edit.bom.import_bom</source>
|
<source>assembly.edit.bom.import_bom</source>
|
||||||
|
|
@ -9445,60 +9427,6 @@ exemple de ville</target>
|
||||||
<target>Ajouter des pièces</target>
|
<target>Ajouter des pièces</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="ZbDTUTS" name="assembly.builds.check_assembly_status">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.check_assembly_status</source>
|
|
||||||
<target><![CDATA[Le statut actuel de l'assemblage est <b>"%assembly_status%"</b>. Vérifiez bien si vous souhaitez construire l'assemblage avec ce statut !]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="xq1Soad" name="assembly.builds.build_not_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_not_possible</source>
|
|
||||||
<target>Construction impossible : pièces insuffisantes disponibles</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="njRyDHQ" name="assembly.builds.following_bom_entries_miss_instock">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock</source>
|
|
||||||
<target>Il n'y a pas suffisamment de pièces en stock pour construire ce projet %number_of_builds% fois. Les pièces suivantes manquent en stock :</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="sp7Z0MS" name="assembly.builds.build_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_possible</source>
|
|
||||||
<target>Construction possible</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1uZzdEl" name="assembly.builds.number_of_builds_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds_possible</source>
|
|
||||||
<target><![CDATA[Vous disposez de suffisamment de pièces en stock pour construire <b>%max_builds%</b> unités de cet assemblage.]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="pW6QLXf" name="assembly.builds.number_of_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds</source>
|
|
||||||
<target>Nombre d'assemblages à construire</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="mtJqT_a" name="assembly.build.btn_build">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.btn_build</source>
|
|
||||||
<target>Construire</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1bCA1zb" name="assembly.build.form.referencedAssembly">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.form.referencedAssembly</source>
|
|
||||||
<target>Assemblage "%name%"</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="LFSVVcP" name="assembly.builds.no_stocked_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.no_stocked_builds</source>
|
|
||||||
<target>Nombre d'instances construites en stock</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.info.bom_entries_count</source>
|
<source>assembly.info.bom_entries_count</source>
|
||||||
|
|
@ -9511,18 +9439,6 @@ exemple de ville</target>
|
||||||
<target>Sous-ensembles</target>
|
<target>Sous-ensembles</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="HZYhTlb" name="assembly.builds.stocked">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.stocked</source>
|
|
||||||
<target>en stock</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="9EG0PLW" name="assembly.builds.needed">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.needed</source>
|
|
||||||
<target>nécessaire</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom.delete.confirm</source>
|
<source>assembly.bom.delete.confirm</source>
|
||||||
|
|
@ -9571,24 +9487,6 @@ exemple de ville</target>
|
||||||
<target>Commentaires</target>
|
<target>Commentaires</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="87YpQ_u" name="assembly.builds.following_bom_entries_miss_instock_n">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock_n</source>
|
|
||||||
<target>Il n'y a pas suffisamment de pièces en stock pour construire cet assemblage %number_of_builds% fois. Les pièces suivantes manquent en stock :</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="JlQhDdS" name="assembly.build.help">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.help</source>
|
|
||||||
<target>Sélectionnez les stocks à partir desquels les pièces nécessaires à la construction seront prises (et en quelle quantité). Vérifiez chaque pièce en les retirant, ou utilisez la case supérieure pour les sélectionner toutes à la fois.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="iP5_QVj" name="assembly.build.required_qty">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.required_qty</source>
|
|
||||||
<target>Quantité requise</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="UJpD7n6" name="assembly.import_bom">
|
<unit id="UJpD7n6" name="assembly.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.import_bom</source>
|
<source>assembly.import_bom</source>
|
||||||
|
|
@ -9619,24 +9517,6 @@ exemple de ville</target>
|
||||||
<target>Prix</target>
|
<target>Prix</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="63adIrC" name="assembly.build.dont_check_quantity">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.dont_check_quantity</source>
|
|
||||||
<target>Ne pas vérifier les quantités</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="O0DP6tK" name="assembly.build.dont_check_quantity.help">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.dont_check_quantity.help</source>
|
|
||||||
<target>Si cette option est activée, les quantités sélectionnées seront retirées du stock, quelle que soit leur suffisance pour l’assemblage.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="9bc0nzK" name="assembly.build.add_builds_to_builds_part">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.add_builds_to_builds_part</source>
|
|
||||||
<target>Ajouter les unités construites à la pièce assemblée</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom_import.type</source>
|
<source>assembly.bom_import.type</source>
|
||||||
|
|
|
||||||
|
|
@ -12929,24 +12929,6 @@ Notare che non è possibile impersonare un utente disattivato. Quando si prova a
|
||||||
<target>Nuovo assemblaggio</target>
|
<target>Nuovo assemblaggio</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="M51YUE." name="assembly.edit.associated_build_part">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part</source>
|
|
||||||
<target>Componente associato</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nH9R9f." name="assembly.edit.associated_build_part.add">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part.add</source>
|
|
||||||
<target>Aggiungi componente</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="oVfOk.i" name="assembly.edit.associated_build.hint">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build.hint</source>
|
|
||||||
<target>Questo componente rappresenta le istanze fabbricate dell'assemblaggio. Specificare se sono necessarie istanze fabbricate. In caso contrario, le quantità di componenti verranno utilizzate solo durante la costruzione del progetto corrispondente.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.edit.bom.import_bom</source>
|
<source>assembly.edit.bom.import_bom</source>
|
||||||
|
|
@ -13055,60 +13037,6 @@ Notare che non è possibile impersonare un utente disattivato. Quando si prova a
|
||||||
<target>Aggiungi componenti</target>
|
<target>Aggiungi componenti</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="ZbDTUTS" name="assembly.builds.check_assembly_status">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.check_assembly_status</source>
|
|
||||||
<target><![CDATA[Lo stato attuale del gruppo è <b>"%assembly_status%"</b>. Controlla se vuoi davvero costruire il gruppo con questo stato!]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="xq1Soad" name="assembly.builds.build_not_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_not_possible</source>
|
|
||||||
<target>Costruzione impossibile: componenti insufficienti disponibili</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="njRyDHQ" name="assembly.builds.following_bom_entries_miss_instock">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock</source>
|
|
||||||
<target>Non ci sono abbastanza componenti in magazzino per costruire questo progetto %number_of_builds% volte. Mancano i seguenti componenti:</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="sp7Z0MS" name="assembly.builds.build_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_possible</source>
|
|
||||||
<target>Costruzione possibile</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1uZzdEl" name="assembly.builds.number_of_builds_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds_possible</source>
|
|
||||||
<target><![CDATA[Hai abbastanza pezzi in magazzino per costruire <b>%max_builds%</b> unità di questo gruppo.]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="pW6QLXf" name="assembly.builds.number_of_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds</source>
|
|
||||||
<target>Numero di gruppi da costruire</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="mtJqT_a" name="assembly.build.btn_build">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.btn_build</source>
|
|
||||||
<target>Costruire</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1bCA1zb" name="assembly.build.form.referencedAssembly">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.form.referencedAssembly</source>
|
|
||||||
<target>Gruppo "%name%"</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="LFSVVcP" name="assembly.builds.no_stocked_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.no_stocked_builds</source>
|
|
||||||
<target>Numero di istanze costruite in magazzino</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.info.bom_entries_count</source>
|
<source>assembly.info.bom_entries_count</source>
|
||||||
|
|
@ -13121,18 +13049,6 @@ Notare che non è possibile impersonare un utente disattivato. Quando si prova a
|
||||||
<target>Sotto-gruppi</target>
|
<target>Sotto-gruppi</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="HZYhTlb" name="assembly.builds.stocked">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.stocked</source>
|
|
||||||
<target>disponibile</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="9EG0PLW" name="assembly.builds.needed">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.needed</source>
|
|
||||||
<target>necessari</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom.delete.confirm</source>
|
<source>assembly.bom.delete.confirm</source>
|
||||||
|
|
@ -13181,24 +13097,6 @@ Notare che non è possibile impersonare un utente disattivato. Quando si prova a
|
||||||
<target>Commenti</target>
|
<target>Commenti</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="87YpQ_u" name="assembly.builds.following_bom_entries_miss_instock_n">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock_n</source>
|
|
||||||
<target>Non ci sono abbastanza componenti in magazzino per costruire questo gruppo %number_of_builds% volte. Mancano i seguenti componenti:</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="JlQhDdS" name="assembly.build.help">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.help</source>
|
|
||||||
<target>Seleziona i magazzini da cui prelevare i componenti necessari per la costruzione (e in che quantità). Spunta ciascun componente una volta prelevato, oppure utilizza la casella superiore per selezionare tutto in una volta.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="iP5_QVj" name="assembly.build.required_qty">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.required_qty</source>
|
|
||||||
<target>Quantità necessaria</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="UJpD7n6" name="assembly.import_bom">
|
<unit id="UJpD7n6" name="assembly.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.import_bom</source>
|
<source>assembly.import_bom</source>
|
||||||
|
|
@ -13229,24 +13127,6 @@ Notare che non è possibile impersonare un utente disattivato. Quando si prova a
|
||||||
<target>Prezzo</target>
|
<target>Prezzo</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="63adIrC" name="assembly.build.dont_check_quantity">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.dont_check_quantity</source>
|
|
||||||
<target>Non controllare le quantità</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="O0DP6tK" name="assembly.build.dont_check_quantity.help">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.dont_check_quantity.help</source>
|
|
||||||
<target>Se abilitata, le quantità selezionate verranno rimosse dal magazzino indipendentemente dalla loro sufficienza per il gruppo.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="9bc0nzK" name="assembly.build.add_builds_to_builds_part">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.add_builds_to_builds_part</source>
|
|
||||||
<target>Aggiungi istanze costruite al gruppo componenti</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom_import.type</source>
|
<source>assembly.bom_import.type</source>
|
||||||
|
|
|
||||||
|
|
@ -9056,24 +9056,6 @@ Exampletown</target>
|
||||||
<target>新しいアセンブリ</target>
|
<target>新しいアセンブリ</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="M51YUE." name="assembly.edit.associated_build_part">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part</source>
|
|
||||||
<target>関連コンポーネント</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nH9R9f." name="assembly.edit.associated_build_part.add">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part.add</source>
|
|
||||||
<target>コンポーネントを追加</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="oVfOk.i" name="assembly.edit.associated_build.hint">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build.hint</source>
|
|
||||||
<target>このコンポーネントは、アセンブリの製造されたインスタンスを表します。製造されたインスタンスが必要な場合は登録してください。それ以外の場合、コンポーネントの数量は該当するプロジェクトを構築する際にのみ使用されます。</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.edit.bom.import_bom</source>
|
<source>assembly.edit.bom.import_bom</source>
|
||||||
|
|
@ -9182,60 +9164,6 @@ Exampletown</target>
|
||||||
<target>部品を追加</target>
|
<target>部品を追加</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="ZbDTUTS" name="assembly.builds.check_assembly_status">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.check_assembly_status</source>
|
|
||||||
<target><![CDATA[アセンブリの現在の状態は<b>"%assembly_status%"</b>です。この状態でビルドを続行してよろしいですか?]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="xq1Soad" name="assembly.builds.build_not_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_not_possible</source>
|
|
||||||
<target>ビルド不可能: 必要な部品が不足しています</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="njRyDHQ" name="assembly.builds.following_bom_entries_miss_instock">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock</source>
|
|
||||||
<target>%number_of_builds% 回のビルドを行うのに十分な部品在庫がありません。不足している部品:</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="sp7Z0MS" name="assembly.builds.build_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_possible</source>
|
|
||||||
<target>ビルド可能</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1uZzdEl" name="assembly.builds.number_of_builds_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds_possible</source>
|
|
||||||
<target><![CDATA[現在の在庫では<b>%max_builds%</b> 回のアセンブリをビルドできます。]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="pW6QLXf" name="assembly.builds.number_of_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds</source>
|
|
||||||
<target>ビルドするアセンブリ数</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="mtJqT_a" name="assembly.build.btn_build">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.btn_build</source>
|
|
||||||
<target>ビルド</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1bCA1zb" name="assembly.build.form.referencedAssembly">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.form.referencedAssembly</source>
|
|
||||||
<target>アセンブリ「%name%」</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="LFSVVcP" name="assembly.builds.no_stocked_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.no_stocked_builds</source>
|
|
||||||
<target>在庫のビルド済みアセンブリ数</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.info.bom_entries_count</source>
|
<source>assembly.info.bom_entries_count</source>
|
||||||
|
|
@ -9248,18 +9176,6 @@ Exampletown</target>
|
||||||
<target>サブアセンブリ</target>
|
<target>サブアセンブリ</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="HZYhTlb" name="assembly.builds.stocked">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.stocked</source>
|
|
||||||
<target>在庫あり</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="9EG0PLW" name="assembly.builds.needed">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.needed</source>
|
|
||||||
<target>必要数量</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom.delete.confirm</source>
|
<source>assembly.bom.delete.confirm</source>
|
||||||
|
|
@ -9308,24 +9224,6 @@ Exampletown</target>
|
||||||
<target>コメント</target>
|
<target>コメント</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="87YpQ_u" name="assembly.builds.following_bom_entries_miss_instock_n">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock_n</source>
|
|
||||||
<target>このアセンブリを%number_of_builds%回作成するための部品が十分に在庫にありません。以下の部品が不足しています:</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="JlQhDdS" name="assembly.build.help">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.help</source>
|
|
||||||
<target>どの在庫から必要な部品を取り出すか(およびその数量)を選択してください。部品を取り出した場合は、各項目のチェックをオンにするか、最上部のチェックボックスを使って一括でオンにすることができます。</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="rs_qty" name="assembly.build.required_qty">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.required_qty</source>
|
|
||||||
<target>必要な数量</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="UJpD7n6" name="assembly.import_bom">
|
<unit id="UJpD7n6" name="assembly.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.import_bom</source>
|
<source>assembly.import_bom</source>
|
||||||
|
|
@ -9344,36 +9242,12 @@ Exampletown</target>
|
||||||
<target>識別子</target>
|
<target>識別子</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="yes_button" name="assembly.build.yes_button">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.yes_button</source>
|
|
||||||
<target>はい</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="no_button" name="assembly.build.no_button">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.no_button</source>
|
|
||||||
<target>いいえ</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="JLhsU08" name="assembly.confirmation.required">
|
<unit id="JLhsU08" name="assembly.confirmation.required">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.confirmation.required</source>
|
<source>assembly.confirmation.required</source>
|
||||||
<target><![CDATA[続行してよろしいですか?]]></target>
|
<target><![CDATA[続行してよろしいですか?]]></target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="build_success" name="assembly.build.success">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.success</source>
|
|
||||||
<target>ビルドが正常に完了しました!</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="build_cancelled" name="assembly.build.cancelled">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.cancelled</source>
|
|
||||||
<target>ビルドがキャンセルされました。</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom_import.type</source>
|
<source>assembly.bom_import.type</source>
|
||||||
|
|
|
||||||
|
|
@ -892,24 +892,6 @@
|
||||||
<target>Nieuwe assemblage</target>
|
<target>Nieuwe assemblage</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="M51YUE." name="assembly.edit.associated_build_part">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part</source>
|
|
||||||
<target>Geassocieerd onderdeel</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nH9R9f." name="assembly.edit.associated_build_part.add">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part.add</source>
|
|
||||||
<target>Onderdeel toevoegen</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="oVfOk.i" name="assembly.edit.associated_build.hint">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build.hint</source>
|
|
||||||
<target>Dit onderdeel vertegenwoordigt de vervaardigde exemplaren van de assemblage. Geef aan of vervaardigde exemplaren nodig zijn. Zo niet, dan worden de aantallen onderdelen alleen gebruikt bij het bouwen van het bijbehorende project.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.edit.bom.import_bom</source>
|
<source>assembly.edit.bom.import_bom</source>
|
||||||
|
|
@ -1018,60 +1000,6 @@
|
||||||
<target>Onderdelen toevoegen</target>
|
<target>Onderdelen toevoegen</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="ZbDTUTS" name="assembly.builds.check_assembly_status">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.check_assembly_status</source>
|
|
||||||
<target><![CDATA[De huidige status van de assemblage is <b>"%assembly_status%"</b>. Bevestig dat je hiermee wilt doorgaan!]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="xq1Soad" name="assembly.builds.build_not_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_not_possible</source>
|
|
||||||
<target>Bouwen is niet mogelijk: niet voldoende onderdelen beschikbaar</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="njRyDHQ" name="assembly.builds.following_bom_entries_miss_instock">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock</source>
|
|
||||||
<target>Er zijn niet voldoende onderdelen in voorraad om %number_of_builds% keer te bouwen. De volgende onderdelen ontbreken:</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="sp7Z0MS" name="assembly.builds.build_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_possible</source>
|
|
||||||
<target>Bouwen mogelijk</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1uZzdEl" name="assembly.builds.number_of_builds_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds_possible</source>
|
|
||||||
<target><![CDATA[Er zijn genoeg onderdelen beschikbaar om <b>%max_builds%</b> assemblages te bouwen.]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="pW6QLXf" name="assembly.builds.number_of_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds</source>
|
|
||||||
<target>Aantal te bouwen assemblages</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="mtJqT_a" name="assembly.build.btn_build">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.btn_build</source>
|
|
||||||
<target>Bouwen</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1bCA1zb" name="assembly.build.form.referencedAssembly">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.form.referencedAssembly</source>
|
|
||||||
<target>Assemblage "%name%"</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="LFSVVcP" name="assembly.builds.no_stocked_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.no_stocked_builds</source>
|
|
||||||
<target>Aantal geassembleerde onderdelen op voorraad</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.info.bom_entries_count</source>
|
<source>assembly.info.bom_entries_count</source>
|
||||||
|
|
@ -1084,18 +1012,6 @@
|
||||||
<target>Subgroepen</target>
|
<target>Subgroepen</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="HZYhTlb" name="assembly.builds.stocked">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.stocked</source>
|
|
||||||
<target>Op voorraad</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="9EG0PLW" name="assembly.builds.needed">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.needed</source>
|
|
||||||
<target>Nodig</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom.delete.confirm</source>
|
<source>assembly.bom.delete.confirm</source>
|
||||||
|
|
@ -1144,24 +1060,6 @@
|
||||||
<target>Notities</target>
|
<target>Notities</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="87YpQ_u" name="assembly.builds.following_bom_entries_miss_instock_n">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock_n</source>
|
|
||||||
<target>Er zijn niet genoeg onderdelen op voorraad om deze assemblage %number_of_builds% keer te bouwen. Van de volgende onderdelen is er niet genoeg op voorraad:</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="JlQhDdS" name="assembly.build.help">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.help</source>
|
|
||||||
<target>Selecteer uit welke voorraden de benodigde onderdelen voor de bouw gehaald moeten worden (en in welke hoeveelheid). Vink elk onderdeel afzonderlijk aan als het is verwijderd, of gebruik de bovenste selectievak om alle selectievakjes in één keer aan te vinken.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="iP5_QVj" name="assembly.build.required_qty">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.required_qty</source>
|
|
||||||
<target>Benodigde hoeveelheid</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="UJpD7n6" name="assembly.import_bom">
|
<unit id="UJpD7n6" name="assembly.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.import_bom</source>
|
<source>assembly.import_bom</source>
|
||||||
|
|
@ -1192,60 +1090,12 @@
|
||||||
<target>Prijs</target>
|
<target>Prijs</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="63adIrC" name="assembly.build.dont_check_quantity">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.dont_check_quantity</source>
|
|
||||||
<target>Hoeveelheden niet controleren</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="O0DP6tK" name="assembly.build.dont_check_quantity.help">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.dont_check_quantity.help</source>
|
|
||||||
<target>Als deze optie is geselecteerd, worden de geselecteerde hoeveelheden uit de voorraad verwijderd, ongeacht of er meer of minder onderdelen zijn dan nodig is voor de assemblage.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="9bc0nzK" name="assembly.build.add_builds_to_builds_part">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.add_builds_to_builds_part</source>
|
|
||||||
<target>Gemaakte instanties toevoegen aan onderdeel van assemblage</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="rs_qty" name="assembly.build.required_qty">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.required_qty</source>
|
|
||||||
<target>Benodigd aantal</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="yes_button" name="assembly.build.yes_button">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.yes_button</source>
|
|
||||||
<target>Ja</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="no_button" name="assembly.build.no_button">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.no_button</source>
|
|
||||||
<target>Nee</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="JLhsU08" name="assembly.confirmation.required">
|
<unit id="JLhsU08" name="assembly.confirmation.required">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.confirmation.required</source>
|
<source>assembly.confirmation.required</source>
|
||||||
<target><![CDATA[Bevestig je dat je door wilt gaan?]]></target>
|
<target><![CDATA[Bevestig je dat je door wilt gaan?]]></target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="build_success" name="assembly.build.success">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.success</source>
|
|
||||||
<target>De assemblage is succesvol gebouwd!</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="build_cancelled" name="assembly.build.cancelled">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.cancelled</source>
|
|
||||||
<target>De assemblage is geannuleerd.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom_import.type</source>
|
<source>assembly.bom_import.type</source>
|
||||||
|
|
|
||||||
|
|
@ -12806,24 +12806,6 @@ Należy pamiętać, że nie możesz udawać nieaktywnych użytkowników. Jeśli
|
||||||
<target>Nowy zespół</target>
|
<target>Nowy zespół</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="M51YUE." name="assembly.edit.associated_build_part">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part</source>
|
|
||||||
<target>Powiązany komponent</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nH9R9f." name="assembly.edit.associated_build_part.add">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part.add</source>
|
|
||||||
<target>Dodaj komponent</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="oVfOk.i" name="assembly.edit.associated_build.hint">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build.hint</source>
|
|
||||||
<target>Ten komponent reprezentuje wyprodukowane instancje zespołu. Określ, czy są potrzebne wyprodukowane instancje. W przeciwnym razie ilości komponentów zostaną zastosowane tylko podczas budowy odpowiedniego projektu.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.edit.bom.import_bom</source>
|
<source>assembly.edit.bom.import_bom</source>
|
||||||
|
|
@ -12932,60 +12914,6 @@ Należy pamiętać, że nie możesz udawać nieaktywnych użytkowników. Jeśli
|
||||||
<target>Dodaj części</target>
|
<target>Dodaj części</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="ZbDTUTS" name="assembly.builds.check_assembly_status">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.check_assembly_status</source>
|
|
||||||
<target><![CDATA[Obecny status zespołu to <b>"%assembly_status%"</b>. Upewnij się, że chcesz zbudować zespół w tym statusie!]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="xq1Soad" name="assembly.builds.build_not_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_not_possible</source>
|
|
||||||
<target>Budowa niemożliwa: niewystarczająca ilość części</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="njRyDHQ" name="assembly.builds.following_bom_entries_miss_instock">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock</source>
|
|
||||||
<target>Brakuje wystarczającej ilości części na magazynie, aby zbudować ten projekt %number_of_builds% razy. Brakujące części to:</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="sp7Z0MS" name="assembly.builds.build_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_possible</source>
|
|
||||||
<target>Budowa możliwa</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1uZzdEl" name="assembly.builds.number_of_builds_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds_possible</source>
|
|
||||||
<target><![CDATA[Masz wystarczająco dużo części na magazynie, aby zbudować <b>%max_builds%</b> egzemplarzy tego zespołu.]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="pW6QLXf" name="assembly.builds.number_of_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds</source>
|
|
||||||
<target>Liczba budowanych egzemplarzy</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="mtJqT_a" name="assembly.build.btn_build">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.btn_build</source>
|
|
||||||
<target>Zbuduj</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1bCA1zb" name="assembly.build.form.referencedAssembly">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.form.referencedAssembly</source>
|
|
||||||
<target>Zespół "%name%"</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="LFSVVcP" name="assembly.builds.no_stocked_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.no_stocked_builds</source>
|
|
||||||
<target>Liczba zbudowanych i zmagazynowanych egzemplarzy</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.info.bom_entries_count</source>
|
<source>assembly.info.bom_entries_count</source>
|
||||||
|
|
@ -12998,18 +12926,6 @@ Należy pamiętać, że nie możesz udawać nieaktywnych użytkowników. Jeśli
|
||||||
<target>Podzespoły</target>
|
<target>Podzespoły</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="HZYhTlb" name="assembly.builds.stocked">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.stocked</source>
|
|
||||||
<target>na magazynie</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="9EG0PLW" name="assembly.builds.needed">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.needed</source>
|
|
||||||
<target>potrzebne</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom.delete.confirm</source>
|
<source>assembly.bom.delete.confirm</source>
|
||||||
|
|
@ -13058,24 +12974,6 @@ Należy pamiętać, że nie możesz udawać nieaktywnych użytkowników. Jeśli
|
||||||
<target>Uwagi</target>
|
<target>Uwagi</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="87YpQ_u" name="assembly.builds.following_bom_entries_miss_instock_n">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock_n</source>
|
|
||||||
<target>Brakuje wystarczającej ilości części na magazynie, aby zbudować ten zespół %number_of_builds% razy. Brakujące części to:</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="JlQhDdS" name="assembly.build.help">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.help</source>
|
|
||||||
<target>Wybierz, z których magazynów mają być pobrane części potrzebne do budowy (i w jakiej ilości). Zaznacz każdą pozycję, jeśli części zostały pobrane, lub użyj głównego pola wyboru, aby zaznaczyć wszystkie na raz.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="iP5_QVj" name="assembly.build.required_qty">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.required_qty</source>
|
|
||||||
<target>Wymagana ilość</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="UJpD7n6" name="assembly.import_bom">
|
<unit id="UJpD7n6" name="assembly.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.import_bom</source>
|
<source>assembly.import_bom</source>
|
||||||
|
|
@ -13106,24 +13004,6 @@ Należy pamiętać, że nie możesz udawać nieaktywnych użytkowników. Jeśli
|
||||||
<target>Cena</target>
|
<target>Cena</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="63adIrC" name="assembly.build.dont_check_quantity">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.dont_check_quantity</source>
|
|
||||||
<target>Nie sprawdzaj ilości</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="O0DP6tK" name="assembly.build.dont_check_quantity.help">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.dont_check_quantity.help</source>
|
|
||||||
<target>Jeśli opcja jest wybrana, zadeklarowana ilość zostanie odjęta z magazynu, niezależnie od tego, czy jest wystarczająca do budowy zespołu.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="9bc0nzK" name="assembly.build.add_builds_to_builds_part">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.add_builds_to_builds_part</source>
|
|
||||||
<target>Dodaj zbudowane egzemplarze jako część zespołu</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom_import.type</source>
|
<source>assembly.bom_import.type</source>
|
||||||
|
|
|
||||||
|
|
@ -12906,24 +12906,6 @@
|
||||||
<target>Новая сборка</target>
|
<target>Новая сборка</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="M51YUE." name="assembly.edit.associated_build_part">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part</source>
|
|
||||||
<target>Связанный компонент</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nH9R9f." name="assembly.edit.associated_build_part.add">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part.add</source>
|
|
||||||
<target>Добавить компонент</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="oVfOk.i" name="assembly.edit.associated_build.hint">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build.hint</source>
|
|
||||||
<target>Этот компонент представляет изготовленные экземпляры сборки. Укажите, нужны ли изготовленные экземпляры. В противном случае количество компонентов будет использоваться только при создании соответствующего проекта.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.edit.bom.import_bom</source>
|
<source>assembly.edit.bom.import_bom</source>
|
||||||
|
|
@ -13032,60 +13014,6 @@
|
||||||
<target>Добавить детали</target>
|
<target>Добавить детали</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="ZbDTUTS" name="assembly.builds.check_assembly_status">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.check_assembly_status</source>
|
|
||||||
<target><![CDATA[Текущий статус сборки: <b>"%assembly_status%"</b>. Убедитесь, что действительно хотите выполнить сборку с этим статусом!]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="xq1Soad" name="assembly.builds.build_not_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_not_possible</source>
|
|
||||||
<target>Сборка невозможна: недостаточно деталей</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="njRyDHQ" name="assembly.builds.following_bom_entries_miss_instock">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock</source>
|
|
||||||
<target>Недостаточно деталей на складе для сборки %number_of_builds% экземпляров. Следующие детали отсутствуют в достаточном количестве:</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="sp7Z0MS" name="assembly.builds.build_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_possible</source>
|
|
||||||
<target>Сборка возможна</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1uZzdEl" name="assembly.builds.number_of_builds_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds_possible</source>
|
|
||||||
<target><![CDATA[На складе имеется достаточно деталей для сборки <b>%max_builds%</b> экземпляров.]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="pW6QLXf" name="assembly.builds.number_of_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds</source>
|
|
||||||
<target>Количество сборок</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="mtJqT_a" name="assembly.build.btn_build">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.btn_build</source>
|
|
||||||
<target>Собрать</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1bCA1zb" name="assembly.build.form.referencedAssembly">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.form.referencedAssembly</source>
|
|
||||||
<target>Сборка "%name%"</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="LFSVVcP" name="assembly.builds.no_stocked_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.no_stocked_builds</source>
|
|
||||||
<target>Собранные экземпляры на складе</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.info.bom_entries_count</source>
|
<source>assembly.info.bom_entries_count</source>
|
||||||
|
|
@ -13098,18 +13026,6 @@
|
||||||
<target>Подсборки</target>
|
<target>Подсборки</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="HZYhTlb" name="assembly.builds.stocked">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.stocked</source>
|
|
||||||
<target>На складе</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="9EG0PLW" name="assembly.builds.needed">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.needed</source>
|
|
||||||
<target>Необходимо</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom.delete.confirm</source>
|
<source>assembly.bom.delete.confirm</source>
|
||||||
|
|
@ -13158,24 +13074,6 @@
|
||||||
<target>Примечания</target>
|
<target>Примечания</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="87YpQ_u" name="assembly.builds.following_bom_entries_miss_instock_n">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock_n</source>
|
|
||||||
<target>Недостаточно деталей на складе для сборки %number_of_builds% экземпляров. У следующих деталей недостаточное количество:</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="JlQhDdS" name="assembly.build.help">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.help</source>
|
|
||||||
<target>Выберите, из каких запасов брать необходимые для сборки детали (и в каком количестве). Установите галочку для каждой позиции, если детали были взяты, или используйте основную галочку, чтобы отметить все позиции сразу.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="iP5_QVj" name="assembly.build.required_qty">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.required_qty</source>
|
|
||||||
<target>Необходимое количество</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="UJpD7n6" name="assembly.import_bom">
|
<unit id="UJpD7n6" name="assembly.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.import_bom</source>
|
<source>assembly.import_bom</source>
|
||||||
|
|
@ -13206,24 +13104,6 @@
|
||||||
<target>Цена</target>
|
<target>Цена</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="63adIrC" name="assembly.build.dont_check_quantity">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.dont_check_quantity</source>
|
|
||||||
<target>Не проверять количество</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="O0DP6tK" name="assembly.build.dont_check_quantity.help">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.dont_check_quantity.help</source>
|
|
||||||
<target>Если выбрано, указанные количества будут списаны со склада независимо от того, достаточно их или нет для указанной сборки.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="9bc0nzK" name="assembly.build.add_builds_to_builds_part">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.add_builds_to_builds_part</source>
|
|
||||||
<target>Добавить собранные экземпляры как компонент для подсборки</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom_import.type</source>
|
<source>assembly.bom_import.type</source>
|
||||||
|
|
|
||||||
|
|
@ -12791,24 +12791,6 @@ Element 3</target>
|
||||||
<target>新装配</target>
|
<target>新装配</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="M51YUE." name="assembly.edit.associated_build_part">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part</source>
|
|
||||||
<target>关联组件</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nH9R9f." name="assembly.edit.associated_build_part.add">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build_part.add</source>
|
|
||||||
<target>添加组件</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="oVfOk.i" name="assembly.edit.associated_build.hint">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.edit.associated_build.hint</source>
|
|
||||||
<target>此组件表示装配的生产实例。指定是否需要生产实例。如果不需要,则组件数量仅在构建相关项目时使用。</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
<unit id="_wZ_JZY" name="assembly.edit.bom.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.edit.bom.import_bom</source>
|
<source>assembly.edit.bom.import_bom</source>
|
||||||
|
|
@ -12917,60 +12899,6 @@ Element 3</target>
|
||||||
<target>添加零件</target>
|
<target>添加零件</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="ZbDTUTS" name="assembly.builds.check_assembly_status">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.check_assembly_status</source>
|
|
||||||
<target><![CDATA[当前装配状态为 <b>"%assembly_status%"</b>。请确认您是否要在该状态下构建组件!]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="xq1Soad" name="assembly.builds.build_not_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_not_possible</source>
|
|
||||||
<target>无法构建:零件数量不足</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="njRyDHQ" name="assembly.builds.following_bom_entries_miss_instock">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock</source>
|
|
||||||
<target>库存中缺少足够的零件,无法构建 %number_of_builds% 次。缺少的零件包括:</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="sp7Z0MS" name="assembly.builds.build_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.build_possible</source>
|
|
||||||
<target>可以构建</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1uZzdEl" name="assembly.builds.number_of_builds_possible">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds_possible</source>
|
|
||||||
<target><![CDATA[您的库存中有足够的零件,可以构建 <b>%max_builds%</b> 个该组件。]]></target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="pW6QLXf" name="assembly.builds.number_of_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.number_of_builds</source>
|
|
||||||
<target>构建数量</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="mtJqT_a" name="assembly.build.btn_build">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.btn_build</source>
|
|
||||||
<target>构建</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="1bCA1zb" name="assembly.build.form.referencedAssembly">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.form.referencedAssembly</source>
|
|
||||||
<target>组件“%name%”</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="LFSVVcP" name="assembly.builds.no_stocked_builds">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.no_stocked_builds</source>
|
|
||||||
<target>已构建并库存的数量</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
<unit id="dGFHutJ" name="assembly.info.bom_entries_count">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.info.bom_entries_count</source>
|
<source>assembly.info.bom_entries_count</source>
|
||||||
|
|
@ -12983,18 +12911,6 @@ Element 3</target>
|
||||||
<target>子组件</target>
|
<target>子组件</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="HZYhTlb" name="assembly.builds.stocked">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.stocked</source>
|
|
||||||
<target>库存中</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="9EG0PLW" name="assembly.builds.needed">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.needed</source>
|
|
||||||
<target>需要</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
<unit id="hO7vWmc" name="assembly.bom.delete.confirm">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom.delete.confirm</source>
|
<source>assembly.bom.delete.confirm</source>
|
||||||
|
|
@ -13043,24 +12959,6 @@ Element 3</target>
|
||||||
<target>备注</target>
|
<target>备注</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="87YpQ_u" name="assembly.builds.following_bom_entries_miss_instock_n">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.builds.following_bom_entries_miss_instock_n</source>
|
|
||||||
<target>库存不足,无法构建 %number_of_builds% 次。缺少零件包括:</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="JlQhDdS" name="assembly.build.help">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.help</source>
|
|
||||||
<target>选择部分库存零件及数量用于构建。每项零件使用复选框,如果零件已提取,也可以使用主复选框来选择所有项目。</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="iP5_QVj" name="assembly.build.required_qty">
|
|
||||||
<segment>
|
|
||||||
<source>assembly.build.required_qty</source>
|
|
||||||
<target>所需数量</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="UJpD7n6" name="assembly.import_bom">
|
<unit id="UJpD7n6" name="assembly.import_bom">
|
||||||
<segment>
|
<segment>
|
||||||
<source>assembly.import_bom</source>
|
<source>assembly.import_bom</source>
|
||||||
|
|
@ -13091,24 +12989,6 @@ Element 3</target>
|
||||||
<target>价格</target>
|
<target>价格</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="63adIrC" name="assembly.build.dont_check_quantity">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.dont_check_quantity</source>
|
|
||||||
<target>不检查数量</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="O0DP6tK" name="assembly.build.dont_check_quantity.help">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.dont_check_quantity.help</source>
|
|
||||||
<target>如果选中,即使库存不足,系统也会从库存中扣除声明的数量。</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="9bc0nzK" name="assembly.build.add_builds_to_builds_part">
|
|
||||||
<segment state="translated">
|
|
||||||
<source>assembly.build.add_builds_to_builds_part</source>
|
|
||||||
<target>将已构建的零件添加到组件</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
<unit id="nl.jtSx" name="assembly.bom_import.type">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>assembly.bom_import.type</source>
|
<source>assembly.bom_import.type</source>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue