diff --git a/Api/Resource/PredictConfig.php b/Api/Resource/PredictConfig.php
new file mode 100644
index 0000000..ebbecf3
--- /dev/null
+++ b/Api/Resource/PredictConfig.php
@@ -0,0 +1,193 @@
+ [self::GROUP_ADMIN_READ]],
+ denormalizationContext: ['groups' => [self::GROUP_ADMIN_WRITE]]
+)]
+class PredictConfig
+{
+ public const GROUP_ADMIN_READ = 'admin:predict_config:read';
+ public const GROUP_ADMIN_WRITE = 'admin:predict_config:write';
+
+ /**
+ * @var bool|null
+ */
+ #[Groups([self::GROUP_ADMIN_READ, self::GROUP_ADMIN_WRITE])]
+ public ?bool $predict_freeshipping = null;
+
+ /**
+ * @var float|null
+ */
+ #[Groups([self::GROUP_ADMIN_READ, self::GROUP_ADMIN_WRITE])]
+ public ?float $predict_freeshipping_amount = null;
+
+ /**
+ * @var string|null
+ */
+ #[Groups([self::GROUP_ADMIN_READ, self::GROUP_ADMIN_WRITE])]
+ public ?string $store_exapaq_account = null;
+
+ /**
+ * @var string|null
+ */
+ #[Groups([self::GROUP_ADMIN_READ, self::GROUP_ADMIN_WRITE])]
+ public ?string $store_cellphone = null;
+
+ /**
+ * @var string|null
+ */
+ #[Groups([self::GROUP_ADMIN_READ, self::GROUP_ADMIN_WRITE])]
+ public ?string $store_phone = null;
+
+ /**
+ * @var bool|null
+ */
+ #[Groups([self::GROUP_ADMIN_READ, self::GROUP_ADMIN_WRITE])]
+ public ?bool $store_predict_option = null;
+
+ /**
+ * @var int|null
+ */
+ #[Groups([self::GROUP_ADMIN_READ, self::GROUP_ADMIN_WRITE])]
+ public ?int $predict_tax_rule_id = null;
+
+ /**
+ * @return bool|null
+ */
+ public function getPredictFreeshipping(): ?bool
+ {
+ return $this->predict_freeshipping;
+ }
+
+ /**
+ * @param bool|null $predict_freeshipping
+ * @return void
+ */
+ public function setPredictFreeshipping(?bool $predict_freeshipping): void
+ {
+ $this->predict_freeshipping = $predict_freeshipping;
+ }
+
+ /**
+ * @return float|null
+ */
+ public function getPredictFreeshippingAmount(): ?float
+ {
+ return $this->predict_freeshipping_amount;
+ }
+
+ /**
+ * @param float|null $predict_freeshipping_amount
+ * @return void
+ */
+ public function setPredictFreeshippingAmount(?float $predict_freeshipping_amount): void
+ {
+ $this->predict_freeshipping_amount = $predict_freeshipping_amount;
+ }
+
+ /**
+ * @return string|null
+ */
+ public function getStoreExapaqAccount(): ?string
+ {
+ return $this->store_exapaq_account;
+ }
+
+ /**
+ * @param string|null $store_exapaq_account
+ * @return void
+ */
+ public function setStoreExapaqAccount(?string $store_exapaq_account): void
+ {
+ $this->store_exapaq_account = $store_exapaq_account;
+ }
+
+ /**
+ * @return string|null
+ */
+ public function getStoreCellphone(): ?string
+ {
+ return $this->store_cellphone;
+ }
+
+ /**
+ * @param string|null $store_cellphone
+ * @return void
+ */
+ public function setStoreCellphone(?string $store_cellphone): void
+ {
+ $this->store_cellphone = $store_cellphone;
+ }
+
+ /**
+ * @return bool|null
+ */
+ public function getStorePredictOption(): ?bool
+ {
+ return $this->store_predict_option;
+ }
+
+ /**
+ * @param bool|null $store_predict_option
+ * @return void
+ */
+ public function setStorePredictOption(?bool $store_predict_option): void
+ {
+ $this->store_predict_option = $store_predict_option;
+ }
+
+ /**
+ * @return int|null
+ */
+ public function getPredictTaxRuleId(): ?int
+ {
+ return $this->predict_tax_rule_id;
+ }
+
+ /**
+ * @param int|null $predict_tax_rule_id
+ * @return void
+ */
+ public function setPredictTaxRuleId(?int $predict_tax_rule_id): void
+ {
+ $this->predict_tax_rule_id = $predict_tax_rule_id;
+ }
+
+ /**
+ * @return string|null
+ */
+ public function getStorePhone(): ?string
+ {
+ return $this->store_phone;
+ }
+
+ /**
+ * @param string|null $store_phone
+ * @return void
+ */
+ public function setStorePhone(?string $store_phone): void
+ {
+ $this->store_phone = $store_phone;
+ }
+}
diff --git a/Api/Resource/PredictPriceSlice.php b/Api/Resource/PredictPriceSlice.php
new file mode 100644
index 0000000..05f1c36
--- /dev/null
+++ b/Api/Resource/PredictPriceSlice.php
@@ -0,0 +1,142 @@
+ [self::GROUP_ADMIN_READ]],
+ denormalizationContext: ['groups' => [self::GROUP_ADMIN_WRITE]],
+)]
+class PredictPriceSlice
+{
+ public const GROUP_ADMIN_READ = 'admin:predict_price_slice:read';
+ public const GROUP_ADMIN_WRITE = 'admin:predict_price_slice:write';
+
+ /**
+ * @var string|null
+ */
+ #[Groups([self::GROUP_ADMIN_READ])]
+ public ?string $id = null; // ex: "1_12"
+
+ /**
+ * @var int|null
+ */
+ #[Groups([self::GROUP_ADMIN_READ, self::GROUP_ADMIN_WRITE])]
+ public ?int $area = null;
+
+ /**
+ * @var float|null
+ */
+ #[Groups([self::GROUP_ADMIN_READ, self::GROUP_ADMIN_WRITE])]
+ public ?float $weight = null;
+
+ /**
+ * @var float|null
+ */
+ #[Groups([self::GROUP_ADMIN_READ, self::GROUP_ADMIN_WRITE])]
+ public ?float $price = null;
+
+ /**
+ * @return string|null
+ */
+ public function getId(): ?string
+ {
+ return $this->id;
+ }
+
+ /**
+ * @param string|null $id
+ * @return void
+ */
+ public function setId(?string $id): void
+ {
+ $this->id = $id;
+ }
+
+ /**
+ * @return int|null
+ */
+ public function getArea(): ?int
+ {
+ return $this->area;
+ }
+
+ /**
+ * @param int|null $area
+ * @return void
+ */
+ public function setArea(?int $area): void
+ {
+ $this->area = $area;
+ }
+
+ /**
+ * @return float|null
+ */
+ public function getWeight(): ?float
+ {
+ return $this->weight;
+ }
+
+ /**
+ * @param float|null $weight
+ * @return void
+ */
+ public function setWeight(?float $weight): void
+ {
+ $this->weight = $weight;
+ }
+
+ /**
+ * @return float|null
+ */
+ public function getPrice(): ?float
+ {
+ return $this->price;
+ }
+
+ /**
+ * @param float|null $price
+ * @return void
+ */
+ public function setPrice(?float $price): void
+ {
+ $this->price = $price;
+ }
+}
diff --git a/Api/State/PredictConfigPersister.php b/Api/State/PredictConfigPersister.php
new file mode 100644
index 0000000..47af9b5
--- /dev/null
+++ b/Api/State/PredictConfigPersister.php
@@ -0,0 +1,44 @@
+predict_freeshipping)) {
+ ConfigQuery::write('predict_freeshipping', $data->predict_freeshipping ? '1' : '0');
+ }
+ if (isset($data->predict_freeshipping_amount)) {
+ ConfigQuery::write('predict_freeshipping_amount', $data->predict_freeshipping_amount);
+ }
+ if (isset($data->store_exapaq_account)) {
+ ConfigQuery::write('store_exapaq_account', $data->store_exapaq_account);
+ }
+ if (isset($data->store_phone)) {
+ ConfigQuery::write('store_phone', $data->store_phone);
+ }
+ if (isset($data->store_cellphone)) {
+ ConfigQuery::write('store_cellphone', $data->store_cellphone);
+ }
+ if (isset($data->store_predict_option)) {
+ ConfigQuery::write('store_predict_option', $data->store_predict_option ? '1' : '0');
+ }
+ if (isset($data->predict_tax_rule_id)) {
+ ConfigQuery::write('predict_tax_rule_id', $data->predict_tax_rule_id);
+ }
+
+ return $data;
+ }
+}
diff --git a/Api/State/PredictConfigProvider.php b/Api/State/PredictConfigProvider.php
new file mode 100644
index 0000000..6069b54
--- /dev/null
+++ b/Api/State/PredictConfigProvider.php
@@ -0,0 +1,32 @@
+predict_freeshipping = (bool) ConfigQuery::read('predict_freeshipping');
+ $config->predict_freeshipping_amount = (float) ConfigQuery::read('predict_freeshipping_amount');
+ $config->store_exapaq_account = ConfigQuery::read('store_exapaq_account');
+ $config->store_cellphone = ConfigQuery::read('store_cellphone');
+ $config->store_phone = ConfigQuery::read('store_phone');
+ $config->store_predict_option = (bool) ConfigQuery::read('store_predict_option');
+ $config->predict_tax_rule_id = (int) ConfigQuery::read('predict_tax_rule_id');
+
+ return $config;
+ }
+}
diff --git a/Api/State/PredictPriceSlicePersister.php b/Api/State/PredictPriceSlicePersister.php
new file mode 100644
index 0000000..c11caf7
--- /dev/null
+++ b/Api/State/PredictPriceSlicePersister.php
@@ -0,0 +1,58 @@
+area ?? null;
+ $weight = $data->weight ?? null;
+ }
+
+ // POST
+ if ($operation->getMethod() === 'POST') {
+ \Predict\Model\PricesQuery::setPostageAmount(
+ $data->price,
+ $area,
+ $weight
+ );
+ return $data;
+ }
+
+ // PATCH
+ if ($operation->getMethod() === 'PATCH' && $area && $weight) {
+ $newPrice = $data->price ?? null;
+ if ($newPrice === null) {
+ throw new \InvalidArgumentException('Price value required for patch.');
+ }
+ \Predict\Model\PricesQuery::setPostageAmount($newPrice, $area, $weight);
+ $data->area = (int) $area;
+ $data->weight = (float) $weight;
+ return $data;
+ }
+
+ // DELETE
+ if ($operation->getMethod() === 'DELETE' && $area && $weight) {
+ \Predict\Model\PricesQuery::setPostageAmount(false, $area, $weight);
+ return null;
+ }
+
+ return $data;
+ }
+}
diff --git a/Api/State/PredictPriceSliceProvider.php b/Api/State/PredictPriceSliceProvider.php
new file mode 100644
index 0000000..1522f89
--- /dev/null
+++ b/Api/State/PredictPriceSliceProvider.php
@@ -0,0 +1,51 @@
+id = $area . '_' . $weight;
+ $resource->area = (int) $area;
+ $resource->weight = (float) $weight;
+ $resource->price = (float) $prices[$area]['slices'][$weight];
+ return $resource;
+ }
+ return null;
+ }
+
+ // GetCollection
+ $resources = [];
+ foreach ($prices as $area => $areaData) {
+ if (!isset($areaData['slices']) || $area === '') continue;
+ foreach ($areaData['slices'] as $weight => $price) {
+ $resource = new PredictPriceSlice();
+ $resource->id = $area . '_' . $weight;
+ $resource->area = (int) $area;
+ $resource->weight = (float) $weight;
+ $resource->price = (float) $price;
+ $resources[] = $resource;
+ }
+ }
+ return $resources;
+ }
+}
diff --git a/Config/module.xml b/Config/module.xml
index 080ef1b..5b157c7 100755
--- a/Config/module.xml
+++ b/Config/module.xml
@@ -10,7 +10,7 @@
Livraison en 24/48H dans un créneau horaire précis (parmi des choix proposés par DPD).
- 2.1.9
+ 2.2.0
Benjamin Perche
bperche@openstudio.fr
diff --git a/Predict.php b/Predict.php
index f0e7d1d..afe7753 100755
--- a/Predict.php
+++ b/Predict.php
@@ -204,7 +204,7 @@ public static function setFreeShippingAmount($amount)
public static function configureServices(ServicesConfigurator $servicesConfigurator): void
{
$servicesConfigurator->load(self::getModuleCode().'\\', __DIR__)
- ->exclude([THELIA_MODULE_DIR . ucfirst(self::getModuleCode()). "/I18n/*"])
+ ->exclude(["/I18n/*"])
->autowire(true)
->autoconfigure(true);
}