return $this->redirect(['index']); | return $this->redirect(['index']); | ||||
} | } | ||||
public function actionDolibarr(int $id) | |||||
{ | |||||
$producerManager = $this->getProducerManager(); | |||||
$producer = $this->findProducer($id); | |||||
if($producer->dolibarr_socid) { | |||||
$producerManager->generateDolibarrProducerInvoice($producer); | |||||
$this->setFlash('success', "Facture générée sur Dolibarr pour le producteur <strong>".$producer->name."</strong>"); | |||||
} | |||||
else { | |||||
$this->setFlash('error', "Dolibarr : l'id user du producteur doit être défini"); | |||||
} | |||||
return $this->redirect(['index']); | |||||
} | |||||
public function actionUserTransfer($fromProducerId, $toProducerId, $withOrders = 1) | public function actionUserTransfer($fromProducerId, $toProducerId, $withOrders = 1) | ||||
{ | { | ||||
$producerManager = $this->getProducerManager(); | $producerManager = $this->getProducerManager(); | ||||
if (($model = $producerManager->findOneProducerById($id)) !== null) { | if (($model = $producerManager->findOneProducerById($id)) !== null) { | ||||
return $model; | return $model; | ||||
} else { | } else { | ||||
throw new NotFoundHttpException('The requested page does not exist.'); | |||||
throw new NotFoundHttpException('Producteur introuvable.'); | |||||
} | } | ||||
} | } | ||||
1 => 'Oui' | 1 => 'Oui' | ||||
]); ?> | ]); ?> | ||||
<?= $form->field($model, 'option_billing_permanent_transfer_amount') ?> | <?= $form->field($model, 'option_billing_permanent_transfer_amount') ?> | ||||
<?= $form->field($model, 'dolibarr_socid') ?> | |||||
<?= $form->field($model, 'dolibarr_product_id') ?> | |||||
<div class="form-group"> | <div class="form-group"> | ||||
<?= Html::submitButton($model->isNewRecord ? 'Ajouter' : 'Modifier', ['class' => 'btn btn-success']) ?> | <?= Html::submitButton($model->isNewRecord ? 'Ajouter' : 'Modifier', ['class' => 'btn btn-success']) ?> | ||||
</div> | </div> |
], | ], | ||||
[ | [ | ||||
'class' => 'yii\grid\ActionColumn', | 'class' => 'yii\grid\ActionColumn', | ||||
'template' => '{update} {billing} {alwaysdata}', | |||||
'template' => '{update} {dolibarr} {billing} {alwaysdata}', | |||||
'headerOptions' => ['class' => 'column-actions'], | 'headerOptions' => ['class' => 'column-actions'], | ||||
'contentOptions' => ['class' => 'column-actions'], | 'contentOptions' => ['class' => 'column-actions'], | ||||
'buttons' => [ | 'buttons' => [ | ||||
] | ] | ||||
); | ); | ||||
}, | }, | ||||
'dolibarr' => function ($url, $model) { | |||||
return Html::a( | |||||
'<span class="glyphicon glyphicon-paste"></span>', | |||||
$url, | |||||
[ | |||||
'title' => 'Générer la facture sur Dolibarr', | |||||
'class' => 'btn btn-default' | |||||
] | |||||
); | |||||
}, | |||||
'billing' => function ($url, $model) { | 'billing' => function ($url, $model) { | ||||
return Html::a( | return Html::a( | ||||
'<span class="glyphicon glyphicon-euro"></span>', | '<span class="glyphicon glyphicon-euro"></span>', |
<?= $form->field($model, 'range_begin') ?> | <?= $form->field($model, 'range_begin') ?> | ||||
<?= $form->field($model, 'range_end') ?> | <?= $form->field($model, 'range_end') ?> | ||||
<?= $form->field($model, 'price') ?> | <?= $form->field($model, 'price') ?> | ||||
<?= $form->field($model, 'dolibarr_product_id') ?> | |||||
<div class="form-group"> | <div class="form-group"> | ||||
<?= Html::submitButton('Ajouter', ['class' => 'btn btn-success']) ?> | <?= Html::submitButton('Ajouter', ['class' => 'btn btn-success']) ?> | ||||
</div> | </div> |
use yii\helpers\Html; | use yii\helpers\Html; | ||||
use yii\widgets\ActiveForm; | use yii\widgets\ActiveForm; | ||||
$this->setTitle('Éditer une taxe') ; | |||||
$this->addBreadcrumb(['label' => 'taxe', 'url' => ['index']]) ; | |||||
$this->setTitle('Éditer une tranche de prix') ; | |||||
$this->addBreadcrumb(['label' => 'tranche de prix', 'url' => ['index']]) ; | |||||
$this->addBreadcrumb('Éditer') ; | $this->addBreadcrumb('Éditer') ; | ||||
?> | ?> | ||||
<?= $form->field($model, 'range_begin') ?> | <?= $form->field($model, 'range_begin') ?> | ||||
<?= $form->field($model, 'range_end') ?> | <?= $form->field($model, 'range_end') ?> | ||||
<?= $form->field($model, 'price') ?> | <?= $form->field($model, 'price') ?> | ||||
<?= $form->field($model, 'dolibarr_product_id') ?> | |||||
<div class="form-group"> | <div class="form-group"> | ||||
<?= Html::submitButton('Ajouter', ['class' => 'btn btn-success']) ?> | <?= Html::submitButton('Ajouter', ['class' => 'btn btn-success']) ?> | ||||
</div> | </div> |
<?php | |||||
namespace common\components; | |||||
use GuzzleHttp\Client; | |||||
use linslin\yii2\curl\Curl; | |||||
use Psr\Http\Message\ResponseInterface; | |||||
abstract class AbstractApi | |||||
{ | |||||
public string $url; | |||||
public array $auth; | |||||
public function __construct(string $url, array $auth) | |||||
{ | |||||
$this->url = $url; | |||||
$this->auth = $auth; | |||||
} | |||||
protected function get(string $resource, array $data = [], bool $raw = false) | |||||
{ | |||||
$client = $this->getClient(); | |||||
$client->setGetParams($data); | |||||
return $client->get($this->buildUrl($resource), $raw); | |||||
} | |||||
protected function post(string $resource, array $data = [], bool $raw = true) | |||||
{ | |||||
$client = $this->getClient(); | |||||
$client->setPostParams($data); | |||||
return $client->post($this->buildUrl($resource), $raw); | |||||
} | |||||
protected function put(string $resource, array $data = [], bool $raw = true) | |||||
{ | |||||
$client = $this->getClient(); | |||||
$client->setPostParams($data); | |||||
return $client->put($this->buildUrl($resource), $raw); | |||||
} | |||||
private function getClient() | |||||
{ | |||||
$curl = new Curl(); | |||||
$curl->setHeader($this->auth[0], $this->auth[1]); | |||||
return $curl; | |||||
} | |||||
public function buildUrl(string $resource): string | |||||
{ | |||||
return $this->url.$resource; | |||||
} | |||||
protected function getUrl(): string | |||||
{ | |||||
return $this->url; | |||||
} | |||||
private function getAuth(): array | |||||
{ | |||||
return $this->auth; | |||||
} | |||||
} |
<?php | |||||
namespace common\components; | |||||
use Psr\Http\Message\ResponseInterface; | |||||
class DolibarrApi extends AbstractApi | |||||
{ | |||||
const RESOURCE_INVOICES = 'invoices'; | |||||
const RESOURCE_PRODUCTS = 'products'; | |||||
const RESOURCE_DOCUMENTS = 'documents'; | |||||
public function createInvoice(int $idUser) | |||||
{ | |||||
return $this->post(self::RESOURCE_INVOICES, [ | |||||
'socid' => $idUser | |||||
]); | |||||
} | |||||
public function addInvoiceLine(int $idInvoice, int $idProduct) | |||||
{ | |||||
$productArray = $this->getProduct($idProduct); | |||||
return $this->post(self::RESOURCE_INVOICES . '/' . $idInvoice . '/lines', [ | |||||
'fk_product' => $idProduct, | |||||
'subprice' => $productArray['price'], | |||||
'qty' => 1, | |||||
'desc' => $productArray['description'] | |||||
]); | |||||
} | |||||
public function validateInvoice(int $idInvoice) | |||||
{ | |||||
return $this->post(self::RESOURCE_INVOICES . '/' . $idInvoice . '/validate', [], false); | |||||
} | |||||
public function generateInvoicePdf(string $reference) | |||||
{ | |||||
return $this->put(self::RESOURCE_DOCUMENTS . '/builddoc', [ | |||||
'modulepart' => 'invoice', | |||||
'doctemplate' => 'crabe', | |||||
'langcode' => 'fr_FR', | |||||
'original_file' => $reference.'/'.$reference.'.pdf' | |||||
]); | |||||
} | |||||
public function getProduct(int $idProduct) | |||||
{ | |||||
return $this->get(self::RESOURCE_PRODUCTS . '/' . $idProduct); | |||||
} | |||||
} |
*/ | */ | ||||
use common\components\BusinessLogic; | use common\components\BusinessLogic; | ||||
use common\components\DolibarrApi; | |||||
use common\logic\Distribution\Distribution\Model\Distribution; | use common\logic\Distribution\Distribution\Model\Distribution; | ||||
use common\logic\Document\DeliveryNote\Model\DeliveryNote; | use common\logic\Document\DeliveryNote\Model\DeliveryNote; | ||||
use common\logic\Ticket\Ticket\Model\Ticket; | use common\logic\Ticket\Ticket\Model\Ticket; | ||||
'enableStrictParsing' => false, | 'enableStrictParsing' => false, | ||||
'rules' => [], | 'rules' => [], | ||||
], | ], | ||||
'dolibarrApi' => function() { | |||||
return new DolibarrApi( | |||||
Yii::$app->parameterBag->get('dolibarrApiUrl'), | |||||
['DOLAPIKEY', \Yii::$app->parameterBag->get('dolibarrApiKey')] | |||||
); | |||||
}, | |||||
'logic' => function () { | 'logic' => function () { | ||||
return new BusinessLogic(); | return new BusinessLogic(); | ||||
}, | }, |
<?php | |||||
namespace common\logic; | |||||
abstract class AbstractUtils extends AbstractService implements UtilsInterface | |||||
{ | |||||
} |
'option_online_payment_minimum_amount', | 'option_online_payment_minimum_amount', | ||||
'option_document_price_decimals', | 'option_document_price_decimals', | ||||
'option_billing_reduction_percentage', | 'option_billing_reduction_percentage', | ||||
'dolibarr_socid', | |||||
'dolibarr_product_id' | |||||
], | ], | ||||
'integer' | 'integer' | ||||
], | ], | ||||
'option_testimony' => 'Témoignage', | 'option_testimony' => 'Témoignage', | ||||
'option_time_saved' => 'Temps gagné / semaine', | 'option_time_saved' => 'Temps gagné / semaine', | ||||
'contact_email' => 'Email de contact', | 'contact_email' => 'Email de contact', | ||||
'admin_comment' => 'Commentaire' | |||||
'admin_comment' => 'Commentaire', | |||||
'dolibarr_socid' => 'Dolibarr : id user', | |||||
'dolibarr_product_id' => 'Dolibarr : id produit' | |||||
]; | ]; | ||||
} | } | ||||
]; | ]; | ||||
} | } | ||||
public function getTurnoverLastMonth(Producer $producer, bool $format = false) | |||||
{ | |||||
$period = date('Y-m', strtotime('-1 month')); | |||||
return $this->getTurnover($producer, $period, $format); | |||||
} | |||||
/** | /** | ||||
* Retourne le CA du producteur pour un mois donné | * Retourne le CA du producteur pour un mois donné | ||||
*/ | */ |
<?php | |||||
namespace common\logic\Producer\Producer\Service; | |||||
use common\components\DolibarrApi; | |||||
use common\logic\AbstractUtils; | |||||
use common\logic\Producer\Producer\Model\Producer; | |||||
use common\logic\Producer\Producer\Repository\ProducerRepository; | |||||
use common\logic\Producer\ProducerPriceRange\Repository\ProducerPriceRangeRepository; | |||||
use yii\base\ErrorException; | |||||
class DolibarrProducerUtils extends AbstractUtils | |||||
{ | |||||
protected DolibarrApi $dolibarrApi; | |||||
protected ProducerPriceRangeRepository $producerPriceRangeRepository; | |||||
protected ProducerRepository $producerRepository; | |||||
public function loadDependencies(): void | |||||
{ | |||||
$this->dolibarrApi = \Yii::$app->dolibarrApi; | |||||
$this->producerPriceRangeRepository = $this->loadService(ProducerPriceRangeRepository::class); | |||||
$this->producerRepository = $this->loadService(ProducerRepository::class); | |||||
} | |||||
public function generateDolibarrProducerInvoice(Producer $producer) | |||||
{ | |||||
$idProduct = $this->getDolibarrProductId($producer); | |||||
if(!$idProduct) { | |||||
throw new ErrorException("Dolibarr : pas d'id product trouvé pour le producteur ".$producer->name); | |||||
} | |||||
$idInvoice = $this->dolibarrApi->createInvoice($producer->dolibarr_socid); | |||||
$this->dolibarrApi->addInvoiceLine($idInvoice, $idProduct); | |||||
$responseValidate = $this->dolibarrApi->validateInvoice($idInvoice); | |||||
$this->dolibarrApi->generateInvoicePdf($responseValidate['ref']); | |||||
} | |||||
private function getDolibarrProductId(Producer $producer) | |||||
{ | |||||
if($producer->dolibarr_product_id) { | |||||
$idProduct = $producer->dolibarr_product_id; | |||||
} | |||||
else { | |||||
$producerPriceRange = $this->producerPriceRangeRepository->getProducerPriceRangeByTurnover($this->producerRepository->getTurnoverLastMonth($producer)); | |||||
if($producerPriceRange && $producerPriceRange->dolibarr_product_id) { | |||||
$idProduct = $producerPriceRange->dolibarr_product_id; | |||||
} | |||||
} | |||||
return $idProduct; | |||||
} | |||||
} |
use common\logic\AbstractContainer; | use common\logic\AbstractContainer; | ||||
use common\logic\Producer\Producer\Repository\ProducerRepository; | use common\logic\Producer\Producer\Repository\ProducerRepository; | ||||
use common\logic\Producer\Producer\Service\DolibarrProducerUtils; | |||||
use common\logic\Producer\Producer\Service\ProducerBuilder; | use common\logic\Producer\Producer\Service\ProducerBuilder; | ||||
use common\logic\Producer\Producer\Service\ProducerDefinition; | use common\logic\Producer\Producer\Service\ProducerDefinition; | ||||
use common\logic\Producer\Producer\Service\ProducerSolver; | use common\logic\Producer\Producer\Service\ProducerSolver; | ||||
ProducerSolver::class, | ProducerSolver::class, | ||||
ProducerRepository::class, | ProducerRepository::class, | ||||
ProducerBuilder::class, | ProducerBuilder::class, | ||||
ProducerUtils::class | |||||
ProducerUtils::class, | |||||
DolibarrProducerUtils::class, | |||||
]; | ]; | ||||
} | } | ||||
use common\logic\AbstractManager; | use common\logic\AbstractManager; | ||||
use common\logic\Producer\Producer\Repository\ProducerRepository; | use common\logic\Producer\Producer\Repository\ProducerRepository; | ||||
use common\logic\Producer\Producer\Service\DolibarrProducerUtils; | |||||
use common\logic\Producer\Producer\Service\ProducerBuilder; | use common\logic\Producer\Producer\Service\ProducerBuilder; | ||||
use common\logic\Producer\Producer\Service\ProducerDefinition; | use common\logic\Producer\Producer\Service\ProducerDefinition; | ||||
use common\logic\Producer\Producer\Service\ProducerSolver; | use common\logic\Producer\Producer\Service\ProducerSolver; | ||||
* @mixin ProducerRepository | * @mixin ProducerRepository | ||||
* @mixin ProducerBuilder | * @mixin ProducerBuilder | ||||
* @mixin ProducerUtils | * @mixin ProducerUtils | ||||
* @mixin DolibarrProducerUtils | |||||
*/ | */ | ||||
class ProducerManager extends AbstractManager | class ProducerManager extends AbstractManager | ||||
{ | { |
{ | { | ||||
return [ | return [ | ||||
[['range_begin', 'range_end', 'price'], 'double'], | [['range_begin', 'range_end', 'price'], 'double'], | ||||
[['dolibarr_product_id'], 'integer'] | |||||
]; | ]; | ||||
} | } | ||||
'range_begin' => 'Début', | 'range_begin' => 'Début', | ||||
'range_end' => 'Fin', | 'range_end' => 'Fin', | ||||
'price' => 'Tarif (HT)', | 'price' => 'Tarif (HT)', | ||||
'dolibarr_product_id' => 'Dolibarr : id produit' | |||||
]; | ]; | ||||
} | } | ||||
} | } |
return $this->queryProducerPriceRanges()->find(); | return $this->queryProducerPriceRanges()->find(); | ||||
} | } | ||||
public function getProducerPriceRangeByTurnover(float $turnover = null): ?ProducerPriceRange | |||||
{ | |||||
$producerPriceRangeArray = $this->findProducerPriceRanges(); | |||||
foreach ($producerPriceRangeArray as $producerPriceRange) { | |||||
if ($turnover >= $producerPriceRange->range_begin && $turnover < $producerPriceRange->range_end) { | |||||
return $producerPriceRange; | |||||
} | |||||
} | |||||
return null; | |||||
} | |||||
public function getAmountToBeBilledByTurnover(float $turnover = null, $format = false) | public function getAmountToBeBilledByTurnover(float $turnover = null, $format = false) | ||||
{ | { | ||||
$amountToBeBilled = 0; | $amountToBeBilled = 0; |
interface UtilsInterface | interface UtilsInterface | ||||
{ | { | ||||
} | |||||
} |
"justcoded/yii2-event-listener": "*", | "justcoded/yii2-event-listener": "*", | ||||
"ext-pdo": "*", | "ext-pdo": "*", | ||||
"weluse/yii2-mailjet": "^0.2.0", | "weluse/yii2-mailjet": "^0.2.0", | ||||
"ext-json": "*" | |||||
"ext-json": "*", | |||||
"ext-curl": "*" | |||||
}, | }, | ||||
"require-dev": { | "require-dev": { | ||||
"yiisoft/yii2-codeception": "*", | "yiisoft/yii2-codeception": "*", |
<?php | |||||
use yii\db\Migration; | |||||
use yii\db\Schema; | |||||
/** | |||||
* Class m230905_091112_add_columns_dolibarr | |||||
*/ | |||||
class m230905_091112_add_columns_dolibarr extends Migration | |||||
{ | |||||
/** | |||||
* {@inheritdoc} | |||||
*/ | |||||
public function safeUp() | |||||
{ | |||||
$this->addColumn('producer', 'dolibarr_socid', Schema::TYPE_INTEGER); | |||||
$this->addColumn('producer', 'dolibarr_product_id', Schema::TYPE_INTEGER); | |||||
$this->addColumn('producer_price_range', 'dolibarr_product_id', Schema::TYPE_INTEGER); | |||||
} | |||||
/** | |||||
* {@inheritdoc} | |||||
*/ | |||||
public function safeDown() | |||||
{ | |||||
$this->dropColumn('producer', 'dolibarr_socid'); | |||||
$this->dropColumn('producer', 'dolibarr_product_id'); | |||||
$this->dropColumn('producer_price_range', 'dolibarr_product_id'); | |||||
} | |||||
} |