@@ -170,6 +170,21 @@ class ProducerAdminController extends BackendController | |||
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) | |||
{ | |||
$producerManager = $this->getProducerManager(); | |||
@@ -248,7 +263,7 @@ class ProducerAdminController extends BackendController | |||
if (($model = $producerManager->findOneProducerById($id)) !== null) { | |||
return $model; | |||
} else { | |||
throw new NotFoundHttpException('The requested page does not exist.'); | |||
throw new NotFoundHttpException('Producteur introuvable.'); | |||
} | |||
} | |||
@@ -73,6 +73,9 @@ use common\logic\Producer\Producer\Model\Producer; | |||
1 => 'Oui' | |||
]); ?> | |||
<?= $form->field($model, 'option_billing_permanent_transfer_amount') ?> | |||
<?= $form->field($model, 'dolibarr_socid') ?> | |||
<?= $form->field($model, 'dolibarr_product_id') ?> | |||
<div class="form-group"> | |||
<?= Html::submitButton($model->isNewRecord ? 'Ajouter' : 'Modifier', ['class' => 'btn btn-success']) ?> | |||
</div> |
@@ -218,7 +218,7 @@ $this->addButton(['label' => 'Nouveau producteur <span class="glyphicon glyphico | |||
], | |||
[ | |||
'class' => 'yii\grid\ActionColumn', | |||
'template' => '{update} {billing} {alwaysdata}', | |||
'template' => '{update} {dolibarr} {billing} {alwaysdata}', | |||
'headerOptions' => ['class' => 'column-actions'], | |||
'contentOptions' => ['class' => 'column-actions'], | |||
'buttons' => [ | |||
@@ -232,6 +232,16 @@ $this->addButton(['label' => 'Nouveau producteur <span class="glyphicon glyphico | |||
] | |||
); | |||
}, | |||
'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) { | |||
return Html::a( | |||
'<span class="glyphicon glyphicon-euro"></span>', |
@@ -50,6 +50,7 @@ $this->addBreadcrumb('Ajouter') ; | |||
<?= $form->field($model, 'range_begin') ?> | |||
<?= $form->field($model, 'range_end') ?> | |||
<?= $form->field($model, 'price') ?> | |||
<?= $form->field($model, 'dolibarr_product_id') ?> | |||
<div class="form-group"> | |||
<?= Html::submitButton('Ajouter', ['class' => 'btn btn-success']) ?> | |||
</div> |
@@ -39,8 +39,8 @@ termes. | |||
use yii\helpers\Html; | |||
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') ; | |||
?> | |||
@@ -50,6 +50,7 @@ $this->addBreadcrumb('Éditer') ; | |||
<?= $form->field($model, 'range_begin') ?> | |||
<?= $form->field($model, 'range_end') ?> | |||
<?= $form->field($model, 'price') ?> | |||
<?= $form->field($model, 'dolibarr_product_id') ?> | |||
<div class="form-group"> | |||
<?= Html::submitButton('Ajouter', ['class' => 'btn btn-success']) ?> | |||
</div> |
@@ -0,0 +1,62 @@ | |||
<?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; | |||
} | |||
} |
@@ -0,0 +1,51 @@ | |||
<?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); | |||
} | |||
} |
@@ -37,6 +37,7 @@ | |||
*/ | |||
use common\components\BusinessLogic; | |||
use common\components\DolibarrApi; | |||
use common\logic\Distribution\Distribution\Model\Distribution; | |||
use common\logic\Document\DeliveryNote\Model\DeliveryNote; | |||
use common\logic\Ticket\Ticket\Model\Ticket; | |||
@@ -129,6 +130,12 @@ return [ | |||
'enableStrictParsing' => false, | |||
'rules' => [], | |||
], | |||
'dolibarrApi' => function() { | |||
return new DolibarrApi( | |||
Yii::$app->parameterBag->get('dolibarrApiUrl'), | |||
['DOLAPIKEY', \Yii::$app->parameterBag->get('dolibarrApiKey')] | |||
); | |||
}, | |||
'logic' => function () { | |||
return new BusinessLogic(); | |||
}, |
@@ -0,0 +1,8 @@ | |||
<?php | |||
namespace common\logic; | |||
abstract class AbstractUtils extends AbstractService implements UtilsInterface | |||
{ | |||
} |
@@ -151,6 +151,8 @@ class Producer extends ActiveRecordCommon | |||
'option_online_payment_minimum_amount', | |||
'option_document_price_decimals', | |||
'option_billing_reduction_percentage', | |||
'dolibarr_socid', | |||
'dolibarr_product_id' | |||
], | |||
'integer' | |||
], | |||
@@ -415,7 +417,9 @@ class Producer extends ActiveRecordCommon | |||
'option_testimony' => 'Témoignage', | |||
'option_time_saved' => 'Temps gagné / semaine', | |||
'contact_email' => 'Email de contact', | |||
'admin_comment' => 'Commentaire' | |||
'admin_comment' => 'Commentaire', | |||
'dolibarr_socid' => 'Dolibarr : id user', | |||
'dolibarr_product_id' => 'Dolibarr : id produit' | |||
]; | |||
} | |||
@@ -113,6 +113,12 @@ class ProducerRepository extends AbstractRepository | |||
]; | |||
} | |||
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é | |||
*/ |
@@ -0,0 +1,52 @@ | |||
<?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; | |||
} | |||
} |
@@ -4,6 +4,7 @@ namespace common\logic\Producer\Producer\Wrapper; | |||
use common\logic\AbstractContainer; | |||
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\ProducerDefinition; | |||
use common\logic\Producer\Producer\Service\ProducerSolver; | |||
@@ -18,7 +19,8 @@ class ProducerContainer extends AbstractContainer | |||
ProducerSolver::class, | |||
ProducerRepository::class, | |||
ProducerBuilder::class, | |||
ProducerUtils::class | |||
ProducerUtils::class, | |||
DolibarrProducerUtils::class, | |||
]; | |||
} | |||
@@ -4,6 +4,7 @@ namespace common\logic\Producer\Producer\Wrapper; | |||
use common\logic\AbstractManager; | |||
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\ProducerDefinition; | |||
use common\logic\Producer\Producer\Service\ProducerSolver; | |||
@@ -15,6 +16,7 @@ use common\logic\Producer\Producer\Service\ProducerUtils; | |||
* @mixin ProducerRepository | |||
* @mixin ProducerBuilder | |||
* @mixin ProducerUtils | |||
* @mixin DolibarrProducerUtils | |||
*/ | |||
class ProducerManager extends AbstractManager | |||
{ |
@@ -62,6 +62,7 @@ class ProducerPriceRange extends ActiveRecordCommon | |||
{ | |||
return [ | |||
[['range_begin', 'range_end', 'price'], 'double'], | |||
[['dolibarr_product_id'], 'integer'] | |||
]; | |||
} | |||
@@ -75,6 +76,7 @@ class ProducerPriceRange extends ActiveRecordCommon | |||
'range_begin' => 'Début', | |||
'range_end' => 'Fin', | |||
'price' => 'Tarif (HT)', | |||
'dolibarr_product_id' => 'Dolibarr : id produit' | |||
]; | |||
} | |||
} |
@@ -45,6 +45,18 @@ class ProducerPriceRangeRepository extends AbstractRepository | |||
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) | |||
{ | |||
$amountToBeBilled = 0; |
@@ -5,4 +5,4 @@ namespace common\logic; | |||
interface UtilsInterface | |||
{ | |||
} | |||
} |
@@ -35,7 +35,8 @@ | |||
"justcoded/yii2-event-listener": "*", | |||
"ext-pdo": "*", | |||
"weluse/yii2-mailjet": "^0.2.0", | |||
"ext-json": "*" | |||
"ext-json": "*", | |||
"ext-curl": "*" | |||
}, | |||
"require-dev": { | |||
"yiisoft/yii2-codeception": "*", |
@@ -0,0 +1,30 @@ | |||
<?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'); | |||
} | |||
} |