@@ -134,6 +134,8 @@ class DistributionController extends BackendController | |||
$json['users'] = $userModule->findUsers(); | |||
$json['one_distribution_week_active'] = $distributionModule->isOneDistributionWeekActive($date); | |||
$json['tiller_is_synchro'] = $this->buildAjaxInfosResponseTiller($producer, $date); | |||
$json['tiller_is_authenticated'] = $this->getOrderModule()->getTillerManager()->isAuthenticated(); | |||
$json['tiller_url_authorize_code'] = $this->getOrderModule()->getTillerManager()->getUrlAuthorizeCode(); | |||
$json['missing_subscriptions'] = $this->buildAjaxInfosResponseMissingSubscriptions($date, $distribution, $ordersArrayObject); | |||
} | |||
@@ -0,0 +1,91 @@ | |||
<?php | |||
/** | |||
* Copyright distrib (2018) | |||
* | |||
* contact@opendistrib.net | |||
* | |||
* Ce logiciel est un programme informatique servant à aider les producteurs | |||
* à distribuer leur production en circuits courts. | |||
* | |||
* Ce logiciel est régi par la licence CeCILL soumise au droit français et | |||
* respectant les principes de diffusion des logiciels libres. Vous pouvez | |||
* utiliser, modifier et/ou redistribuer ce programme sous les conditions | |||
* de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA | |||
* sur le site "http://www.cecill.info". | |||
* | |||
* En contrepartie de l'accessibilité au code source et des droits de copie, | |||
* de modification et de redistribution accordés par cette licence, il n'est | |||
* offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons, | |||
* seule une responsabilité restreinte pèse sur l'auteur du programme, le | |||
* titulaire des droits patrimoniaux et les concédants successifs. | |||
* | |||
* A cet égard l'attention de l'utilisateur est attirée sur les risques | |||
* associés au chargement, à l'utilisation, à la modification et/ou au | |||
* développement et à la reproduction du logiciel par l'utilisateur étant | |||
* donné sa spécificité de logiciel libre, qui peut le rendre complexe à | |||
* manipuler et qui le réserve donc à des développeurs et des professionnels | |||
* avertis possédant des connaissances informatiques approfondies. Les | |||
* utilisateurs sont donc invités à charger et tester l'adéquation du | |||
* logiciel à leurs besoins dans des conditions permettant d'assurer la | |||
* sécurité de leurs systèmes et ou de leurs données et, plus généralement, | |||
* à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. | |||
* | |||
* Le fait que vous puissiez accéder à cet en-tête signifie que vous avez | |||
* pris connaissance de la licence CeCILL, et que vous en avez accepté les | |||
* termes. | |||
*/ | |||
namespace backend\controllers; | |||
use yii\filters\AccessControl; | |||
use linslin\yii2\curl; | |||
class TillerController extends BackendController | |||
{ | |||
public function behaviors() | |||
{ | |||
return [ | |||
'access' => [ | |||
'class' => AccessControl::class, | |||
'rules' => [ | |||
[ | |||
'allow' => true, | |||
'roles' => ['@'], | |||
'matchCallback' => function ($rule, $action) { | |||
return $this->getUserModule() | |||
->getAuthorizationChecker() | |||
->isGrantedAsProducer($this->getUserCurrent()); | |||
} | |||
] | |||
], | |||
], | |||
]; | |||
} | |||
public function actionOauth(string $code) | |||
{ | |||
$producerModule = $this->getProducerModule(); | |||
$curl = new curl\Curl(); | |||
$redirectUri = $producerModule->getSolver()->getConfig('tiller_redirect_uri'); | |||
$clientId = $producerModule->getSolver()->getConfig('tiller_client_id'); | |||
$clientSecret = $producerModule->getSolver()->getConfig('tiller_client_secret'); | |||
$url = "https://oauth.api.tiller.systems/oauth2/token?grant_type=authorization_code&redirect_uri=$redirectUri&client_id=$clientId&client_secret=$clientSecret&code=$code"; | |||
$response = $curl | |||
->setHeaders(['Content-type' => 'application/x-www-form-urlencoded']) | |||
->post($url); | |||
$datasResponse = json_decode($response); | |||
$accessToken = $datasResponse->access_token; | |||
$refreshToken = $datasResponse->refresh_token; | |||
$producer = $this->getProducerCurrent(); | |||
$producer->tiller_access_token = $accessToken; | |||
$producer->tiller_refresh_token = $refreshToken; | |||
$producer->save(); | |||
return $this->redirectDashboard(); | |||
} | |||
} |
@@ -299,13 +299,18 @@ $this->setPageTitle('Distributions') ; | |||
</div> | |||
<button id="btn-add-subscriptions" @click="addSubscriptions" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-plus"></span> Importer les abonnements</button> | |||
<template v-if="producer && producer.tiller == true"> | |||
<button v-if="tillerIsSynchro" id="btn-tiller" class="btn btn-success btn-xs" disabled><span class="glyphicon glyphicon-refresh"></span> Synchronisé avec Tiller</button> | |||
<template v-else-if="!isDistributionToday()"> | |||
<template v-if="tillerIsAuthenticated"> | |||
<button v-if="tillerIsSynchro" id="btn-tiller" class="btn btn-success btn-xs" disabled><span class="glyphicon glyphicon-refresh"></span> Synchronisé avec Tiller</button> | |||
<template v-else-if="!isDistributionToday()"> | |||
<span data-toggle="tooltip" data-placement="top" data-original-title="Synchronisation possible uniquement le jour de la distribution"> | |||
<button id="btn-tiller" class="btn btn-xs btn-default" disabled><span class="glyphicon glyphicon-refresh"></span> Synchroniser avec Tiller</button> | |||
</span> | |||
</template> | |||
<button v-else id="btn-tiller" class="btn btn-xs btn-default" @click="synchroTiller"><span class="glyphicon glyphicon-refresh"></span> Synchroniser avec Tiller</button> | |||
</template> | |||
<template v-else> | |||
<a :href="tillerUrlAuthorizeCode" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-refresh"></span> Connexion Tiller</a> | |||
</template> | |||
<button v-else id="btn-tiller" class="btn btn-xs btn-default" @click="synchroTiller"><span class="glyphicon glyphicon-refresh"></span> Synchroniser avec Tiller</button> | |||
</template> | |||
<button v-if="producer && producer.credit" id="btn-pay-orders" class="btn btn-default btn-xs" @click="payOrders"><span class="glyphicon glyphicon-euro"></span> Débiter les commandes</button> | |||
<button id="btn-add-order" @click="openModalFormOrderCreate" class="btn btn-xs btn-primary"><span class="glyphicon glyphicon-plus"></span> Ajouter une commande</button> |
@@ -422,8 +422,20 @@ $this->addBreadcrumb($this->getTitle()); | |||
<?= $form->field($model, 'tiller') | |||
->dropDownList(Dropdown::noYesChoices()) | |||
->label('Synchroniser avec Tiller'); ?> | |||
<?= $form->field($model, 'tiller_api_version') | |||
->dropDownList([ | |||
'v2' => 'v2', | |||
'v3' => 'v3' | |||
]); ?> | |||
<h4>API V2</h4> | |||
<?= $form->field($model, 'tiller_provider_token'); ?> | |||
<?= $form->field($model, 'tiller_restaurant_token'); ?> | |||
<h4>API V3</h4> | |||
<?= $form->field($model, 'tiller_redirect_uri'); ?> | |||
<?= $form->field($model, 'tiller_client_id'); ?> | |||
<?= $form->field($model, 'tiller_client_secret'); ?> | |||
</div> | |||
</div> | |||
@@ -75,6 +75,8 @@ var app = new Vue({ | |||
showModalPayment: false, | |||
idOrderPayment: 0, | |||
showLoading: false, | |||
tillerIsAuthenticated: false, | |||
tillerUrlAuthorizeCode: '#', | |||
tillerIsSynchro: false, | |||
checkboxSelectAllOrders: false, | |||
messageGenerateDeliveryNoteDisplayed: false, | |||
@@ -206,6 +208,8 @@ var app = new Vue({ | |||
app.deliveryNotes = response.data.delivery_notes; | |||
} | |||
app.tillerUrlAuthorizeCode = response.data.tiller_url_authorize_code; | |||
app.tillerIsAuthenticated = response.data.tiller_is_authenticated; | |||
app.tillerIsSynchro = response.data.tiller_is_synchro; | |||
app.calendar.attrs = []; | |||
@@ -644,6 +648,9 @@ var app = new Vue({ | |||
.then(function (response) { | |||
app.init(app.idActivePointSale); | |||
}); | |||
}, | |||
authTiller: function() { | |||
}, | |||
totalActivePointSale: function () { | |||
var total = 0; |
@@ -0,0 +1,10 @@ | |||
<?php | |||
namespace common\components\Tiller; | |||
interface TillerClientInterface | |||
{ | |||
public function isAuthenticated(): bool; | |||
public function getOrders($date); | |||
public function postOrder($params); | |||
} |
@@ -36,11 +36,11 @@ | |||
* termes. | |||
*/ | |||
namespace common\components; | |||
namespace common\components\Tiller; | |||
use linslin\yii2\curl; | |||
class TillerClient | |||
class TillerClientV2 implements TillerClientInterface | |||
{ | |||
var $curl; | |||
var $providerToken; | |||
@@ -54,6 +54,11 @@ class TillerClient | |||
$this->restaurantToken = $restaurantToken; | |||
} | |||
public function isAuthenticated(): bool | |||
{ | |||
return true; | |||
} | |||
public function getOrders($date) | |||
{ | |||
$orders = $this->curl->setGetParams([ |
@@ -0,0 +1,94 @@ | |||
<?php | |||
/** | |||
* Copyright distrib (2018) | |||
* | |||
* contact@opendistrib.net | |||
* | |||
* Ce logiciel est un programme informatique servant à aider les producteurs | |||
* à distribuer leur production en circuits courts. | |||
* | |||
* Ce logiciel est régi par la licence CeCILL soumise au droit français et | |||
* respectant les principes de diffusion des logiciels libres. Vous pouvez | |||
* utiliser, modifier et/ou redistribuer ce programme sous les conditions | |||
* de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA | |||
* sur le site "http://www.cecill.info". | |||
* | |||
* En contrepartie de l'accessibilité au code source et des droits de copie, | |||
* de modification et de redistribution accordés par cette licence, il n'est | |||
* offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons, | |||
* seule une responsabilité restreinte pèse sur l'auteur du programme, le | |||
* titulaire des droits patrimoniaux et les concédants successifs. | |||
* | |||
* A cet égard l'attention de l'utilisateur est attirée sur les risques | |||
* associés au chargement, à l'utilisation, à la modification et/ou au | |||
* développement et à la reproduction du logiciel par l'utilisateur étant | |||
* donné sa spécificité de logiciel libre, qui peut le rendre complexe à | |||
* manipuler et qui le réserve donc à des développeurs et des professionnels | |||
* avertis possédant des connaissances informatiques approfondies. Les | |||
* utilisateurs sont donc invités à charger et tester l'adéquation du | |||
* logiciel à leurs besoins dans des conditions permettant d'assurer la | |||
* sécurité de leurs systèmes et ou de leurs données et, plus généralement, | |||
* à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. | |||
* | |||
* Le fait que vous puissiez accéder à cet en-tête signifie que vous avez | |||
* pris connaissance de la licence CeCILL, et que vous en avez accepté les | |||
* termes. | |||
*/ | |||
namespace common\components\Tiller; | |||
use common\components\Tiller\TillerClientInterface; | |||
use linslin\yii2\curl; | |||
class TillerClientV3 implements TillerClientInterface | |||
{ | |||
var $curl; | |||
var $clientId; | |||
var $clientSecret; | |||
var $urlApi = 'https://app.tillersystems.com/api/'; | |||
public function __construct(string $clientId = null, string $clientSecret = null) | |||
{ | |||
$this->curl = new curl\Curl(); | |||
$this->clientId = $clientId; | |||
$this->clientSecret = $clientSecret; | |||
} | |||
public function getUrlAuthorizeCode(string $clientId, string $redirectUri): string | |||
{ | |||
return "https://oauth.api.tiller.systems/oauth2/authorize?client_id=$clientId&response_type=code&scope=&redirect_uri=$redirectUri"; | |||
} | |||
public function isAuthenticated(): bool | |||
{ | |||
return false; | |||
} | |||
public function getOrders($date) | |||
{ | |||
$orders = $this->curl->setGetParams([ | |||
'client_id' => $this->clientId, | |||
'client_secret' => $this->clientSecret, | |||
'dateFrom' => date('Y-m-d H-i-s', strtotime($date)), | |||
'dateTo' => date( | |||
'Y-m-d H-i-s', | |||
strtotime($date) + 24 * 60 * 60 - 1 | |||
), | |||
'status' => 'IN_PROGRESS', | |||
])->get($this->urlApi . 'orders'); | |||
return json_decode($orders); | |||
} | |||
public function postOrder($params) | |||
{ | |||
return $this->curl->setPostParams( | |||
array_merge([ | |||
'client_id' => $this->clientId, | |||
'client_secret' => $this->clientSecret, | |||
], $params) | |||
) | |||
->post($this->urlApi . 'orders'); | |||
} | |||
} |
@@ -2,18 +2,20 @@ | |||
namespace common\logic\Order\Order\Service; | |||
use common\components\TillerClient; | |||
use common\components\Tiller\TillerClientV2; | |||
use common\helpers\MeanPayment; | |||
use common\logic\AbstractManager; | |||
use common\logic\Order\Order\Model\Order; | |||
use common\logic\Order\ProductOrder\Service\ProductOrderSolver; | |||
use common\logic\Producer\Producer\Service\ProducerSolver; | |||
use common\components\Tiller\TillerClientInterface; | |||
use common\components\Tiller\TillerClientV3; | |||
class TillerManager extends AbstractManager | |||
{ | |||
protected ?bool $tillerActivated; | |||
protected ProducerSolver $producerSolver; | |||
protected TillerClient $tillerClient; | |||
protected TillerClientInterface $tillerClient; | |||
protected OrderSolver $orderSolver; | |||
protected OrderBuilder $orderBuilder; | |||
protected ProductOrderSolver $productOrderSolver; | |||
@@ -30,14 +32,38 @@ class TillerManager extends AbstractManager | |||
$this->productOrderSolver = $this->loadService(ProductOrderSolver::class); | |||
} | |||
public function getClient(): TillerClient | |||
public function getClient(): ?TillerClientInterface | |||
{ | |||
return new TillerClient( | |||
$this->producerSolver->getConfig('tiller_provider_token'), | |||
$this->producerSolver->getConfig('tiller_restaurant_token') | |||
$apiVersion = $this->producerSolver->getConfig('tiller_api_version'); | |||
if($apiVersion == 'v2') { | |||
return new TillerClientV2( | |||
$this->producerSolver->getConfig('tiller_provider_token'), | |||
$this->producerSolver->getConfig('tiller_restaurant_token') | |||
); | |||
} | |||
elseif($apiVersion == 'v3') { | |||
return new TillerClientV3( | |||
$this->producerSolver->getConfig('tiller_client_id'), | |||
$this->producerSolver->getConfig('tiller_client_secret') | |||
); | |||
} | |||
return null; | |||
} | |||
public function getUrlAuthorizeCode(): string | |||
{ | |||
return $this->tillerClient->getUrlAuthorizeCode( | |||
$this->producerSolver->getConfig('tiller_client_id'), | |||
$this->producerSolver->getConfig('tiller_redirect_uri') | |||
); | |||
} | |||
public function isAuthenticated(): bool | |||
{ | |||
return $this->tillerClient->isAuthenticated(); | |||
} | |||
public function synchronizeDistribution(string $date): array | |||
{ | |||
$return = []; |
@@ -248,7 +248,13 @@ class Producer extends ActiveRecordCommon | |||
'admin_comment', | |||
'export_shopping_cart_labels_format', | |||
'document_image_bottom', | |||
'website' | |||
'website', | |||
'tiller_api_version', | |||
'tiller_client_id', | |||
'tiller_client_secret', | |||
'tiller_access_token', | |||
'tiller_refresh_token', | |||
'tiller_redirect_uri' | |||
], | |||
'string' | |||
], | |||
@@ -506,6 +512,12 @@ class Producer extends ActiveRecordCommon | |||
'website' => 'Site web', | |||
'option_leave_period_start' => 'Prochains congés : date de début', | |||
'option_leave_period_end' => 'Prochains congés : date de fin', | |||
'tiller_api_version' => 'Tiller : version API', | |||
'tiller_client_id' => 'Tiller : client ID', | |||
'tiller_client_secret' => 'Tiller : client secret', | |||
'tiller_access_token' => 'Tiller : access token', | |||
'tiller_refresh_token' => 'Tiller : refresh token', | |||
'tiller_redirect_uri' => 'Tiller : callback URL', | |||
]; | |||
} | |||
@@ -0,0 +1,36 @@ | |||
<?php | |||
use yii\db\Migration; | |||
use yii\db\Schema; | |||
/** | |||
* Class m240206_135558_add_columns_producer_tiller_api_v3 | |||
*/ | |||
class m240206_135558_add_columns_producer_tiller_api_v3 extends Migration | |||
{ | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeUp() | |||
{ | |||
$this->addColumn('producer', 'tiller_api_version', Schema::TYPE_STRING.' DEFAULT \'v3\''); | |||
$this->addColumn('producer', 'tiller_client_id', Schema::TYPE_STRING); | |||
$this->addColumn('producer', 'tiller_client_secret', Schema::TYPE_STRING); | |||
$this->addColumn('producer', 'tiller_access_token', Schema::TYPE_TEXT); | |||
$this->addColumn('producer', 'tiller_refresh_token', Schema::TYPE_TEXT); | |||
$this->addColumn('producer', 'tiller_redirect_uri', Schema::TYPE_STRING); | |||
} | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeDown() | |||
{ | |||
$this->dropColumn('producer', 'tiller_api_version'); | |||
$this->dropColumn('producer', 'tiller_client_id'); | |||
$this->dropColumn('producer', 'tiller_client_secret'); | |||
$this->dropColumn('producer', 'tiller_access_token'); | |||
$this->dropColumn('producer', 'tiller_refresh_token'); | |||
$this->dropColumn('producer', 'tiller_redirect_uri'); | |||
} | |||
} |