mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2026-02-03 07:59:37 +00:00
Implemented basic functionality to search and retrieve part details
This commit is contained in:
parent
705e71f1eb
commit
7ab33c859b
3 changed files with 223 additions and 24 deletions
|
|
@ -31,7 +31,7 @@ use Symfony\Contracts\HttpClient\HttpClientInterface;
|
|||
readonly class ConradProvider implements InfoProviderInterface
|
||||
{
|
||||
|
||||
private const SEARCH_ENDPOINT = 'https://api.conrad.de/search/1/v3/facetSearch';
|
||||
private const SEARCH_ENDPOINT = '/search/1/v3/facetSearch';
|
||||
|
||||
public function __construct(private HttpClientInterface $httpClient, private ConradSettings $settings)
|
||||
{
|
||||
|
|
@ -40,7 +40,7 @@ readonly class ConradProvider implements InfoProviderInterface
|
|||
public function getProviderInfo(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'Pollin',
|
||||
'name' => 'Conrad',
|
||||
'description' => 'Retrieves part information from conrad.de',
|
||||
'url' => 'https://www.conrad.de/',
|
||||
'disabled_help' => 'Set API key in settings',
|
||||
|
|
@ -58,9 +58,38 @@ readonly class ConradProvider implements InfoProviderInterface
|
|||
return !empty($this->settings->apiKey);
|
||||
}
|
||||
|
||||
private function getProductUrl(string $productId): string
|
||||
{
|
||||
return 'https://' . $this->settings->shopID->getDomain() . '/' . $this->settings->shopID->getLanguage() . '/p/' . $productId;
|
||||
}
|
||||
|
||||
private function getFootprintFromTechnicalDetails(array $technicalDetails): ?string
|
||||
{
|
||||
foreach ($technicalDetails as $detail) {
|
||||
if ($detail['name'] === 'ATT_LOV_HOUSING_SEMICONDUCTORS') {
|
||||
return $detail['values'][0] ?? 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;
|
||||
}
|
||||
|
||||
public function searchByKeyword(string $keyword): array
|
||||
{
|
||||
$url = self::SEARCH_ENDPOINT . '/' . $this->settings->country . '/' . $this->settings->language . '/' . $this->settings->customerType;
|
||||
$url = $this->settings->shopID->getAPIRoot() . self::SEARCH_ENDPOINT . '/'
|
||||
. $this->settings->shopID->getDomainEnd() . '/' . $this->settings->shopID->getLanguage()
|
||||
. '/' . $this->settings->shopID->getCustomerType();
|
||||
|
||||
$response = $this->httpClient->request('POST', $url, [
|
||||
'query' => [
|
||||
|
|
@ -68,13 +97,15 @@ readonly class ConradProvider implements InfoProviderInterface
|
|||
],
|
||||
'json' => [
|
||||
'query' => $keyword,
|
||||
'size' => 25,
|
||||
],
|
||||
]);
|
||||
|
||||
$out = [];
|
||||
$results = $response->toArray();
|
||||
|
||||
foreach($results as $result) {
|
||||
foreach($results['hits'] as $result) {
|
||||
|
||||
$out[] = new SearchResultDTO(
|
||||
provider_key: $this->getProviderKey(),
|
||||
provider_id: $result['productId'],
|
||||
|
|
@ -83,6 +114,8 @@ readonly class ConradProvider implements InfoProviderInterface
|
|||
manufacturer: $result['brand']['name'] ?? null,
|
||||
mpn: $result['manufacturerId'] ?? null,
|
||||
preview_image_url: $result['image'] ?? null,
|
||||
provider_url: $this->getProductUrl($result['productId']),
|
||||
footprint: $this->getFootprintFromTechnicalDetails($result['technicalDetails'] ?? []),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -91,7 +124,29 @@ readonly class ConradProvider implements InfoProviderInterface
|
|||
|
||||
public function getDetails(string $id): PartDetailDTO
|
||||
{
|
||||
// TODO: Implement getDetails() method.
|
||||
$productInfoURL = $this->settings->shopID->getAPIRoot() . '/product/1/service/' . $this->settings->shopID->getShopID()
|
||||
. '/product/' . $id;
|
||||
|
||||
$response = $this->httpClient->request('GET', $productInfoURL, [
|
||||
'query' => [
|
||||
'apikey' => $this->settings->apiKey,
|
||||
]
|
||||
]);
|
||||
|
||||
$data = $response->toArray();
|
||||
|
||||
return new PartDetailDTO(
|
||||
provider_key: $this->getProviderKey(),
|
||||
provider_id: $data['shortProductNumber'],
|
||||
name: $data['productShortInformation']['title'],
|
||||
description: $data['productShortInformation']['shortDescription'] ?? '',
|
||||
manufacturer: $data['brand']['displayName'] ?? null,
|
||||
mpn: $data['productFullInformation']['manufacturer']['id'] ?? null,
|
||||
preview_image_url: $data['productShortInformation']['mainImage']['imageUrl'] ?? null,
|
||||
provider_url: $this->getProductUrl($data['shortProductNumber']),
|
||||
footprint: $this->getFootprintFromTechnicalAttributes($data['productFullInformation']['technicalAttributes'] ?? []),
|
||||
notes: $data['productFullInformation']['description'] ?? null,
|
||||
);
|
||||
}
|
||||
|
||||
public function getCapabilities(): array
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ use Jbtronics\SettingsBundle\Settings\SettingsParameter;
|
|||
use Jbtronics\SettingsBundle\Settings\SettingsTrait;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CountryType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\EnumType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\LanguageType;
|
||||
use Symfony\Component\Translation\TranslatableMessage as TM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
|
@ -46,24 +47,11 @@ class ConradSettings
|
|||
formOptions: ["help_html" => true], envVar: "PROVIDER_CONRAD_API_KEY", envVarMode: EnvVarMode::OVERWRITE)]
|
||||
public ?string $apiKey = null;
|
||||
|
||||
#[SettingsParameter(label: new TM("settings.ips.tme.country"), formType: CountryType::class,
|
||||
envVar: "PROVIDER_CONRAD_COUNTRY", envVarMode: EnvVarMode::OVERWRITE)]
|
||||
#[Assert\Country]
|
||||
public string $country = "DE";
|
||||
#[SettingsParameter(label: new TM("settings.ips.conrad.shopID"),
|
||||
formType: EnumType::class,
|
||||
formOptions: ['class' => ConradShopIDs::class],
|
||||
)]
|
||||
public ConradShopIDs $shopID = ConradShopIDs::COM_B2B;
|
||||
|
||||
#[SettingsParameter(label: new TM("settings.ips.tme.language"), formType: LanguageType::class,
|
||||
envVar: "PROVIDER_CONRAD_LANGUAGE", envVarMode: EnvVarMode::OVERWRITE)]
|
||||
#[Assert\Language]
|
||||
public string $language = "en";
|
||||
|
||||
#[SettingsParameter(label: new TM("settings.ips.conrad.customerType"), formType: ChoiceType::class,
|
||||
formOptions: [
|
||||
"choices" => [
|
||||
"settings.ips.conrad.customerType.b2c" => "b2c",
|
||||
"settings.ips.conrad.customerType.b2b" => "b2b",
|
||||
],
|
||||
],
|
||||
envVar: "PROVIDER_CONRAD_LANGUAGE", envVarMode: EnvVarMode::OVERWRITE, )]
|
||||
#[Assert\Choice(choices: ["b2c", "b2b"])]
|
||||
public string $customerType = "b2c";
|
||||
public bool $includeVAT = true;
|
||||
}
|
||||
|
|
|
|||
156
src/Settings/InfoProviderSystem/ConradShopIDs.php
Normal file
156
src/Settings/InfoProviderSystem/ConradShopIDs.php
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
<?php
|
||||
/*
|
||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
||||
*
|
||||
* Copyright (C) 2019 - 2026 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\Settings\InfoProviderSystem;
|
||||
|
||||
use Symfony\Contracts\Translation\TranslatableInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
enum ConradShopIDs: string implements TranslatableInterface
|
||||
{
|
||||
case COM_B2B = 'HP_COM_B2B';
|
||||
case DE_B2B = 'CQ_DE_B2B';
|
||||
case AT_B2C = 'CQ_AT_B2C';
|
||||
case CH_B2C = 'CQ_CH_B2C';
|
||||
case SE_B2B = 'HP_SE_B2B';
|
||||
case HU_B2C = 'CQ_HU_B2C';
|
||||
case CZ_B2B = 'HP_CZ_B2B';
|
||||
case SI_B2B = 'HP_SI_B2B';
|
||||
case SK_B2B = 'HP_SK_B2B';
|
||||
case BE_B2B = 'HP_BE_B2B';
|
||||
case DE_B2C = 'CQ_DE_B2C';
|
||||
case PL_B2B = 'HP_PL_B2B';
|
||||
case NL_B2B = 'CQ_NL_B2B';
|
||||
case DK_B2B = 'HP_DK_B2B';
|
||||
case IT_B2B = 'HP_IT_B2B';
|
||||
case NL_B2C = 'CQ_NL_B2C';
|
||||
case FR_B2B = 'HP_FR_B2B';
|
||||
case AT_B2B = 'CQ_AT_B2B';
|
||||
case HR_B2B = 'HP_HR_B2B';
|
||||
|
||||
|
||||
public function trans(TranslatorInterface $translator, ?string $locale = null): string
|
||||
{
|
||||
return match ($this) {
|
||||
self::DE_B2B => "conrad.de (B2B)",
|
||||
self::AT_B2C => "conrad.at (B2C)",
|
||||
self::CH_B2C => "conrad.ch (B2C)",
|
||||
self::SE_B2B => "conrad.se (B2B)",
|
||||
self::HU_B2C => "conrad.hu (B2C)",
|
||||
self::CZ_B2B => "conrad.cz (B2B)",
|
||||
self::SI_B2B => "conrad.si (B2B)",
|
||||
self::SK_B2B => "conrad.sk (B2B)",
|
||||
self::BE_B2B => "conrad.be (B2B)",
|
||||
self::DE_B2C => "conrad.de (B2C)",
|
||||
self::PL_B2B => "conrad.pl (B2B)",
|
||||
self::NL_B2B => "conrad.nl (B2B)",
|
||||
self::DK_B2B => "conrad.dk (B2B)",
|
||||
self::IT_B2B => "conrad.it (B2B)",
|
||||
self::NL_B2C => "conrad.nl (B2C)",
|
||||
self::FR_B2B => "conrad.fr (B2B)",
|
||||
self::COM_B2B => "conrad.com (B2B)",
|
||||
self::AT_B2B => "conrad.at (B2B)",
|
||||
self::HR_B2B => "conrad.hr (B2B)",
|
||||
};
|
||||
}
|
||||
|
||||
public function getDomain(): string
|
||||
{
|
||||
return 'conrad.' . $this->getDomainEnd();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the API root URL for this shop ID. e.g. https://api.conrad.de
|
||||
* @return string
|
||||
*/
|
||||
public function getAPIRoot(): string
|
||||
{
|
||||
return 'https://api.' . $this->getDomain();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the shop ID value used in the API requests. e.g. 'CQ_DE_B2B'
|
||||
* @return string
|
||||
*/
|
||||
public function getShopID(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
public function getDomainEnd(): string
|
||||
{
|
||||
return match ($this) {
|
||||
self::DE_B2B, self::DE_B2C => 'de',
|
||||
self::AT_B2B, self::AT_B2C => 'at',
|
||||
self::CH_B2C => 'ch',
|
||||
self::SE_B2B => 'se',
|
||||
self::HU_B2C => 'hu',
|
||||
self::CZ_B2B => 'cz',
|
||||
self::SI_B2B => 'si',
|
||||
self::SK_B2B => 'sk',
|
||||
self::BE_B2B => 'be',
|
||||
self::PL_B2B => 'pl',
|
||||
self::NL_B2B, self::NL_B2C => 'nl',
|
||||
self::DK_B2B => 'dk',
|
||||
self::IT_B2B => 'it',
|
||||
self::FR_B2B => 'fr',
|
||||
self::COM_B2B => 'com',
|
||||
self::HR_B2B => 'hr',
|
||||
};
|
||||
}
|
||||
|
||||
public function getLanguage(): string
|
||||
{
|
||||
return match ($this) {
|
||||
self::DE_B2B, self::DE_B2C, self::AT_B2B, self::AT_B2C => 'de',
|
||||
self::CH_B2C => 'de',
|
||||
self::SE_B2B => 'sv',
|
||||
self::HU_B2C => 'hu',
|
||||
self::CZ_B2B => 'cs',
|
||||
self::SI_B2B => 'sl',
|
||||
self::SK_B2B => 'sk',
|
||||
self::BE_B2B => 'nl',
|
||||
self::PL_B2B => 'pl',
|
||||
self::NL_B2B, self::NL_B2C => 'nl',
|
||||
self::DK_B2B => 'da',
|
||||
self::IT_B2B => 'it',
|
||||
self::FR_B2B => 'fr',
|
||||
self::COM_B2B => 'en',
|
||||
self::HR_B2B => 'hr',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the customer type for this shop ID. e.g. 'b2b' or 'b2c'
|
||||
* @return string 'b2b' or 'b2c'
|
||||
*/
|
||||
public function getCustomerType(): string
|
||||
{
|
||||
return match ($this) {
|
||||
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::IT_B2B, self::FR_B2B, self::COM_B2B, self::HR_B2B => 'b2b',
|
||||
self::DE_B2C, self::AT_B2C, self::CH_B2C, self::HU_B2C, self::NL_B2C => 'b2c',
|
||||
};
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue