mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2026-04-22 22:39:37 +00:00
Compare commits
No commits in common. "df3f069a769ee42224429b04a44c9c0daab9dd88" and "3ed62f5cee80ca4dbfa935b27caff50b9af0af1e" have entirely different histories.
df3f069a76
...
3ed62f5cee
5 changed files with 44 additions and 261 deletions
|
|
@ -278,16 +278,6 @@ The following env configuration options are available:
|
||||||
* `PROVIDER_BUERKLIN_CURRENCY`: The currency you want to get prices in if available (optional, 3 letter ISO-code, default: `EUR`).
|
* `PROVIDER_BUERKLIN_CURRENCY`: The currency you want to get prices in if available (optional, 3 letter ISO-code, default: `EUR`).
|
||||||
* `PROVIDER_BUERKLIN_LANGUAGE`: The language you want to get the descriptions in. Possible values: `de` = German, `en` = English. (optional, default: `en`)
|
* `PROVIDER_BUERKLIN_LANGUAGE`: The language you want to get the descriptions in. Possible values: `de` = German, `en` = English. (optional, default: `en`)
|
||||||
|
|
||||||
### Conrad
|
|
||||||
|
|
||||||
The conrad provider the [Conrad API](https://developer.conrad.com/) to search for parts and retried their information.
|
|
||||||
To use it you have to request access to the API, however it seems currently your mail address needs to be allowlisted before you can register for an account.
|
|
||||||
The conrad webpages uses the API key in the requests, so you might be able to extract a working API key by listening to browser requests.
|
|
||||||
That method is not officially supported nor encouraged by Part-DB, and might break at any moment.
|
|
||||||
|
|
||||||
The following env configuration options are available:
|
|
||||||
* `PROVIDER_CONRAD_API_KEY`: The API key you got from Conrad (mandatory)
|
|
||||||
|
|
||||||
### Custom provider
|
### Custom provider
|
||||||
|
|
||||||
To create a custom provider, you have to create a new class implementing the `InfoProviderInterface` interface. As long
|
To create a custom provider, you have to create a new class implementing the `InfoProviderInterface` interface. As long
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,8 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Services\InfoProviderSystem\Providers;
|
namespace App\Services\InfoProviderSystem\Providers;
|
||||||
|
|
||||||
use App\Services\InfoProviderSystem\DTOs\FileDTO;
|
|
||||||
use App\Services\InfoProviderSystem\DTOs\ParameterDTO;
|
use App\Services\InfoProviderSystem\DTOs\ParameterDTO;
|
||||||
use App\Services\InfoProviderSystem\DTOs\PartDetailDTO;
|
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\Services\InfoProviderSystem\DTOs\SearchResultDTO;
|
||||||
use App\Settings\InfoProviderSystem\ConradSettings;
|
use App\Settings\InfoProviderSystem\ConradSettings;
|
||||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||||
|
|
@ -36,18 +33,9 @@ readonly class ConradProvider implements InfoProviderInterface
|
||||||
{
|
{
|
||||||
|
|
||||||
private const SEARCH_ENDPOINT = '/search/1/v3/facetSearch';
|
private const SEARCH_ENDPOINT = '/search/1/v3/facetSearch';
|
||||||
public const DISTRIBUTOR_NAME = 'Conrad';
|
|
||||||
|
|
||||||
private HttpClientInterface $httpClient;
|
public function __construct(private HttpClientInterface $httpClient, private ConradSettings $settings)
|
||||||
|
|
||||||
public function __construct( HttpClientInterface $httpClient, private ConradSettings $settings)
|
|
||||||
{
|
{
|
||||||
//We want everything in JSON
|
|
||||||
$this->httpClient = $httpClient->withOptions([
|
|
||||||
'headers' => [
|
|
||||||
'Accept' => 'application/json',
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getProviderInfo(): array
|
public function getProviderInfo(): array
|
||||||
|
|
@ -87,6 +75,31 @@ readonly class ConradProvider implements InfoProviderInterface
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getFootprintFromTechnicalAttributes(array $technicalDetails): ?string
|
||||||
|
{
|
||||||
|
foreach ($technicalDetails as $detail) {
|
||||||
|
if ($detail['attributeID'] === 'ATT.LOV.HOUSING_SEMICONDUCTORS') {
|
||||||
|
return $detail['values'][0]['value'] ?? null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function technicalAttributesToParameters(array $technicalAttributes): array
|
||||||
|
{
|
||||||
|
$parameters = [];
|
||||||
|
foreach ($technicalAttributes as $attribute) {
|
||||||
|
if ($attribute['multiValue'] ?? false === true) {
|
||||||
|
throw new \LogicException('Multi value attributes are not supported yet');
|
||||||
|
}
|
||||||
|
$parameters[] = ParameterDTO::parseValueField($attribute['attributeName'],
|
||||||
|
$attribute['values'][0]['value'], $attribute['values'][0]['unit']['name'] ?? null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $parameters;
|
||||||
|
}
|
||||||
|
|
||||||
public function searchByKeyword(string $keyword): array
|
public function searchByKeyword(string $keyword): array
|
||||||
{
|
{
|
||||||
$url = $this->settings->shopID->getAPIRoot() . self::SEARCH_ENDPOINT . '/'
|
$url = $this->settings->shopID->getAPIRoot() . self::SEARCH_ENDPOINT . '/'
|
||||||
|
|
@ -99,8 +112,7 @@ readonly class ConradProvider implements InfoProviderInterface
|
||||||
],
|
],
|
||||||
'json' => [
|
'json' => [
|
||||||
'query' => $keyword,
|
'query' => $keyword,
|
||||||
'size' => 50,
|
'size' => 25,
|
||||||
'sort' => [["field"=>"_score","order"=>"desc"]],
|
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
@ -112,8 +124,8 @@ readonly class ConradProvider implements InfoProviderInterface
|
||||||
$out[] = new SearchResultDTO(
|
$out[] = new SearchResultDTO(
|
||||||
provider_key: $this->getProviderKey(),
|
provider_key: $this->getProviderKey(),
|
||||||
provider_id: $result['productId'],
|
provider_id: $result['productId'],
|
||||||
name: $result['manufacturerId'] ?? $result['productId'],
|
name: $result['title'],
|
||||||
description: $result['title'] ?? '',
|
description: '',
|
||||||
manufacturer: $result['brand']['name'] ?? null,
|
manufacturer: $result['brand']['name'] ?? null,
|
||||||
mpn: $result['manufacturerId'] ?? null,
|
mpn: $result['manufacturerId'] ?? null,
|
||||||
preview_image_url: $result['image'] ?? null,
|
preview_image_url: $result['image'] ?? null,
|
||||||
|
|
@ -125,158 +137,6 @@ readonly class ConradProvider implements InfoProviderInterface
|
||||||
return $out;
|
return $out;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getFootprintFromTechnicalAttributes(array $technicalDetails): ?string
|
|
||||||
{
|
|
||||||
foreach ($technicalDetails as $detail) {
|
|
||||||
if ($detail['attributeID'] === 'ATT.LOV.HOUSING_SEMICONDUCTORS') {
|
|
||||||
return $detail['values'][0]['value'] ?? null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $technicalAttributes
|
|
||||||
* @return array<ParameterDTO>
|
|
||||||
*/
|
|
||||||
private function technicalAttributesToParameters(array $technicalAttributes): array
|
|
||||||
{
|
|
||||||
return array_map(static function (array $p) {
|
|
||||||
if (count($p['values']) === 1) { //Single value attribute
|
|
||||||
if (array_key_exists('unit', $p['values'][0])) {
|
|
||||||
return ParameterDTO::parseValueField( //With unit
|
|
||||||
name: $p['attributeName'],
|
|
||||||
value: $p['values'][0]['value'],
|
|
||||||
unit: $p['values'][0]['unit']['name'],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ParameterDTO::parseValueIncludingUnit(
|
|
||||||
name: $p['attributeName'],
|
|
||||||
value: $p['values'][0]['value'],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count($p['values']) === 2) { //Multi value attribute (e.g. min/max)
|
|
||||||
$value = $p['values'][0]['value'] ?? null;
|
|
||||||
$value2 = $p['values'][1]['value'] ?? null;
|
|
||||||
$unit = $p['values'][0]['unit']['name'] ?? '';
|
|
||||||
$unit2 = $p['values'][1]['unit']['name'] ?? '';
|
|
||||||
if ($unit === $unit2 && is_numeric($value) && is_numeric($value2)) {
|
|
||||||
if (array_key_exists('unit', $p['values'][0])) { //With unit
|
|
||||||
return new ParameterDTO(
|
|
||||||
name: $p['attributeName'],
|
|
||||||
value_min: (float)$value,
|
|
||||||
value_max: (float)$value2,
|
|
||||||
unit: $unit,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ParameterDTO(
|
|
||||||
name: $p['attributeName'],
|
|
||||||
value_min: (float)$value,
|
|
||||||
value_max: (float)$value2,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fallback implementation
|
|
||||||
$values = implode(", ", array_map(fn($q) =>
|
|
||||||
array_key_exists('unit', $q) ? $q['value']." ". ($q['unit']['name'] ?? $q['unit']) : $q['value']
|
|
||||||
, $p['values']));
|
|
||||||
return ParameterDTO::parseValueIncludingUnit(
|
|
||||||
name: $p['attributeName'],
|
|
||||||
value: $values,
|
|
||||||
);
|
|
||||||
}, $technicalAttributes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $productMedia
|
|
||||||
* @return array<FileDTO>
|
|
||||||
*/
|
|
||||||
public function productMediaToDatasheets(array $productMedia): array
|
|
||||||
{
|
|
||||||
$files = [];
|
|
||||||
foreach ($productMedia['manuals'] as $manual) {
|
|
||||||
//Filter out unwanted languages
|
|
||||||
if (!empty($this->settings->attachmentLanguageFilter) && !in_array($manual['language'], $this->settings->attachmentLanguageFilter, true)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$files[] = new FileDTO($manual['fullUrl'], $manual['title'] . ' (' . $manual['language'] . ')');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $files;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Queries prices for a given product ID. It makes a POST request to the Conrad API
|
|
||||||
* @param string $productId
|
|
||||||
* @return PurchaseInfoDTO
|
|
||||||
*/
|
|
||||||
private function queryPrices(string $productId): PurchaseInfoDTO
|
|
||||||
{
|
|
||||||
$priceQueryURL = $this->settings->shopID->getAPIRoot() . '/price-availability/4/'
|
|
||||||
. $this->settings->shopID->getShopID() . '/facade';
|
|
||||||
|
|
||||||
$response = $this->httpClient->request('POST', $priceQueryURL, [
|
|
||||||
'query' => [
|
|
||||||
'apikey' => $this->settings->apiKey,
|
|
||||||
'overrideCalculationSchema' => $this->settings->includeVAT ? 'GROSS' : 'NET'
|
|
||||||
],
|
|
||||||
'json' => [
|
|
||||||
'ns:inputArticleItemList' => [
|
|
||||||
"#namespaces" => [
|
|
||||||
"ns" => "http://www.conrad.de/ccp/basit/service/article/priceandavailabilityservice/api"
|
|
||||||
],
|
|
||||||
'articles' => [
|
|
||||||
[
|
|
||||||
"articleID" => $productId,
|
|
||||||
"calculatePrice" => true,
|
|
||||||
"checkAvailability" => true,
|
|
||||||
],
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
|
|
||||||
$result = $response->toArray();
|
|
||||||
|
|
||||||
$priceInfo = $result['priceAndAvailabilityFacadeResponse']['priceAndAvailability']['price'] ?? [];
|
|
||||||
$price = $priceInfo['price'] ?? "0.0";
|
|
||||||
$currency = $priceInfo['currency'] ?? "EUR";
|
|
||||||
$includesVat = $priceInfo['isGrossAmount'] === "true" ?? true;
|
|
||||||
$minOrderAmount = $result['priceAndAvailabilityFacadeResponse']['priceAndAvailability']['availabilityStatus']['minimumOrderQuantity'] ?? 1;
|
|
||||||
|
|
||||||
$prices = [];
|
|
||||||
foreach ($priceInfo['priceScale'] ?? [] as $priceScale) {
|
|
||||||
$prices[] = new PriceDTO(
|
|
||||||
minimum_discount_amount: max($priceScale['scaleFrom'], $minOrderAmount),
|
|
||||||
price: (string)$priceScale['pricePerUnit'],
|
|
||||||
currency_iso_code: $currency,
|
|
||||||
includes_tax: $includesVat
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (empty($prices)) { //Fallback if no price scales are defined
|
|
||||||
$prices[] = new PriceDTO(
|
|
||||||
minimum_discount_amount: $minOrderAmount,
|
|
||||||
price: (string)$price,
|
|
||||||
currency_iso_code: $currency,
|
|
||||||
includes_tax: $includesVat
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new PurchaseInfoDTO(
|
|
||||||
distributor_name: self::DISTRIBUTOR_NAME,
|
|
||||||
order_number: $productId,
|
|
||||||
prices: $prices,
|
|
||||||
product_url: $this->getProductUrl($productId)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDetails(string $id): PartDetailDTO
|
public function getDetails(string $id): PartDetailDTO
|
||||||
{
|
{
|
||||||
$productInfoURL = $this->settings->shopID->getAPIRoot() . '/product/1/service/' . $this->settings->shopID->getShopID()
|
$productInfoURL = $this->settings->shopID->getAPIRoot() . '/product/1/service/' . $this->settings->shopID->getShopID()
|
||||||
|
|
@ -293,28 +153,22 @@ readonly class ConradProvider implements InfoProviderInterface
|
||||||
return new PartDetailDTO(
|
return new PartDetailDTO(
|
||||||
provider_key: $this->getProviderKey(),
|
provider_key: $this->getProviderKey(),
|
||||||
provider_id: $data['shortProductNumber'],
|
provider_id: $data['shortProductNumber'],
|
||||||
name: $data['productFullInformation']['manufacturer']['name'] ?? $data['productFullInformation']['manufacturer']['id'] ?? $data['shortProductNumber'],
|
name: $data['productShortInformation']['title'],
|
||||||
description: $data['productShortInformation']['title'] ?? '',
|
description: $data['productShortInformation']['shortDescription'] ?? '',
|
||||||
category: $data['productShortInformation']['articleGroupName'] ?? null,
|
manufacturer: $data['brand']['displayName'] ?? null,
|
||||||
manufacturer: $data['brand']['displayName'] !== null ? preg_replace("/[\u{2122}\u{00ae}]/", "", $data['brand']['displayName']) : null, //Replace ™ and ® symbols
|
|
||||||
mpn: $data['productFullInformation']['manufacturer']['id'] ?? null,
|
mpn: $data['productFullInformation']['manufacturer']['id'] ?? null,
|
||||||
preview_image_url: $data['productShortInformation']['mainImage']['imageUrl'] ?? null,
|
preview_image_url: $data['productShortInformation']['mainImage']['imageUrl'] ?? null,
|
||||||
provider_url: $this->getProductUrl($data['shortProductNumber']),
|
provider_url: $this->getProductUrl($data['shortProductNumber']),
|
||||||
footprint: $this->getFootprintFromTechnicalAttributes($data['productFullInformation']['technicalAttributes'] ?? []),
|
footprint: $this->getFootprintFromTechnicalAttributes($data['productFullInformation']['technicalAttributes'] ?? []),
|
||||||
notes: $data['productFullInformation']['description'] ?? null,
|
notes: $data['productFullInformation']['description'] ?? null,
|
||||||
datasheets: $this->productMediaToDatasheets($data['productMedia'] ?? []),
|
|
||||||
parameters: $this->technicalAttributesToParameters($data['productFullInformation']['technicalAttributes'] ?? []),
|
parameters: $this->technicalAttributesToParameters($data['productFullInformation']['technicalAttributes'] ?? []),
|
||||||
vendor_infos: [$this->queryPrices($data['shortProductNumber'])]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCapabilities(): array
|
public function getCapabilities(): array
|
||||||
{
|
{
|
||||||
return [
|
return [ProviderCapabilities::BASIC,
|
||||||
ProviderCapabilities::BASIC,
|
|
||||||
ProviderCapabilities::PICTURE,
|
ProviderCapabilities::PICTURE,
|
||||||
ProviderCapabilities::DATASHEET,
|
ProviderCapabilities::PRICE,];
|
||||||
ProviderCapabilities::PRICE,
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,6 @@ namespace App\Settings\InfoProviderSystem;
|
||||||
use App\Form\Type\APIKeyType;
|
use App\Form\Type\APIKeyType;
|
||||||
use App\Settings\SettingsIcon;
|
use App\Settings\SettingsIcon;
|
||||||
use Jbtronics\SettingsBundle\Metadata\EnvVarMode;
|
use Jbtronics\SettingsBundle\Metadata\EnvVarMode;
|
||||||
use Jbtronics\SettingsBundle\ParameterTypes\ArrayType;
|
|
||||||
use Jbtronics\SettingsBundle\ParameterTypes\StringType;
|
|
||||||
use Jbtronics\SettingsBundle\Settings\Settings;
|
use Jbtronics\SettingsBundle\Settings\Settings;
|
||||||
use Jbtronics\SettingsBundle\Settings\SettingsParameter;
|
use Jbtronics\SettingsBundle\Settings\SettingsParameter;
|
||||||
use Jbtronics\SettingsBundle\Settings\SettingsTrait;
|
use Jbtronics\SettingsBundle\Settings\SettingsTrait;
|
||||||
|
|
@ -50,28 +48,10 @@ class ConradSettings
|
||||||
public ?string $apiKey = null;
|
public ?string $apiKey = null;
|
||||||
|
|
||||||
#[SettingsParameter(label: new TM("settings.ips.conrad.shopID"),
|
#[SettingsParameter(label: new TM("settings.ips.conrad.shopID"),
|
||||||
description: new TM("settings.ips.conrad.shopID.description"),
|
|
||||||
formType: EnumType::class,
|
formType: EnumType::class,
|
||||||
formOptions: ['class' => ConradShopIDs::class],
|
formOptions: ['class' => ConradShopIDs::class],
|
||||||
)]
|
)]
|
||||||
public ConradShopIDs $shopID = ConradShopIDs::COM_B2B;
|
public ConradShopIDs $shopID = ConradShopIDs::COM_B2B;
|
||||||
|
|
||||||
#[SettingsParameter(label: new TM("settings.ips.reichelt.include_vat"))]
|
|
||||||
public bool $includeVAT = true;
|
public bool $includeVAT = true;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array|string[] Only attachments in these languages will be downloaded (ISO 639-1 codes)
|
|
||||||
*/
|
|
||||||
#[Assert\Unique()]
|
|
||||||
#[Assert\All([new Assert\Language()])]
|
|
||||||
#[SettingsParameter(type: ArrayType::class,
|
|
||||||
label: new TM("settings.ips.conrad.attachment_language_filter"), description: new TM("settings.ips.conrad.attachment_language_filter.description"),
|
|
||||||
options: ['type' => StringType::class],
|
|
||||||
formType: LanguageType::class,
|
|
||||||
formOptions: [
|
|
||||||
'multiple' => true,
|
|
||||||
'preferred_choices' => ['en', 'de', 'fr', 'it', 'cs', 'da', 'nl', 'hu', 'hr', 'sk', 'pl']
|
|
||||||
],
|
|
||||||
)]
|
|
||||||
public array $attachmentLanguageFilter = ['en'];
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,22 +30,20 @@ enum ConradShopIDs: string implements TranslatableInterface
|
||||||
{
|
{
|
||||||
case COM_B2B = 'HP_COM_B2B';
|
case COM_B2B = 'HP_COM_B2B';
|
||||||
case DE_B2B = 'CQ_DE_B2B';
|
case DE_B2B = 'CQ_DE_B2B';
|
||||||
case DE_B2C = 'CQ_DE_B2C';
|
|
||||||
case AT_B2C = 'CQ_AT_B2C';
|
case AT_B2C = 'CQ_AT_B2C';
|
||||||
case CH_B2C_DE = 'CQ_CH_B2C_DE';
|
case CH_B2C = 'CQ_CH_B2C';
|
||||||
case CH_B2C_FR = 'CQ_CH_B2C_FR';
|
|
||||||
case SE_B2B = 'HP_SE_B2B';
|
case SE_B2B = 'HP_SE_B2B';
|
||||||
case HU_B2C = 'CQ_HU_B2C';
|
case HU_B2C = 'CQ_HU_B2C';
|
||||||
case CZ_B2B = 'HP_CZ_B2B';
|
case CZ_B2B = 'HP_CZ_B2B';
|
||||||
case SI_B2B = 'HP_SI_B2B';
|
case SI_B2B = 'HP_SI_B2B';
|
||||||
case SK_B2B = 'HP_SK_B2B';
|
case SK_B2B = 'HP_SK_B2B';
|
||||||
case BE_B2B = 'HP_BE_B2B';
|
case BE_B2B = 'HP_BE_B2B';
|
||||||
|
case DE_B2C = 'CQ_DE_B2C';
|
||||||
case PL_B2B = 'HP_PL_B2B';
|
case PL_B2B = 'HP_PL_B2B';
|
||||||
case NL_B2B = 'CQ_NL_B2B';
|
case NL_B2B = 'CQ_NL_B2B';
|
||||||
case NL_B2C = 'CQ_NL_B2C';
|
|
||||||
case DK_B2B = 'HP_DK_B2B';
|
case DK_B2B = 'HP_DK_B2B';
|
||||||
case IT_B2B = 'HP_IT_B2B';
|
case IT_B2B = 'HP_IT_B2B';
|
||||||
|
case NL_B2C = 'CQ_NL_B2C';
|
||||||
case FR_B2B = 'HP_FR_B2B';
|
case FR_B2B = 'HP_FR_B2B';
|
||||||
case AT_B2B = 'CQ_AT_B2B';
|
case AT_B2B = 'CQ_AT_B2B';
|
||||||
case HR_B2B = 'HP_HR_B2B';
|
case HR_B2B = 'HP_HR_B2B';
|
||||||
|
|
@ -56,8 +54,7 @@ enum ConradShopIDs: string implements TranslatableInterface
|
||||||
return match ($this) {
|
return match ($this) {
|
||||||
self::DE_B2B => "conrad.de (B2B)",
|
self::DE_B2B => "conrad.de (B2B)",
|
||||||
self::AT_B2C => "conrad.at (B2C)",
|
self::AT_B2C => "conrad.at (B2C)",
|
||||||
self::CH_B2C_DE => "conrad.ch DE (B2C)",
|
self::CH_B2C => "conrad.ch (B2C)",
|
||||||
self::CH_B2C_FR => "conrad.ch FR (B2C)",
|
|
||||||
self::SE_B2B => "conrad.se (B2B)",
|
self::SE_B2B => "conrad.se (B2B)",
|
||||||
self::HU_B2C => "conrad.hu (B2C)",
|
self::HU_B2C => "conrad.hu (B2C)",
|
||||||
self::CZ_B2B => "conrad.cz (B2B)",
|
self::CZ_B2B => "conrad.cz (B2B)",
|
||||||
|
|
@ -67,7 +64,7 @@ enum ConradShopIDs: string implements TranslatableInterface
|
||||||
self::DE_B2C => "conrad.de (B2C)",
|
self::DE_B2C => "conrad.de (B2C)",
|
||||||
self::PL_B2B => "conrad.pl (B2B)",
|
self::PL_B2B => "conrad.pl (B2B)",
|
||||||
self::NL_B2B => "conrad.nl (B2B)",
|
self::NL_B2B => "conrad.nl (B2B)",
|
||||||
self::DK_B2B => "conradelektronik.dk (B2B)",
|
self::DK_B2B => "conrad.dk (B2B)",
|
||||||
self::IT_B2B => "conrad.it (B2B)",
|
self::IT_B2B => "conrad.it (B2B)",
|
||||||
self::NL_B2C => "conrad.nl (B2C)",
|
self::NL_B2C => "conrad.nl (B2C)",
|
||||||
self::FR_B2B => "conrad.fr (B2B)",
|
self::FR_B2B => "conrad.fr (B2B)",
|
||||||
|
|
@ -79,10 +76,6 @@ enum ConradShopIDs: string implements TranslatableInterface
|
||||||
|
|
||||||
public function getDomain(): string
|
public function getDomain(): string
|
||||||
{
|
{
|
||||||
if ($this === self::DK_B2B) {
|
|
||||||
return 'conradelektronik.dk';
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'conrad.' . $this->getDomainEnd();
|
return 'conrad.' . $this->getDomainEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -101,10 +94,6 @@ enum ConradShopIDs: string implements TranslatableInterface
|
||||||
*/
|
*/
|
||||||
public function getShopID(): string
|
public function getShopID(): string
|
||||||
{
|
{
|
||||||
if ($this === self::CH_B2C_FR || $this === self::CH_B2C_DE) {
|
|
||||||
return 'CQ_CH_B2C';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->value;
|
return $this->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -113,7 +102,7 @@ enum ConradShopIDs: string implements TranslatableInterface
|
||||||
return match ($this) {
|
return match ($this) {
|
||||||
self::DE_B2B, self::DE_B2C => 'de',
|
self::DE_B2B, self::DE_B2C => 'de',
|
||||||
self::AT_B2B, self::AT_B2C => 'at',
|
self::AT_B2B, self::AT_B2C => 'at',
|
||||||
self::CH_B2C_DE => 'ch', self::CH_B2C_FR => 'ch',
|
self::CH_B2C => 'ch',
|
||||||
self::SE_B2B => 'se',
|
self::SE_B2B => 'se',
|
||||||
self::HU_B2C => 'hu',
|
self::HU_B2C => 'hu',
|
||||||
self::CZ_B2B => 'cz',
|
self::CZ_B2B => 'cz',
|
||||||
|
|
@ -134,7 +123,7 @@ enum ConradShopIDs: string implements TranslatableInterface
|
||||||
{
|
{
|
||||||
return match ($this) {
|
return match ($this) {
|
||||||
self::DE_B2B, self::DE_B2C, self::AT_B2B, self::AT_B2C => 'de',
|
self::DE_B2B, self::DE_B2C, self::AT_B2B, self::AT_B2C => 'de',
|
||||||
self::CH_B2C_DE => 'de', self::CH_B2C_FR => 'fr',
|
self::CH_B2C => 'de',
|
||||||
self::SE_B2B => 'sv',
|
self::SE_B2B => 'sv',
|
||||||
self::HU_B2C => 'hu',
|
self::HU_B2C => 'hu',
|
||||||
self::CZ_B2B => 'cs',
|
self::CZ_B2B => 'cs',
|
||||||
|
|
@ -161,7 +150,7 @@ enum ConradShopIDs: string implements TranslatableInterface
|
||||||
self::DE_B2B, self::AT_B2B, self::SE_B2B, self::CZ_B2B, self::SI_B2B,
|
self::DE_B2B, self::AT_B2B, self::SE_B2B, self::CZ_B2B, self::SI_B2B,
|
||||||
self::SK_B2B, self::BE_B2B, self::PL_B2B, self::NL_B2B, self::DK_B2B,
|
self::SK_B2B, self::BE_B2B, self::PL_B2B, self::NL_B2B, self::DK_B2B,
|
||||||
self::IT_B2B, self::FR_B2B, self::COM_B2B, self::HR_B2B => 'b2b',
|
self::IT_B2B, self::FR_B2B, self::COM_B2B, self::HR_B2B => 'b2b',
|
||||||
self::DE_B2C, self::AT_B2C, self::CH_B2C_DE, self::CH_B2C_FR, self::HU_B2C, self::NL_B2C => 'b2c',
|
self::DE_B2C, self::AT_B2C, self::CH_B2C, self::HU_B2C, self::NL_B2C => 'b2c',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9928,13 +9928,13 @@ Element 1 -> Element 1.2]]></target>
|
||||||
<unit id="NdZ1t7a" name="project.builds.number_of_builds_possible">
|
<unit id="NdZ1t7a" name="project.builds.number_of_builds_possible">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>project.builds.number_of_builds_possible</source>
|
<source>project.builds.number_of_builds_possible</source>
|
||||||
<target><![CDATA[You have enough stocked to build <b>%max_builds%</b> builds of this [project].]]></target>
|
<target>You have enough stocked to build <b>%max_builds%</b> builds of this [project].</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="iuSpPbg" name="project.builds.check_project_status">
|
<unit id="iuSpPbg" name="project.builds.check_project_status">
|
||||||
<segment state="translated">
|
<segment state="translated">
|
||||||
<source>project.builds.check_project_status</source>
|
<source>project.builds.check_project_status</source>
|
||||||
<target><![CDATA[The current [project] status is <b>"%project_status%"</b>. You should check if you really want to build the [project] with this status!]]></target>
|
<target>The current [project] status is <b>"%project_status%"</b>. You should check if you really want to build the [project] with this status!</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="Y7vSSxi" name="project.builds.following_bom_entries_miss_instock_n">
|
<unit id="Y7vSSxi" name="project.builds.following_bom_entries_miss_instock_n">
|
||||||
|
|
@ -14286,35 +14286,5 @@ Buerklin-API Authentication server:
|
||||||
<target>Transport error while retrieving information from the providers. Check that your server has internet accesss. See server logs for more info.</target>
|
<target>Transport error while retrieving information from the providers. Check that your server has internet accesss. See server logs for more info.</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
<unit id="kHKChQB" name="settings.ips.conrad">
|
|
||||||
<segment>
|
|
||||||
<source>settings.ips.conrad</source>
|
|
||||||
<target>Conrad</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="gwZXJ0F" name="settings.ips.conrad.shopID">
|
|
||||||
<segment>
|
|
||||||
<source>settings.ips.conrad.shopID</source>
|
|
||||||
<target>Shop ID</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="honqnBf" name="settings.ips.conrad.shopID.description">
|
|
||||||
<segment>
|
|
||||||
<source>settings.ips.conrad.shopID.description</source>
|
|
||||||
<target>The version of the conrad store you wanna get results from. This determines language, prices and currency of the results. If both a B2B and a B2C version if available, you should choose the B2C version if you want prices including VAT. </target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="EVcQbEK" name="settings.ips.conrad.attachment_language_filter">
|
|
||||||
<segment>
|
|
||||||
<source>settings.ips.conrad.attachment_language_filter</source>
|
|
||||||
<target>Language filter for attachments</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
<unit id="MWPmQf2" name="settings.ips.conrad.attachment_language_filter.description">
|
|
||||||
<segment>
|
|
||||||
<source>settings.ips.conrad.attachment_language_filter.description</source>
|
|
||||||
<target>Only includes attachments in the selected languages in the results.</target>
|
|
||||||
</segment>
|
|
||||||
</unit>
|
|
||||||
</file>
|
</file>
|
||||||
</xliff>
|
</xliff>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue