From beb079b825b6bbde12b52394833c4a02d84bd470 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hmer?= Date: Sun, 15 Jun 2025 22:33:31 +0200 Subject: [PATCH 1/2] Removed env variables of already implemented info provider settings --- .env | 75 ------------------------------------------------------------ 1 file changed, 75 deletions(-) diff --git a/.env b/.env index 70f22e5d..34c1b49e 100644 --- a/.env +++ b/.env @@ -92,26 +92,6 @@ PROVIDER_DIGIKEY_LANGUAGE=en # The country to get results for PROVIDER_DIGIKEY_COUNTRY=DE -# Farnell Provider: -# You can get your API key from https://partner.element14.com/ -PROVIDER_ELEMENT14_KEY= -# Configure the store domain you want to use. This decides the language and currency of results. You can get a list of available stores from https://partner.element14.com/docs/Product_Search_API_REST__Description -PROVIDER_ELEMENT14_STORE_ID=de.farnell.com - -# TME Provider: -# You can get your API key from https://developers.tme.eu/en/ -PROVIDER_TME_KEY= -PROVIDER_TME_SECRET= -# The currency to get prices in -PROVIDER_TME_CURRENCY=EUR -# The language to get results in (en, de, pl) -PROVIDER_TME_LANGUAGE=en -# The country to get results for -PROVIDER_TME_COUNTRY=DE -# [DEPRECATED] Set this to 1 to get gross prices (including VAT) instead of net prices -# With private API keys, this option cannot be used anymore is ignored by Part-DB. The VAT inclusion depends on your TME account settings. -PROVIDER_TME_GET_GROSS_PRICES=1 - # Octopart / Nexar Provider: # You can get your API key from https://nexar.com/api PROVIDER_OCTOPART_CLIENT_ID= @@ -126,61 +106,6 @@ PROVIDER_OCTOPART_SEARCH_LIMIT=10 # Set to false to include non authorized offers in the results PROVIDER_OCTOPART_ONLY_AUTHORIZED_SELLERS=1 -# Mouser Provider API V2: -# You can get your API key from https://www.mouser.it/api-hub/ -PROVIDER_MOUSER_KEY= -# Filter search results by RoHS compliance and stock availability: -# Available options: None | Rohs | InStock | RohsAndInStock -PROVIDER_MOUSER_SEARCH_OPTION='None' -# The number of results to get from Mouser while searching (please note that this value is max 50) -PROVIDER_MOUSER_SEARCH_LIMIT=50 -# It is recommended to leave this set to 'true'. The option is not really good doumented by Mouser: -# Used when searching for keywords in the language specified when you signed up for Search API. -PROVIDER_MOUSER_SEARCH_WITH_SIGNUP_LANGUAGE='true' - -# LCSC Provider: -# LCSC does not provide an offical API, so this used the API LCSC uses to render their webshop. -# LCSC did not intended the use of this API and it could break any time, so use it at your own risk. - -# We dont require an API key for LCSC, just set this to 1 to enable LCSC support -PROVIDER_LCSC_ENABLED=0 -# The currency to get prices in (e.g. EUR, USD, etc.) -PROVIDER_LCSC_CURRENCY=EUR - -# Oemsecrets Provider API 3.0.1: -# You can get your API key from https://www.oemsecrets.com/api -PROVIDER_OEMSECRETS_KEY= -# The country you want the output for -PROVIDER_OEMSECRETS_COUNTRY_CODE=DE -# Available country code are: -# AD, AE, AQ, AR, AT, AU, BE, BO, BR, BV, BY, CA, CH, CL, CN, CO, CZ, DE, DK, EC, EE, EH, -# ES, FI, FK, FO, FR, GB, GE, GF, GG, GI, GL, GR, GS, GY, HK, HM, HR, HU, IE, IM, IN, IS, -# IT, JM, JP, KP, KR, KZ, LI, LK, LT, LU, MC, MD, ME, MK, MT, NL, NO, NZ, PE, PH, PL, PT, -# PY, RO, RS, RU, SB, SD, SE, SG, SI, SJ, SK, SM, SO, SR, SY, SZ, TC, TF, TG, TH, TJ, TK, -# TM, TN, TO, TR, TT, TV, TW, TZ, UA, UG, UM, US, UY, UZ, VA, VE, VG, VI, VN, VU, WF, YE, -# ZA, ZM, ZW -# -# The currency you want the prices to be displayed in -PROVIDER_OEMSECRETS_CURRENCY=EUR -# Available currency are:AUD, CAD, CHF, CNY, DKK, EUR, GBP, HKD, ILS, INR, JPY, KRW, NOK, -# NZD, RUB, SEK, SGD, TWD, USD -# -# If PROVIDER_OEMSECRETS_ZERO_PRICE is set to 0, distributors with zero prices -# will be discarded from the creation of a new part (set to 1 otherwise) -PROVIDER_OEMSECRETS_ZERO_PRICE=0 -# -# When PROVIDER_OEMSECRETS_SET_PARAM is set to 1 the parameters for the part are generated -# from the description transforming unstructured descriptions into structured parameters; -# each parameter in description should have the form: "...;name1:value1;name2:value2" -PROVIDER_OEMSECRETS_SET_PARAM=1 -# -# This environment variable determines the sorting criteria for product results. -# The sorting process first arranges items based on the provided keyword. -# Then, if set to 'C', it further sorts by completeness (prioritizing items with the most -# detailed information). If set to 'M', it further sorts by manufacturer name. -#If unset or set to any other value, no sorting is performed. -PROVIDER_OEMSECRETS_SORT_CRITERIA=C - # Reichelt provider: # Reichelt.com offers no official API, so this info provider webscrapes the website to extract info From b2946aee0d444391b8e3ea45cc7facee08894809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hmer?= Date: Sun, 22 Jun 2025 20:08:27 +0200 Subject: [PATCH 2/2] Moved pollin and reichelt info provider settings to new settings system --- .env | 31 ------ .../Providers/PollinProvider.php | 6 +- .../Providers/ReicheltProvider.php | 28 ++---- .../InfoProviderSettings.php | 6 ++ .../InfoProviderSystem/PollinSettings.php | 37 +++++++ .../InfoProviderSystem/ReicheltSettings.php | 62 ++++++++++++ .../InfoProviderSystem/TMESettings.php | 2 +- translations/messages.en.xlf | 96 ++++++++++++------- 8 files changed, 182 insertions(+), 86 deletions(-) create mode 100644 src/Settings/InfoProviderSystem/PollinSettings.php create mode 100644 src/Settings/InfoProviderSystem/ReicheltSettings.php diff --git a/.env b/.env index 34c1b49e..19870ae9 100644 --- a/.env +++ b/.env @@ -67,16 +67,6 @@ ERROR_PAGE_ADMIN_EMAIL='' # If this is set to true, solutions to common problems are shown on error pages. Disable this, if you do not want your users to see them... ERROR_PAGE_SHOW_HELP=1 -################################################################################## -# Part table settings -################################################################################## - -# The default page size for the part table (set to -1 to show all parts on one page) -#TABLE_DEFAULT_PAGE_SIZE=50 -# Configure which columns will be visible by default in the parts table (and in which order). -# This is a comma separated list of column names. See documentation for available values. -#TABLE_PARTS_DEFAULT_COLUMNS=name,description,category,footprint,manufacturer,storage_location,amount - ################################################################################## # Info provider settings ################################################################################## @@ -106,27 +96,6 @@ PROVIDER_OCTOPART_SEARCH_LIMIT=10 # Set to false to include non authorized offers in the results PROVIDER_OCTOPART_ONLY_AUTHORIZED_SELLERS=1 - -# Reichelt provider: -# Reichelt.com offers no official API, so this info provider webscrapes the website to extract info -# It could break at any time, use it at your own risk -# We dont require an API key for Reichelt, just set this to 1 to enable Reichelt support -PROVIDER_REICHELT_ENABLED=0 -# The country to get prices for -PROVIDER_REICHELT_COUNTRY=DE -# The language to get results in (en, de, fr, nl, pl, it, es) -PROVIDER_REICHELT_LANGUAGE=en -# Include VAT in prices (set to 1 to include VAT, 0 to exclude VAT) -PROVIDER_REICHELT_INCLUDE_VAT=1 -# The currency to get prices in (only for countries with countries other than EUR) -PROVIDER_REICHELT_CURRENCY=EUR - -# Pollin provider: -# Pollin.de offers no official API, so this info provider webscrapes the website to extract info -# It could break at any time, use it at your own risk -# We dont require an API key for Pollin, just set this to 1 to enable Pollin support -PROVIDER_POLLIN_ENABLED=0 - ################################################################################## # EDA integration related settings ################################################################################## diff --git a/src/Services/InfoProviderSystem/Providers/PollinProvider.php b/src/Services/InfoProviderSystem/Providers/PollinProvider.php index 09ab8fd4..864effd9 100644 --- a/src/Services/InfoProviderSystem/Providers/PollinProvider.php +++ b/src/Services/InfoProviderSystem/Providers/PollinProvider.php @@ -31,6 +31,7 @@ use App\Services\InfoProviderSystem\DTOs\PartDetailDTO; use App\Services\InfoProviderSystem\DTOs\PriceDTO; use App\Services\InfoProviderSystem\DTOs\PurchaseInfoDTO; use App\Services\InfoProviderSystem\DTOs\SearchResultDTO; +use App\Settings\InfoProviderSystem\PollinSettings; use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\DomCrawler\Crawler; use Symfony\Contracts\HttpClient\HttpClientInterface; @@ -39,8 +40,7 @@ class PollinProvider implements InfoProviderInterface { public function __construct(private readonly HttpClientInterface $client, - #[Autowire(env: 'bool:PROVIDER_POLLIN_ENABLED')] - private readonly bool $enabled = true, + private readonly PollinSettings $settings, ) { } @@ -62,7 +62,7 @@ class PollinProvider implements InfoProviderInterface public function isActive(): bool { - return $this->enabled; + return $this->settings->enabled; } public function searchByKeyword(string $keyword): array diff --git a/src/Services/InfoProviderSystem/Providers/ReicheltProvider.php b/src/Services/InfoProviderSystem/Providers/ReicheltProvider.php index 0c31c411..ebc62dd5 100644 --- a/src/Services/InfoProviderSystem/Providers/ReicheltProvider.php +++ b/src/Services/InfoProviderSystem/Providers/ReicheltProvider.php @@ -29,6 +29,7 @@ use App\Services\InfoProviderSystem\DTOs\PartDetailDTO; use App\Services\InfoProviderSystem\DTOs\PriceDTO; use App\Services\InfoProviderSystem\DTOs\PurchaseInfoDTO; use App\Services\InfoProviderSystem\DTOs\SearchResultDTO; +use App\Settings\InfoProviderSystem\ReicheltSettings; use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\DomCrawler\Crawler; use Symfony\Contracts\HttpClient\HttpClientInterface; @@ -39,16 +40,7 @@ class ReicheltProvider implements InfoProviderInterface public const DISTRIBUTOR_NAME = "Reichelt"; public function __construct(private readonly HttpClientInterface $client, - #[Autowire(env: "bool:PROVIDER_REICHELT_ENABLED")] - private readonly bool $enabled = true, - #[Autowire(env: "PROVIDER_REICHELT_LANGUAGE")] - private readonly string $language = "en", - #[Autowire(env: "PROVIDER_REICHELT_COUNTRY")] - private readonly string $country = "DE", - #[Autowire(env: "PROVIDER_REICHELT_INCLUDE_VAT")] - private readonly bool $includeVAT = false, - #[Autowire(env: "PROVIDER_REICHELT_CURRENCY")] - private readonly string $currency = "EUR", + private readonly ReicheltSettings $settings, ) { } @@ -70,7 +62,7 @@ class ReicheltProvider implements InfoProviderInterface public function isActive(): bool { - return $this->enabled; + return $this->settings->enabled; } public function searchByKeyword(string $keyword): array @@ -121,8 +113,8 @@ class ReicheltProvider implements InfoProviderInterface sprintf( 'https://www.reichelt.com/?ACTION=514&id=74&article=%s&LANGUAGE=%s&CCOUNTRY=%s', $id, - strtoupper($this->language), - strtoupper($this->country) + strtoupper($this->settings->language), + strtoupper($this->settings->country) ) ); $json = $response->toArray(); @@ -133,8 +125,8 @@ class ReicheltProvider implements InfoProviderInterface $response = $this->client->request('GET', $productPage, [ 'query' => [ - 'CCTYPE' => $this->includeVAT ? 'private' : 'business', - 'currency' => $this->currency, + 'CCTYPE' => $this->settings->includeVAT ? 'private' : 'business', + 'currency' => $this->settings->currency, ], ]); $html = $response->getContent(); @@ -158,7 +150,7 @@ class ReicheltProvider implements InfoProviderInterface distributor_name: self::DISTRIBUTOR_NAME, order_number: $json[0]['article_artnr'], prices: array_merge( - [new PriceDTO(1.0, $priceString, $currency, $this->includeVAT)] + [new PriceDTO(1.0, $priceString, $currency, $this->settings->includeVAT)] , $this->parseBatchPrices($dom, $currency)), product_url: $productPage ); @@ -218,7 +210,7 @@ class ReicheltProvider implements InfoProviderInterface //Strip any non-numeric characters $priceString = preg_replace('/[^0-9.]/', '', $priceString); - $prices[] = new PriceDTO($minAmount, $priceString, $currency, $this->includeVAT); + $prices[] = new PriceDTO($minAmount, $priceString, $currency, $this->settings->includeVAT); }); return $prices; @@ -270,7 +262,7 @@ class ReicheltProvider implements InfoProviderInterface private function getBaseURL(): string { //Without the trailing slash - return 'https://www.reichelt.com/' . strtolower($this->country) . '/' . strtolower($this->language); + return 'https://www.reichelt.com/' . strtolower($this->settings->country) . '/' . strtolower($this->settings->language); } public function getCapabilities(): array diff --git a/src/Settings/InfoProviderSystem/InfoProviderSettings.php b/src/Settings/InfoProviderSystem/InfoProviderSettings.php index d087facc..109fbc02 100644 --- a/src/Settings/InfoProviderSystem/InfoProviderSettings.php +++ b/src/Settings/InfoProviderSystem/InfoProviderSettings.php @@ -46,4 +46,10 @@ class InfoProviderSettings #[EmbeddedSettings] public ?OEMSecretsSettings $oemsecrets = null; + + #[EmbeddedSettings] + public ?ReicheltSettings $reichelt = null; + + #[EmbeddedSettings] + public ?PollinSettings $pollin = null; } \ No newline at end of file diff --git a/src/Settings/InfoProviderSystem/PollinSettings.php b/src/Settings/InfoProviderSystem/PollinSettings.php new file mode 100644 index 00000000..8a7713c6 --- /dev/null +++ b/src/Settings/InfoProviderSystem/PollinSettings.php @@ -0,0 +1,37 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Settings\InfoProviderSystem; + +use App\Settings\SettingsIcon; +use Jbtronics\SettingsBundle\Settings\Settings; +use Jbtronics\SettingsBundle\Settings\SettingsParameter; +use Symfony\Component\Translation\TranslatableMessage as TM; + +#[Settings(label: new TM("settings.ips.pollin"), description: new TM("settings.ips.pollin.help"))] +#[SettingsIcon("fa-plug")] +class PollinSettings +{ + #[SettingsParameter(label: new TM("settings.ips.lcsc.enabled"), envVar: "bool:PROVIDER_POLLIN_ENABLED")] + public bool $enabled = false; +} \ No newline at end of file diff --git a/src/Settings/InfoProviderSystem/ReicheltSettings.php b/src/Settings/InfoProviderSystem/ReicheltSettings.php new file mode 100644 index 00000000..8672ae69 --- /dev/null +++ b/src/Settings/InfoProviderSystem/ReicheltSettings.php @@ -0,0 +1,62 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Settings\InfoProviderSystem; + +use App\Settings\SettingsIcon; +use Jbtronics\SettingsBundle\Settings\Settings; +use Jbtronics\SettingsBundle\Settings\SettingsParameter; +use Jbtronics\SettingsBundle\Settings\SettingsTrait; +use Symfony\Component\Form\Extension\Core\Type\CountryType; +use Symfony\Component\Form\Extension\Core\Type\CurrencyType; +use Symfony\Component\Form\Extension\Core\Type\LanguageType; +use Symfony\Component\Translation\TranslatableMessage as TM; +use Symfony\Component\Validator\Constraints as Assert; + +#[Settings(label: new TM("settings.ips.reichelt"), description: new TM("settings.ips.reichelt.help"))] +#[SettingsIcon("fa-plug")] +class ReicheltSettings +{ + use SettingsTrait; + + public const SUPPORTED_LANGUAGE = ["en", "de", "fr", "nl", "pl", "it", "es"]; + + #[SettingsParameter(label: new TM("settings.ips.lcsc.enabled"), envVar: "bool:PROVIDER_REICHELT_ENABLED")] + public bool $enabled = false; + + #[SettingsParameter(label: new TM("settings.ips.tme.currency"), formType: CurrencyType::class, formOptions: ["preferred_choices" => ["EUR"]], envVar: "PROVIDER_REICHELT_CURRENCY")] + public string $currency = "EUR"; + + #[SettingsParameter(label: new TM("settings.ips.tme.language"), formType: LanguageType::class, formOptions: ["preferred_choices" => self::SUPPORTED_LANGUAGE], envVar: "PROVIDER_REICHELT_LANGUAGE")] + #[Assert\Language()] + #[Assert\Choice(choices: self::SUPPORTED_LANGUAGE)] + public string $language = "en"; + + #[SettingsParameter(label: new TM("settings.ips.tme.country"), envVar: "PROVIDER_REICHELT_COUNTRY", formType: CountryType::class, formOptions: ["preferred_choices" => ["DE", "PL", "GB", "FR"]])] + #[Assert\Country] + public string $country = "DE"; + + #[SettingsParameter(label: new TM("settings.ips.reichelt.include_vat"), envVar: "bool:PROVIDER_REICHELT_INCLUDE_VAT")] + public bool $includeVAT = true; + +} \ No newline at end of file diff --git a/src/Settings/InfoProviderSystem/TMESettings.php b/src/Settings/InfoProviderSystem/TMESettings.php index d44e3325..f414e984 100644 --- a/src/Settings/InfoProviderSystem/TMESettings.php +++ b/src/Settings/InfoProviderSystem/TMESettings.php @@ -56,7 +56,7 @@ class TMESettings #[Assert\Language] public string $language = "en"; - #[SettingsParameter(label: new TM("settings.ips.tme.country"), envVar: "PROVIDER_TME_COUNTRY", formType: CountryType::class, formOptions: ["preferred_choices" => ["DE", "PL", "GB", "FR"]])] + #[SettingsParameter(label: new TM("settings.ips.tme.country"), formType: CountryType::class, formOptions: ["preferred_choices" => ["DE", "PL", "GB", "FR"]], envVar: "PROVIDER_TME_COUNTRY")] #[Assert\Country] public string $country = "DE"; diff --git a/translations/messages.en.xlf b/translations/messages.en.xlf index 0a6c97b0..3ca784cd 100644 --- a/translations/messages.en.xlf +++ b/translations/messages.en.xlf @@ -242,7 +242,7 @@ part.info.timetravel_hint - This is how the part appeared before %timestamp%. <i>Please note that this feature is experimental, so the info may not be correct.</i> + Please note that this feature is experimental, so the info may not be correct.]]> @@ -731,10 +731,10 @@ user.edit.tfa.disable_tfa_message - This will disable <b>all active two-factor authentication methods of the user</b> and delete the <b>backup codes</b>! -<br> -The user will have to set up all two-factor authentication methods again and print new backup codes! <br><br> -<b>Only do this if you are absolutely sure about the identity of the user (seeking help), otherwise the account could be compromised by an attacker!</b> + all active two-factor authentication methods of the user and delete the backup codes! +
+The user will have to set up all two-factor authentication methods again and print new backup codes!

