diff --git a/VERSION b/VERSION index c8e38b61..dedcc7d4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.9.0 +2.9.1 diff --git a/src/Controller/ProjectController.php b/src/Controller/ProjectController.php index 2a6d19ee..d2c35efd 100644 --- a/src/Controller/ProjectController.php +++ b/src/Controller/ProjectController.php @@ -240,7 +240,8 @@ class ProjectController extends AbstractController } // Detect fields and get suggestions - $detected_fields = $BOMImporter->detectFields($file_content); + $detected_delimiter = $BOMImporter->detectDelimiter($file_content); + $detected_fields = $BOMImporter->detectFields($file_content, $detected_delimiter); $suggested_mapping = $BOMImporter->getSuggestedFieldMapping($detected_fields); // Create mapping of original field names to sanitized field names for template @@ -257,7 +258,7 @@ class ProjectController extends AbstractController $builder->add('delimiter', ChoiceType::class, [ 'label' => 'project.bom_import.delimiter', 'required' => true, - 'data' => ',', + 'data' => $detected_delimiter, 'choices' => [ 'project.bom_import.delimiter.comma' => ',', 'project.bom_import.delimiter.semicolon' => ';', diff --git a/src/Services/ImportExportSystem/BOMImporter.php b/src/Services/ImportExportSystem/BOMImporter.php index e6518687..7cef3f81 100644 --- a/src/Services/ImportExportSystem/BOMImporter.php +++ b/src/Services/ImportExportSystem/BOMImporter.php @@ -721,26 +721,36 @@ class BOMImporter return $mapped; } + /** + * Try to detect the separator used in the CSV data by analyzing the first line and counting occurrences of common delimiters. + * @param string $data + * @return string + */ + public function detectDelimiter(string $data): string + { + $delimiters = [',', ';', "\t"]; + $lines = explode("\n", $data, 2); + $header_line = $lines[0] ?? ''; + $delimiter_counts = []; + foreach ($delimiters as $delim) { + $delimiter_counts[$delim] = substr_count($header_line, $delim); + } + // Choose the delimiter with the highest count, default to comma if all are zero + $max_count = max($delimiter_counts); + $delimiter = array_search($max_count, $delimiter_counts, true); + if ($max_count === 0 || $delimiter === false) { + $delimiter = ','; + } + return $delimiter; + } + /** * Detect available fields in CSV data for field mapping UI */ public function detectFields(string $data, ?string $delimiter = null): array { if ($delimiter === null) { - // Detect delimiter by counting occurrences in the first row (header) - $delimiters = [',', ';', "\t"]; - $lines = explode("\n", $data, 2); - $header_line = $lines[0] ?? ''; - $delimiter_counts = []; - foreach ($delimiters as $delim) { - $delimiter_counts[$delim] = substr_count($header_line, $delim); - } - // Choose the delimiter with the highest count, default to comma if all are zero - $max_count = max($delimiter_counts); - $delimiter = array_search($max_count, $delimiter_counts, true); - if ($max_count === 0 || $delimiter === false) { - $delimiter = ','; - } + $delimiter = $this->detectDelimiter($data); } // Handle potential BOM (Byte Order Mark) at the beginning $data = preg_replace('/^\xEF\xBB\xBF/', '', $data); diff --git a/templates/parts/info/_order_infos.html.twig b/templates/parts/info/_order_infos.html.twig index 59b904df..9aa9d888 100644 --- a/templates/parts/info/_order_infos.html.twig +++ b/templates/parts/info/_order_infos.html.twig @@ -47,17 +47,17 @@ {{ detail.price | format_money(detail.currency) }} / {{ detail.PriceRelatedQuantity | format_amount(part.partUnit) }} - {% set tmp = pricedetail_helper.convertMoneyToCurrency(detail.price, detail.currency) %} + {% set tmp = pricedetail_helper.convertMoneyToCurrency(detail.price, detail.currency, app.user.currency ?? null) %} {% if detail.currency != (app.user.currency ?? null) and tmp is not null and tmp.GreaterThan(0) %} - ({{ pricedetail_helper.convertMoneyToCurrency(detail.price, detail.currency, app.user.currency ?? null) | format_money(app.user.currency ?? null) }}) + ({{ tmp | format_money(app.user.currency ?? null) }}) {% endif %} {{- helper.vat_text(detail.includesVAT) -}} {{ detail.PricePerUnit | format_money(detail.currency) }} - {% set tmp = pricedetail_helper.convertMoneyToCurrency(detail.PricePerUnit, detail.currency) %} + {% set tmp = pricedetail_helper.convertMoneyToCurrency(detail.PricePerUnit, detail.currency, app.user.currency ?? null) %} {% if detail.currency != (app.user.currency ?? null) and tmp is not null and tmp.GreaterThan(0) %} - ({{ pricedetail_helper.convertMoneyToCurrency(detail.PricePerUnit, detail.currency, app.user.currency ?? null) | format_money(app.user.currency ?? null) }}) + ({{ tmp | format_money(app.user.currency ?? null) }}) {% endif %} {{- helper.vat_text(detail.includesVAT) -}} diff --git a/templates/projects/import_bom_map_fields.html.twig b/templates/projects/import_bom_map_fields.html.twig index 4e45eb08..ee1e23ef 100644 --- a/templates/projects/import_bom_map_fields.html.twig +++ b/templates/projects/import_bom_map_fields.html.twig @@ -48,51 +48,59 @@
- - - - - - + + + + + + - {% for field in detected_fields %} - - - + + - + - - - {% endfor %} + {% endif %} + + + + {% endfor %}
{% trans %}project.bom_import.field_mapping.csv_field{% endtrans %}{% trans %}project.bom_import.field_mapping.maps_to{% endtrans %}{% trans %}project.bom_import.field_mapping.suggestion{% endtrans %}{% trans %}project.bom_import.field_mapping.priority{% endtrans %}
{% trans %}project.bom_import.field_mapping.csv_field{% endtrans %}{% trans %}project.bom_import.field_mapping.maps_to{% endtrans %}{% trans %}project.bom_import.field_mapping.suggestion{% endtrans %}{% trans %}project.bom_import.field_mapping.priority{% endtrans %}
- {{ field }} - + {% for field in detected_fields %} +
+ {{ field }} + + {# TODO: This is more a workaround than a proper fix. Ideally the controller should be fixed in a way, that we get the correct fields here #} + {% if field_name_mapping[field] is defined %} + {% set field_name = field_name_mapping[field] %} {{ form_widget(form['mapping_' ~ field_name_mapping[field]], { 'attr': { 'class': 'form-select field-mapping-select', 'data-field': field } }) }} - - {% if suggested_mapping[field] is defined %} - + {% else %} + + {% trans %}project.bom_import.field_mapping.error.check_delimiter{% endtrans %} + + {% endif %} + + {% if suggested_mapping[field] is defined %} + {{ suggested_mapping[field] }} - {% else %} - + {% else %} + {% trans %}project.bom_import.field_mapping.no_suggestion{% endtrans %} - {% endif %} - - -
+ +
diff --git a/translations/messages.de.xlf b/translations/messages.de.xlf index a2884e77..79789e21 100644 --- a/translations/messages.de.xlf +++ b/translations/messages.de.xlf @@ -12945,5 +12945,11 @@ Buerklin-API-Authentication-Server: [Part_lot] aus Barcode erstellt: Bitte überprüfen Sie, ob die Daten korrekt und gewünscht sind. + + + project.bom_import.field_mapping.error.check_delimiter + Zuordnungsfehler: Bitte prüfen Sie, ob Sie das richtige Trennzeichen ausgewählt haben! + + diff --git a/translations/messages.en.xlf b/translations/messages.en.xlf index 180d9e5e..ce92bda6 100644 --- a/translations/messages.en.xlf +++ b/translations/messages.en.xlf @@ -12947,5 +12947,11 @@ Buerklin-API Authentication server: [Part_lot] created from barcode: Please check if the data is correct and desired. + + + project.bom_import.field_mapping.error.check_delimiter + Mapping error: Check if you have selected the right delimiter! + + diff --git a/translations/validators.zh.xlf b/translations/validators.zh.xlf index 8e3e50a9..75491a97 100644 --- a/translations/validators.zh.xlf +++ b/translations/validators.zh.xlf @@ -247,5 +247,11 @@ 该类型在此语言下已存在翻译定义! + + + validator.invalid_gtin + 无效的GTIN / EAN 码。 + + - \ No newline at end of file +