+Only do this if you are absolutely sure about the identity of the user (seeking help), otherwise the account could be compromised by an attacker!]]>
@@ -885,9 +885,9 @@ The user will have to set up all two-factor authentication methods again and pri entity.delete.message - This can not be undone! -<br> -Sub elements will be moved upwards. + +Sub elements will be moved upwards.]]> @@ -1441,7 +1441,7 @@ Sub elements will be moved upwards. homepage.github.text - Source, downloads, bug reports, to-do-list etc. can be found on <a href="%href%" class="link-external" target="_blank">GitHub project page</a> + GitHub project page]]> @@ -1463,7 +1463,7 @@ Sub elements will be moved upwards. homepage.help.text - Help and tips can be found in Wiki the <a href="%href%" class="link-external" target="_blank">GitHub page</a> + GitHub page]]> @@ -1705,7 +1705,7 @@ Sub elements will be moved upwards. email.pw_reset.fallback - If this does not work for you, go to <a href="%url%">%url%</a> and enter the following info + %url% and enter the following info]]> @@ -1735,7 +1735,7 @@ Sub elements will be moved upwards. email.pw_reset.valid_unit %date% - The reset token will be valid until <i>%date%</i>. + %date%.]]> @@ -3578,8 +3578,8 @@ Sub elements will be moved upwards. tfa_google.disable.confirm_message - If you disable the Authenticator App, all backup codes will be deleted, so you may need to reprint them.<br> -Also note that without two-factor authentication, your account is no longer as well protected against attackers! + +Also note that without two-factor authentication, your account is no longer as well protected against attackers!]]> @@ -3599,7 +3599,7 @@ Also note that without two-factor authentication, your account is no longer as w tfa_google.step.download - Download an authenticator app (e.g. <a class="link-external" target="_blank" href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2">Google Authenticator</a> oder <a class="link-external" target="_blank" href="https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp">FreeOTP Authenticator</a>) + Google Authenticator oder FreeOTP Authenticator)]]> @@ -3841,8 +3841,8 @@ Also note that without two-factor authentication, your account is no longer as w tfa_trustedDevices.explanation - When checking the second factor, the current computer can be marked as trustworthy, so no more two-factor checks on this computer are needed. -If you have done this incorrectly or if a computer is no longer trusted, you can reset the status of <i>all </i>computers here. + all computers here.]]> @@ -5313,7 +5313,7 @@ If you have done this incorrectly or if a computer is no longer trusted, you can label_options.lines_mode.help - If you select Twig here, the content field is interpreted as Twig template. See <a href="https://twig.symfony.com/doc/3.x/templates.html">Twig documentation</a> and <a href="https://docs.part-db.de/usage/labels.html#twig-mode">Wiki</a> for more information. + Twig documentation and Wiki for more information.]]> @@ -9388,25 +9388,25 @@ Element 3 filter.parameter_value_constraint.operator.< - Typ. Value < + filter.parameter_value_constraint.operator.> - Typ. Value > + ]]> filter.parameter_value_constraint.operator.<= - Typ. Value <= + filter.parameter_value_constraint.operator.>= - Typ. Value >= + =]]> @@ -9514,7 +9514,7 @@ Element 3 parts_list.search.searching_for - Searching parts with keyword <b>%keyword%</b> + %keyword%]]> @@ -10174,13 +10174,13 @@ Element 3 project.builds.number_of_builds_possible - You have enough stocked to build <b>%max_builds%</b> builds of this project. + %max_builds% builds of this project.]]> project.builds.check_project_status - The current project status is <b>"%project_status%"</b>. You should check if you really want to build the project with this status! + "%project_status%". You should check if you really want to build the project with this status!]]> @@ -10282,7 +10282,7 @@ Element 3 entity.select.add_hint - Use -> to create nested structures, e.g. "Node 1->Node 1.1" + to create nested structures, e.g. "Node 1->Node 1.1"]]> @@ -10306,13 +10306,13 @@ Element 3 homepage.first_steps.introduction - Your database is still empty. You might want to read the <a href="%url%">documentation</a> or start to creating the following data structures: + documentation or start to creating the following data structures:]]> homepage.first_steps.create_part - Or you can directly <a href="%url%">create a new part</a>. + create a new part.]]> @@ -10324,7 +10324,7 @@ Element 3 homepage.forum.text - For questions about Part-DB use the <a href="%href%" class="link-external" target="_blank">discussion forum</a> + discussion forum]]> @@ -10978,7 +10978,7 @@ Element 3 parts.import.help_documentation - See the <a href="%link%">documentation</a> for more information on the file format. + documentation for more information on the file format.]]> @@ -11158,7 +11158,7 @@ Element 3 part.filter.lessThanDesired - In stock less than desired (total amount < min. amount) + @@ -11970,13 +11970,13 @@ Please note, that you can not impersonate a disabled user. If you try you will g part.merge.confirm.title - Do you really want to merge <b>%other%</b> into <b>%target%</b>? + %other% into %target%?]]> part.merge.confirm.message - <b>%other%</b> will be deleted, and the part will be saved with the shown information. + %other% will be deleted, and the part will be saved with the shown information.]]> @@ -12892,5 +12892,35 @@ Please note, that you can not impersonate a disabled user. If you try you will g This part contains more than one stock. Change the location by hand to select, which stock to choose. + + + settings.ips.reichelt + Reichelt + + + + + settings.ips.reichelt.help + Reichelt.com offers no official API, so this info provider webscrapes the website to extract info. It could break at any time, use it at your own risk. + + + + + settings.ips.reichelt.include_vat + Include VAT in prices + + + + + settings.ips.pollin + Pollin + + + + + settings.ips.pollin.help + Pollin.de offers no official API, so this info provider webscrapes the website to extract info. It could break at any time, use it at your own risk. + +