Browse Source

Merge branch 'dev' into feature/tarif

refactoring
Fab 2 years ago
parent
commit
65b3f69b62
32 changed files with 1624 additions and 437 deletions
  1. +8
    -1
      backend/controllers/DistributionController.php
  2. +135
    -1
      backend/controllers/DocumentController.php
  3. +3
    -3
      backend/controllers/ProducerAdminController.php
  4. +163
    -0
      backend/controllers/ProducerPriceRangeAdminController.php
  5. +1
    -0
      backend/controllers/QuotationController.php
  6. +4
    -2
      backend/views/document/_download_product_line.php
  7. +3
    -0
      backend/views/document/_form.php
  8. +20
    -4
      backend/views/document/download.php
  9. +10
    -1
      backend/views/invoice/index.php
  10. +1
    -0
      backend/views/layouts/left.php
  11. +63
    -46
      backend/views/producer-admin/index.php
  12. +59
    -0
      backend/views/producer-price-range-admin/create.php
  13. +94
    -0
      backend/views/producer-price-range-admin/index.php
  14. +59
    -0
      backend/views/producer-price-range-admin/update.php
  15. +32
    -2
      backend/views/producer/update.php
  16. +5
    -0
      backend/views/user/_form.php
  17. +1
    -0
      backend/web/.gitignore
  18. +51
    -36
      backend/web/js/vuejs/producer-update.js
  19. +1
    -1
      common/helpers/CSV.php
  20. +21
    -2
      common/helpers/Price.php
  21. +395
    -302
      common/models/Document.php
  22. +74
    -28
      common/models/Order.php
  23. +143
    -6
      common/models/Producer.php
  24. +95
    -0
      common/models/ProducerPriceRange.php
  25. +9
    -0
      common/models/ProductOrder.php
  26. +12
    -0
      common/models/TaxRate.php
  27. +3
    -2
      common/models/User.php
  28. +31
    -0
      console/migrations/m220914_091112_add_table_producer_price_range.php
  29. +27
    -0
      console/migrations/m220915_072309_producer_add_option_billing_frequency.php
  30. +29
    -0
      console/migrations/m220915_083713_producer_add_options_billing.php
  31. +44
    -0
      console/migrations/m220916_062206_add_column_document_tax_calculation_method.php
  32. +28
    -0
      console/migrations/m220919_084020_add_fields_export_evoliz.php

+ 8
- 1
backend/controllers/DistributionController.php View File



if (!$deliveryNote) { if (!$deliveryNote) {
$deliveryNote = new DeliveryNote(); $deliveryNote = new DeliveryNote();
$deliveryNote->initTaxCalculationMethod();
$deliveryNote->id_producer = GlobalParam::getCurrentProducerId(); $deliveryNote->id_producer = GlobalParam::getCurrentProducerId();
$deliveryNote->id_user = $order->id_user; $deliveryNote->id_user = $order->id_user;
$deliveryNote->name = 'Bon de livraison ' . $order->getUsername() . ' (' . date( $deliveryNote->name = 'Bon de livraison ' . $order->getUsername() . ' (' . date(
// génération du BL // génération du BL
if (!$deliveryNote) { if (!$deliveryNote) {
$deliveryNote = new DeliveryNote; $deliveryNote = new DeliveryNote;
$deliveryNote->initTaxCalculationMethod();
$deliveryNote->name = 'Bon de livraison ' . $firstOrder->pointSale->name . ' (' . date( $deliveryNote->name = 'Bon de livraison ' . $firstOrder->pointSale->name . ' (' . date(
'd/m/Y', 'd/m/Y',
strtotime( strtotime(
$user = User::searchOne([ $user = User::searchOne([
'id' => $deliveryNote->id_user 'id' => $deliveryNote->id_user
]); ]);
$userProducer = UserProducer::searchOne([
'id_user' => $deliveryNote->id_user,
'id_producer' => GlobalParam::getCurrentProducerId(
)
]);
} else { } else {
$user = new User; $user = new User;
$user->type = User::TYPE_LEGAL_PERSON; $user->type = User::TYPE_LEGAL_PERSON;
$deliveryNote->address = $user->getFullAddress(); $deliveryNote->address = $user->getFullAddress();
$deliveryNote->save(); $deliveryNote->save();
} else { } else {
// réinitialisation des order.id_delivery_order
// réinitialisation des order.id_delivery_note
Order::updateAll([ Order::updateAll([
'id_delivery_note' => null 'id_delivery_note' => null
], [ ], [

+ 135
- 1
backend/controllers/DocumentController.php View File

namespace backend\controllers; namespace backend\controllers;


use common\models\DeliveryNote; use common\models\DeliveryNote;
use common\models\Invoice;
use common\models\PointSale; use common\models\PointSale;
use common\models\Product; use common\models\Product;
use common\models\Quotation;
use common\models\User; use common\models\User;
use common\models\Document; use common\models\Document;
use common\helpers\GlobalParam; use common\helpers\GlobalParam;
use common\models\Order; use common\models\Order;
use common\models\UserProducer; use common\models\UserProducer;
use kartik\mpdf\Pdf;
use yii\base\UserException; use yii\base\UserException;
use yii; use yii;


]; ];
} }


public function actionGeneratePdfValidatedDocuments()
{
set_time_limit(0);

$validatedDocumentsArray = array_merge(
Quotation::find()->where(['status' => Document::STATUS_VALID])->all(),
DeliveryNote::find()->where(['status' => Document::STATUS_VALID])->all(),
Invoice::find()->where(['status' => Document::STATUS_VALID])->all()
);

foreach($validatedDocumentsArray as $document) {
$document->generatePdf(Pdf::DEST_FILE);
}
}

public function actionCreate() public function actionCreate()
{ {
$class = $this->getClass(); $class = $this->getClass();
$model = new $class(); $model = new $class();
$model->initTaxCalculationMethod();


if ($model->load(Yii::$app->request->post())) { if ($model->load(Yii::$app->request->post())) {
$model->id_producer = GlobalParam::getCurrentProducerId(); $model->id_producer = GlobalParam::getCurrentProducerId();
$this->redirect([$this->getControllerUrl() . '/index']); $this->redirect([$this->getControllerUrl() . '/index']);
} }


public function actionExportCsvEvoliz($id)
{
$datas = [];
$document = $this->findModel($id);

// données
$datas[] = [
'N° facture externe *',
'Date facture *',
'Client',
'Code client *',
'Total TVA',
'Total HT',
'Total TTC',
'Total réglé',
'Etat',
'Date Etat',
'Date de création',
'Objet',
'Date d\'échéance',
'Date d\'exécution',
'Taux de pénalité',
'Frais de recouvrement',
'Taux d\'escompte',
'Conditions de règlement *',
'Mode de paiement',
'Remise globale',
'Acompte',
'Nombre de relance',
'Commentaires',
'N° facture',
'Annulé',
'Catalogue',
'Réf.',
'Désignation *',
'Qté *',
'Unité',
'PU HT *',
'Remise',
'TVA',
'Total TVA',
'Total HT',
'Créateur',
];

foreach($document->getProductsOrders() as $productOrderArray) {
foreach($productOrderArray as $productOrder) {

$price = $productOrder->getPrice() ;
if($document->isInvoicePrice() && $productOrder->getInvoicePrice()) {
$price = $productOrder->getInvoicePrice() ;
}

$datas[] = [
$document->reference, // N° facture externe *
date('d/m/Y', strtotime($document->date)), // Date facture *
'', // Client
$document->user->evoliz_code, // Code client *
'', // Total TVA
'', // Total HT
'', // Total TTC
'', // Total réglé
'', // Etat
'', // Date Etat
'', // Date de création
$document->name, // Objet
'', // Date d'échéance
'', // Date d'exécution
'', // Taux de pénalité
'', // Frais de recouvrement
'', // Taux d\'escompte
'A réception', // Conditions de règlement *
'', // Mode de paiement
'', // Remise globale
'', // Acompte
'', // Nombre de relance
'', // Commentaires
'', // N° facture
'', // Annulé
'Non', // Catalogue
'', // Réf.
$productOrder->product->name, // Désignation *
$productOrder->quantity, // Qté *
'', // Product::strUnit($productOrder->unit, 'wording'), // Unité
$price, // PU HT *
'', // Remise
$productOrder->taxRate->value * 100, // TVA
'', // Total TVA
'', // Total HT
'', // Créateur
];
}
}

// nom fichier
$reference = $document->id;
if($document->reference && strlen($document->reference)) {
$reference = $document->reference;
}

// status
$status = '';
if($document->isStatusDraft()) {
$status = 'brouillon_';
}

CSV::downloadSendHeaders(strtolower($this->getDocumentType()).'_' . $status . $reference . '.csv');
echo CSV::array2csv($datas);
die();
}

public function actionDownload($id) public function actionDownload($id)
{ {
$document = $this->findModel($id); $document = $this->findModel($id);
return $document->generatePdf(Pdf::DEST_BROWSER);
return $document->downloadPdf();
} }


public function actionSend($id) public function actionSend($id)
if ($document) { if ($document) {
$document->changeStatus(Document::STATUS_VALID); $document->changeStatus(Document::STATUS_VALID);
$document->save(); $document->save();

// génération PDF
$document->generatePdf(Pdf::DEST_FILE);

Yii::$app->getSession()->setFlash('success', $this->getFlashMessage('validate', $document)); Yii::$app->getSession()->setFlash('success', $this->getFlashMessage('validate', $document));
return $this->redirect([$this->getControllerUrl() . '/index']); return $this->redirect([$this->getControllerUrl() . '/index']);
} }

+ 3
- 3
backend/controllers/ProducerAdminController.php View File



$producersArray = Producer::find()->where('active = 1')->all(); $producersArray = Producer::find()->where('active = 1')->all();


$sumFreePrice = 0 ;
$sumPrices = 0;
foreach($producersArray as $producer) { foreach($producersArray as $producer) {
$sumFreePrice += $producer->free_price ;
$sumPrices += $producer->getAmountBilledLastMonth();
} }


return $this->render('index', [ return $this->render('index', [
'dataProviderProducer' => $dataProviderProducer, 'dataProviderProducer' => $dataProviderProducer,
'sumFreePrice' => $sumFreePrice
'sumPrices' => $sumPrices
]); ]);
} }

+ 163
- 0
backend/controllers/ProducerPriceRangeAdminController.php View File

<?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 common\models\ProducerPriceRange;
use Yii;
use common\models\User;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\filters\AccessControl;
use yii\data\ActiveDataProvider;

/**
* TaxRateAdminController implements the CRUD actions for TaxRate model.
*/
class ProducerPriceRangeAdminController extends BackendController
{

public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
],
],
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'allow' => true,
'roles' => ['@'],
'matchCallback' => function ($rule, $action) {
return User::getCurrentStatus() == USER::STATUS_ADMIN;
}
]
],
],
];
}

/**
* Liste les tranches de prix.
*
* @return mixed
*/
public function actionIndex()
{
$dataProvider = new ActiveDataProvider([
'query' => ProducerPriceRange::find()->orderBy('range_begin ASC')
]);

return $this->render('index', [
'dataProviderProducerPriceRange' => $dataProvider,
]);
}

/**
* Crée une tranche de prix.
*
* @return mixed
*/
public function actionCreate()
{
$model = new ProducerPriceRange();

if ($model->load(Yii::$app->request->post()) && $model->save()) {
Yii::$app->getSession()->setFlash('success', 'Tranche de prix créée.');
return $this->redirect(['index']);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}

/**
* Édition d'une tranche de prix.
*
* @return mixed
*/
public function actionUpdate($id)
{
$model = $this->findModel($id);

if ($model->load(Yii::$app->request->post()) && $model->save()) {
Yii::$app->getSession()->setFlash('success', 'Tranche de prix éditée.');
return $this->redirect(['index']);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}

/**
* Supprime une tranche de prix.
*
* @param integer $id
*/
public function actionDelete($id)
{
$producerPriceRange = ProducerPriceRange::searchOne([
'id' => $id
]) ;
$producerPriceRange->delete();

Yii::$app->getSession()->setFlash('success', 'Tranche de prix supprimée.');
return $this->redirect(['producer-price-range-admin/index']);
}

/**
* Finds the Developpement model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* @param integer $id
* @return ProducerPriceRange the loaded model
* @throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = ProducerPriceRange::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
}

+ 1
- 0
backend/controllers/QuotationController.php View File

if($quotation->isStatusValid()) { if($quotation->isStatusValid()) {


$invoice = new Invoice ; $invoice = new Invoice ;
$invoice->initTaxCalculationMethod();
$invoice->id_producer = GlobalParam::getCurrentProducerId(); $invoice->id_producer = GlobalParam::getCurrentProducerId();
$invoice->id_user = $quotation->id_user ; $invoice->id_user = $quotation->id_user ;
$invoice->address = $quotation->address ; $invoice->address = $quotation->address ;

+ 4
- 2
backend/views/document/_download_product_line.php View File

<tr class="<?php if(isset($displayOrders) && $displayOrders): ?>order<?php endif; ?>"> <tr class="<?php if(isset($displayOrders) && $displayOrders): ?>order<?php endif; ?>">
<td class="align-left"> <td class="align-left">
<?= Html::encode($productOrder->product->name) ?>
<?php if($productOrder->product): ?>
<?= Html::encode($productOrder->product->name) ?>
<?php endif; ?>
<?php if($productOrder->unit == 'piece' && isset($productOrder->product->weight) && $productOrder->product->weight): ?> <?php if($productOrder->unit == 'piece' && isset($productOrder->product->weight) && $productOrder->product->weight): ?>
<span class="weight"> / <?= $productOrder->product->weight ?> g</span> <span class="weight"> / <?= $productOrder->product->weight ?> g</span>
<?php endif; ?> <?php endif; ?>
<?php if(strlen($productOrder->product->description) && $displayProductDescription): ?>
<?php if($productOrder->product && strlen($productOrder->product->description) && $displayProductDescription): ?>
<br /><small><?= Html::encode($productOrder->product->description) ?></small> <br /><small><?= Html::encode($productOrder->product->description) ?></small>
<?php endif; ?> <?php endif; ?>
</td> </td>

+ 3
- 0
backend/views/document/_form.php View File

<span class="info-box-icon bg-blue"><i class="fa fa-download"></i></span> <span class="info-box-icon bg-blue"><i class="fa fa-download"></i></span>
<div class="info-box-content"> <div class="info-box-content">
<a href="<?= Yii::$app->urlManager->createUrl([Yii::$app->controller->getControllerUrl().'/download', 'id' => $model->id]) ?>" class="btn btn-default"><span class="glyphicon glyphicon-download-alt"></span> Télécharger (PDF)</a> <a href="<?= Yii::$app->urlManager->createUrl([Yii::$app->controller->getControllerUrl().'/download', 'id' => $model->id]) ?>" class="btn btn-default"><span class="glyphicon glyphicon-download-alt"></span> Télécharger (PDF)</a>
<?php if($model->getClass() == 'Invoice' && Producer::getConfig('option_export_evoliz')): ?>
<a href="<?= Yii::$app->urlManager->createUrl([Yii::$app->controller->getControllerUrl().'/export-csv-evoliz', 'id' => $model->id]) ?>" class="btn btn-default"><span class="glyphicon glyphicon-save-file"></span> Export Evoliz (CSV)</a>
<?php endif; ?>
</div> </div>
</div> </div>
<div v-if="document.status == 'draft'" id="" class="info-box"> <div v-if="document.status == 'draft'" id="" class="info-box">

+ 20
- 4
backend/views/document/download.php View File

<tr> <tr>
<td> <td>
<strong><?= Html::encode($order->getUsername()) ; ?></strong> <strong><?= Html::encode($order->getUsername()) ; ?></strong>
le <?= date('d/m/Y', strtotime($order->distribution->date)) ?>
<?php if($order->distribution): ?>
le <?= date('d/m/Y', strtotime($order->distribution->date)) ?>
<?php endif; ?>
</td> </td>
<?php if($displayPrices): ?> <?php if($displayPrices): ?>
<td class="align-center"></td> <td class="align-center"></td>
<?= Price::format($document->getAmount($typeAmount)); ?> <?= Price::format($document->getAmount($typeAmount)); ?>
</td> </td>
</tr> </tr>
<tr>

<?php
$taxRateArray = TaxRate::getTaxRateArray();
foreach($document->getTotalVatArray($typeAmount) as $idTaxRate => $totalVat): ?>
<tr>
<td class="align-right" colspan="5"><strong>TVA <?= $taxRateArray[$idTaxRate]->value * 100 ?> %</strong></td>
<td class="align-center">
<?= Price::format($totalVat); ?>
</td>
</tr>
<?php endforeach; ?>

<!--<tr>
<td class="align-right" colspan="5"><strong>TVA</strong></td> <td class="align-right" colspan="5"><strong>TVA</strong></td>
<td class="align-center"><?= Price::format($document->getAmountWithTax($typeAmount) - $document->getAmount($typeAmount)) ?></td>
</tr>
<td class="align-center">
<?= Price::format($document->getAmountWithTax($typeAmount) - $document->getAmount($typeAmount)) ?>
</td>
</tr>-->
<tr> <tr>
<td class="align-right" colspan="5"><strong>Total TTC</strong></td> <td class="align-right" colspan="5"><strong>Total TTC</strong></td>
<td class="align-center"><?= Price::format($document->getAmountWithTax($typeAmount)) ?></td> <td class="align-center"><?= Price::format($document->getAmountWithTax($typeAmount)) ?></td>

+ 10
- 1
backend/views/invoice/index.php View File

], ],
[ [
'class' => 'yii\grid\ActionColumn', 'class' => 'yii\grid\ActionColumn',
'template' => '{validate} {update} {delete} {send} {download}',
'template' => '{validate} {update} {delete} {send} {download} {export-csv-evoliz}',
'headerOptions' => ['class' => 'column-actions'], 'headerOptions' => ['class' => 'column-actions'],
'contentOptions' => ['class' => 'column-actions'], 'contentOptions' => ['class' => 'column-actions'],
'buttons' => [ 'buttons' => [
'title' => 'Télécharger', 'class' => 'btn btn-default' 'title' => 'Télécharger', 'class' => 'btn btn-default'
]); ]);
}, },
'export-csv-evoliz' => function($url, $model) {
if(Producer::getConfig('option_export_evoliz')) {
return Html::a('<span class="glyphicon glyphicon-save-file"></span> Evoliz', $url, [
'title' => 'Export CSV Evoliz', 'class' => 'btn btn-default'
]);
}

return '';
},
'update' => function ($url, $model) { 'update' => function ($url, $model) {
return Html::a('<span class="glyphicon glyphicon-pencil"></span>', $url, [ return Html::a('<span class="glyphicon glyphicon-pencil"></span>', $url, [
'title' => 'Modifier', 'class' => 'btn btn-default' 'title' => 'Modifier', 'class' => 'btn btn-default'

+ 1
- 0
backend/views/layouts/left.php View File

['label' => 'Administration', 'options' => ['class' => 'header'], 'visible' => User::isCurrentAdmin()], ['label' => 'Administration', 'options' => ['class' => 'header'], 'visible' => User::isCurrentAdmin()],
['label' => 'Producteurs','icon' => 'th-list','url' => ['/producer-admin/index'], 'visible' => User::isCurrentAdmin()], ['label' => 'Producteurs','icon' => 'th-list','url' => ['/producer-admin/index'], 'visible' => User::isCurrentAdmin()],
['label' => 'Tranches de prix','icon' => 'eur','url' => ['/producer-price-range-admin/index'], 'visible' => User::isCurrentAdmin()],
['label' => 'Taxes','icon' => 'eur','url' => ['/tax-rate-admin/index'], 'visible' => User::isCurrentAdmin()], ['label' => 'Taxes','icon' => 'eur','url' => ['/tax-rate-admin/index'], 'visible' => User::isCurrentAdmin()],
['label' => 'Communiquer','icon' => 'bullhorn','url' => ['/communicate-admin/index'], 'visible' => User::isCurrentAdmin()], ['label' => 'Communiquer','icon' => 'bullhorn','url' => ['/communicate-admin/index'], 'visible' => User::isCurrentAdmin()],

+ 63
- 46
backend/views/producer-admin/index.php View File

?> ?>


<div class="alert alert-info"> <div class="alert alert-info">
Abonnements mensuels : <strong><?= $sumFreePrice ?> € HT</strong>
Facturé le mois dernier : <strong><?= $sumPrices ?> €</strong><br />
</div> </div>


<?= GridView::widget([ <?= GridView::widget([
'dataProvider' => $dataProviderProducer, 'dataProvider' => $dataProviderProducer,
'columns' => [ 'columns' => [
'name',
[ [
'attribute' => 'active',
'format' => 'raw',
'value' => function($model) {
$html = '' ;
if($model->active) {
$html .= '<span class="label label-success">En ligne</span>' ;
}
else {
$html .= '<span class="label label-danger">Hors-ligne</span>' ;
}

if(strlen($model->code))
{
$html .= ' <span class="glyphicon glyphicon-lock" data-toggle="tooltip" data-placement="bottom" data-original-title="'.Html::encode($model->code).'"></span>' ;
}

return $html ;
}
],
'name',
/*[
'attribute' => 'date_creation', 'attribute' => 'date_creation',
'format' => 'raw', 'format' => 'raw',
'value' => function($model) { 'value' => function($model) {
return date('d/m/Y', strtotime($model->date_creation)) ; return date('d/m/Y', strtotime($model->date_creation)) ;
} }
],
[
],*/
/*[
'attribute' => 'Lieu', 'attribute' => 'Lieu',
'format' => 'raw', 'format' => 'raw',
'value' => function($model) { 'value' => function($model) {
return Html::encode($model->city.' ('.$model->postcode.')') ; return Html::encode($model->city.' ('.$model->postcode.')') ;
} }
],
[
],*/
/*[
'attribute' => 'Utilisateurs', 'attribute' => 'Utilisateurs',
'format' => 'raw', 'format' => 'raw',
'value' => function($model) { 'value' => function($model) {
} }
} }
],
],*/
[ [
'attribute' => 'Contact', 'attribute' => 'Contact',
'format' => 'raw', 'format' => 'raw',
} }
], ],
[ [
'attribute' => 'active',
'attribute' => 'Prix libre',
'label' => 'Prix libre',
'format' => 'raw', 'format' => 'raw',
'value' => function($model) { 'value' => function($model) {
$html = '' ;
if($model->active) {
$html .= '<span class="label label-success">En ligne</span>' ;
if(is_null($model->free_price)) {
return '' ;
} }
else { else {
$html .= '<span class="label label-danger">Hors-ligne</span>' ;
}
if(strlen($model->code))
{
$html .= ' <span class="glyphicon glyphicon-lock" data-toggle="tooltip" data-placement="bottom" data-original-title="'.Html::encode($model->code).'"></span>' ;
$str = '';
if($model->isBillingTypeFreePrice()) {
$str .= '<strong>';
}

$str .= $model->getFreePrice();

if($model->isBillingTypeFreePrice()) {
$str .= '</strong>';
}

return $str;
} }
return $html ;
} }
], ],
[ [
'attribute' => 'Prix libre',
'label' => 'Prix libre',
'attribute' => 'À facturer / chiffre d\'affaire',
'label' => 'À facturer / chiffre d\'affaire',
'format' => 'raw', 'format' => 'raw',
'value' => function($model) { 'value' => function($model) {
if(is_null($model->free_price)) {
return '' ;
if($model->isBillingFrequencyMonthly()) {
return $model->getSummaryAmountsToBeBilled('Mois dernier', 1);
} }
else {
return $model->getFreePrice() ;
elseif($model->isBillingFrequencyQuarterly()) {
return $model->getSummaryAmountsToBeBilled('3 derniers mois', 3);
}
elseif($model->isBillingFrequencyBiannual()) {
return $model->getSummaryAmountsToBeBilled('6 derniers mois', 6);
} }
} }
], ],
[ [
'label' => 'Dons (mois précédent)',
'attribute' => 'Facturation',
'label' => 'Détails facturation',
'format' => 'raw', 'format' => 'raw',
'value' => function($model) { 'value' => function($model) {
$productGift = Product::getProductGift() ;

$res = Yii::$app->db->createCommand("SELECT SUM(product_order.price * product_order.quantity) AS total
FROM `order`, product_order, distribution
WHERE distribution.id_producer = :id_producer
AND `order`.id_distribution = distribution.id
AND `order`.id = product_order.id_order
AND distribution.date >= :date_start
AND distribution.date <= :date_end
AND product_order.id_product = :id_product_gift
")
->bindValue(':id_producer', $model->id)
->bindValue(':date_start', date('Y-m-01', strtotime("-1 month")))
->bindValue(':date_end', date('Y-m-31', strtotime("-1 month")))
->bindValue(':id_product_gift', $productGift->id)
->queryOne();

return Price::format($res['total']) ;
$str = '';
$str .= '- '.Producer::$billingTypeArray[$model->option_billing_type].'<br />';
$str .= '- '.Producer::$billingFrequencyArray[$model->option_billing_frequency];


if($model->option_billing_reduction) {
$str .= '<br />- <u>Avec réduction</u>';
}

return $str;
} }
],
]
], ],
]); ?> ]); ?>

+ 59
- 0
backend/views/producer-price-range-admin/create.php View File

<?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.
*/

use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\helpers\ArrayHelper ;
use common\models\Producer ;

$this->setTitle('Ajouter une tranche de prix') ;
$this->addBreadcrumb(['label' => 'tranche de prix', 'url' => ['index']]) ;
$this->addBreadcrumb('Ajouter') ;

?>

<div class="producer-price-range-create">
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'range_begin') ?>
<?= $form->field($model, 'range_end') ?>
<?= $form->field($model, 'price') ?>
<div class="form-group">
<?= Html::submitButton('Ajouter', ['class' => 'btn btn-success']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>

+ 94
- 0
backend/views/producer-price-range-admin/index.php View File

<?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.
*/

use yii\helpers\Html;
use yii\grid\GridView;
use common\models\User;
use common\models\Producer;
use common\models\Distribution;

$this->setTitle('Tranches de prix');
$this->addBreadcrumb($this->getTitle());
$this->addButton(['label' => 'Nouvelle tranche de prix <span class="glyphicon glyphicon-plus"></span>', 'url' => 'producer-price-range-admin/create', 'class' => 'btn btn-primary']);

?>

<?= GridView::widget([
'dataProvider' => $dataProviderProducerPriceRange,
'columns' => [
[
'attribute' => 'range_begin',
'value' => function ($model) {
return Price::format($model->range_begin);
}
],
[
'attribute' => 'range_end',
'value' => function ($model) {
if($model->range_end) {
return Price::format($model->range_end);
}
return '';
}
],
[
'attribute' => 'price',
'value' => function ($model) {
return Price::format($model->price);
}
],
[
'class' => 'yii\grid\ActionColumn',
'template' => '{update} {delete}',
'headerOptions' => ['class' => 'column-actions'],
'contentOptions' => ['class' => 'column-actions'],
'buttons' => [
'update' => function ($url, $model) {
return Html::a('<span class="glyphicon glyphicon-pencil"></span>', $url, [
'title' => Yii::t('app', 'Modifier'), 'class' => 'btn btn-default'
]);
},
'delete' => function ($url, $model) {
return Html::a('<span class="glyphicon glyphicon-trash"></span>', $url, [
'title' => Yii::t('app', 'Supprimer'), 'class' => 'btn btn-default'
]);
}
],
],
],
]); ?>

+ 59
- 0
backend/views/producer-price-range-admin/update.php View File

<?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.
*/

use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\helpers\ArrayHelper ;
use common\models\Producer ;

$this->setTitle('Éditer une taxe') ;
$this->addBreadcrumb(['label' => 'taxe', 'url' => ['index']]) ;
$this->addBreadcrumb('Éditer') ;

?>

<div class="tax-create">
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'range_begin') ?>
<?= $form->field($model, 'range_end') ?>
<?= $form->field($model, 'price') ?>
<div class="form-group">
<?= Html::submitButton('Ajouter', ['class' => 'btn btn-success']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>

+ 32
- 2
backend/views/producer/update.php View File



?> ?>


<script>
var appInitValues = {
isAdmin: <?= (int) User::isCurrentAdmin() ?>
};
</script>

<div class="user-update" id="app-producer-update"> <div class="user-update" id="app-producer-update">
<div id="nav-params"> <div id="nav-params">
<button v-for="section in sectionsArray" :class="'btn '+((currentSection == section.name) ? 'btn-primary' : 'btn-default')" @click="changeSection(section)">
<button v-for="section in sectionsArray" v-if="!section.isAdminSection || (section.isAdminSection && isAdmin)" :class="'btn '+((currentSection == section.name) ? 'btn-primary' : 'btn-default')" @click="changeSection(section)">
{{ section.nameDisplay }} {{ section.nameDisplay }}
<span class="glyphicon glyphicon-triangle-bottom"></span> <span class="glyphicon glyphicon-triangle-bottom"></span>
</button> </button>
<?= $form->field($model, 'id_tax_rate_default') <?= $form->field($model, 'id_tax_rate_default')
->dropDownList(ArrayHelper::map(TaxRate::find()->all(), 'id', function($model) { return $model->name; })) ->dropDownList(ArrayHelper::map(TaxRate::find()->all(), 'id', function($model) { return $model->name; }))
->label('TVA à appliquer par défaut'); ?> ->label('TVA à appliquer par défaut'); ?>
<?= $form->field($model, 'option_tax_calculation_method')
->dropDownList(Document::$taxCalculationMethodArray); ?>
<?= $form->field($model, 'option_export_evoliz')->dropDownList([
0 => 'Non',
1 => 'Oui'
]) ; ?>
<?= $form->field($model, 'document_quotation_prefix') ; ?> <?= $form->field($model, 'document_quotation_prefix') ; ?>
<?= $form->field($model, 'document_quotation_first_reference') ; ?> <?= $form->field($model, 'document_quotation_first_reference') ; ?>
<?= $form->field($model, 'document_quotation_duration') ; ?> <?= $form->field($model, 'document_quotation_duration') ; ?>
->textarea(['rows' => 15]) ?> ->textarea(['rows' => 15]) ?>
</div> </div>
</div> </div>

<?php if(User::isCurrentAdmin()): ?>
<div v-show="currentSection == 'administration'" class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Administration</h3>
</div>
<div class="panel-body">
<?= $form->field($model, 'option_billing_type')
->dropDownList(Producer::getBillingTypePopulateDropdown()); ?>
<?= $form->field($model, 'option_billing_frequency')
->dropDownList(Producer::getBillingFrequencyPopulateDropdown()); ?>
<?= $form->field($model, 'option_billing_reduction')
->dropDownList([
0 => 'Non',
1 => 'Oui'
]); ?>
</div>
</div>
<?php endif; ?>
<div class="form-group"> <div class="form-group">
<?= Html::submitButton('Mettre à jour', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?> <?= Html::submitButton('Mettre à jour', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>

+ 5
- 0
backend/views/user/_form.php View File

<?= $form->field($model, 'phone')->textInput() ?> <?= $form->field($model, 'phone')->textInput() ?>
<?= $form->field($model, 'email')->textInput() ?> <?= $form->field($model, 'email')->textInput() ?>
<?= $form->field($model, 'address')->textarea() ?> <?= $form->field($model, 'address')->textarea() ?>

<?php if(Producer::getConfig('option_export_evoliz')): ?>
<?= $form->field($model, 'evoliz_code')->textInput() ?>
<?php endif; ?>

<?= $form->field($model, 'points_sale')->checkboxlist( <?= $form->field($model, 'points_sale')->checkboxlist(
ArrayHelper::map($pointsSaleArray, 'id', function ($pointSale) use ($model) { ArrayHelper::map($pointsSaleArray, 'id', function ($pointSale) use ($model) {
$commentUserPointSale = isset($pointSale->userPointSale[0]) ? $pointSale->userPointSale[0]->comment : ''; $commentUserPointSale = isset($pointSale->userPointSale[0]) ? $pointSale->userPointSale[0]->comment : '';

+ 1
- 0
backend/web/.gitignore View File

/index.php /index.php
/index-test.php /index-test.php
/pdf/*

+ 51
- 36
backend/web/js/vuejs/producer-update.js View File



var app = new Vue({ var app = new Vue({
el: '#app-producer-update', el: '#app-producer-update',
data: {
currentSection: 'general',
sectionsArray: [
{
name: 'general',
nameDisplay: 'Général'
},
{
name: 'tableau-bord',
nameDisplay: 'Tableau de bord'
},
{
name: 'prise-commande',
nameDisplay: 'Prise de commande'
},
{
name: 'abonnements',
nameDisplay: 'Abonnements'
},
{
name: 'credit-payment',
nameDisplay: 'Crédit'
},
{
name: 'infos',
nameDisplay: 'Informations légales'
},
{
name: 'logiciels-caisse',
nameDisplay: 'Logiciels de caisse'
},
{
name: 'facturation',
nameDisplay: 'Facturation'
}
]
data() {
return Object.assign({
currentSection: 'general',
sectionsArray: [
{
name: 'general',
nameDisplay: 'Général',
isAdminSection: 0
},
{
name: 'tableau-bord',
nameDisplay: 'Tableau de bord',
isAdminSection: 0
},
{
name: 'prise-commande',
nameDisplay: 'Prise de commande',
isAdminSection: 0
},
{
name: 'abonnements',
nameDisplay: 'Abonnements',
isAdminSection: 0
},
{
name: 'credit-payment',
nameDisplay: 'Crédit',
isAdminSection: 0
},
{
name: 'infos',
nameDisplay: 'Informations légales',
isAdminSection: 0
},
{
name: 'logiciels-caisse',
nameDisplay: 'Logiciels de caisse',
isAdminSection: 0
},
{
name: 'facturation',
nameDisplay: 'Facturation',
isAdminSection: 0
},
{
name: 'administration',
nameDisplay: 'Administration',
isAdminSection: 1
}
]
}, window.appInitValues);
}, },
methods: { methods: {
changeSection: function(section) { changeSection: function(section) {

+ 1
- 1
common/helpers/CSV.php View File

// clés // clés
//fputcsv($df, array_keys(reset($array))); //fputcsv($df, array_keys(reset($array)));
foreach ($array as $row) { foreach ($array as $row) {
fputcsv($df, $row);
fputcsv($df, $row, ";");
} }
fclose($df); fclose($df);
return ob_get_clean(); return ob_get_clean();

+ 21
- 2
common/helpers/Price.php View File

return self::numberTwoDecimals($number).' €'; return self::numberTwoDecimals($number).' €';
} }


public static function round($number)
{
return round($number, 2, PHP_ROUND_HALF_UP);
}

public static function getPrice($priceWithTax, $taxRate) public static function getPrice($priceWithTax, $taxRate)
{ {
return floatval($priceWithTax) / ($taxRate + 1); return floatval($priceWithTax) / ($taxRate + 1);
} }


public static function getPriceWithTax($priceWithoutTax, $taxRate)
public static function getPriceWithTax($priceWithoutTax, $taxRate, $taxCalculationMethod = Document::TAX_CALCULATION_METHOD_DEFAULT)
{ {
return self::numberTwoDecimals(floatval($priceWithoutTax) * ($taxRate + 1)) ;
$priceWithoutTax = self::round($priceWithoutTax);
$vat = self::getVat($priceWithoutTax, $taxRate, $taxCalculationMethod);

return $priceWithoutTax + $vat;
}

public static function getVat($priceTotalWithoutTax, $taxRate, $taxCalculationMethod = Document::TAX_CALCULATION_METHOD_DEFAULT)
{
$vat = $priceTotalWithoutTax * $taxRate;

if($taxCalculationMethod == Document::TAX_CALCULATION_METHOD_SUM_OF_ROUNDINGS) {
$vat = self::round($vat);
}

return $vat;
} }


public static function numberTwoDecimals($number) public static function numberTwoDecimals($number)

+ 395
- 302
common/models/Document.php View File

namespace common\models; namespace common\models;


use common\helpers\GlobalParam; use common\helpers\GlobalParam;
use kartik\mpdf\Pdf;
use Symfony\Component\Finder\Exception\DirectoryNotFoundException;
use yii\base\ErrorException;


class Document extends ActiveRecordCommon class Document extends ActiveRecordCommon
{ {
const STATUS_DRAFT = 'draft';
const STATUS_VALID = 'valid';

/**
* @inheritdoc
*/
public function rules()
{
return [
[['name', 'id_user'], 'required'],
[['date'], 'safe'],
[['comment', 'address'], 'string'],
[['id_user', 'id_producer'], 'integer'],
[['name', 'reference', 'status'], 'string', 'max' => 255],
[['deliveryNotes'], 'safe']
];
const STATUS_DRAFT = 'draft';
const STATUS_VALID = 'valid';

const TAX_CALCULATION_METHOD_SUM_OF_ROUNDINGS = 'sum-roundings';
const TAX_CALCULATION_METHOD_ROUNDING_OF_THE_SUM = 'rounding-sum';
const TAX_CALCULATION_METHOD_DEFAULT = self::TAX_CALCULATION_METHOD_ROUNDING_OF_THE_SUM;

public static $taxCalculationMethodArray = [
self::TAX_CALCULATION_METHOD_ROUNDING_OF_THE_SUM => 'Arrondi de la somme des lignes',
self::TAX_CALCULATION_METHOD_SUM_OF_ROUNDINGS => 'Somme des arrondis de chaque ligne'
];

/**
* @inheritdoc
*/
public function rules()
{
return [
[['name', 'id_user'], 'required'],
[['date'], 'safe'],
[['comment', 'address', 'tax_calculation_method'], 'string'],
[['id_user', 'id_producer'], 'integer'],
[['name', 'reference', 'status'], 'string', 'max' => 255],
[['deliveryNotes'], 'safe']
];
}

/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'name' => 'Nom',
'reference' => 'Référence',
'date' => 'Date',
'comment' => 'Commentaire',
'id_user' => 'Utilisateur',
'address' => 'Adresse',
'id_producer' => 'Producteur',
'status' => 'Statut',
'tax_calculation_method' => 'Méthode de calcul de la TVA'
];
}

/*
* Relations
*/

public function getUser()
{
return $this->hasOne(User::className(), ['id' => 'id_user']);
}

public function getProducer()
{
return $this->hasOne(Producer::className(), ['id' => 'id_producer']);
}

public function relationOrders($fieldIdDocument)
{
$defaultOptionsSearch = Order::defaultOptionsSearch();

return $this->hasMany(Order::className(), [$fieldIdDocument => 'id'])
->with($defaultOptionsSearch['with'])
->joinWith($defaultOptionsSearch['join_with'])
->orderBy('distribution.date ASC');
}

/*
* Méthodes
*/

public function getAmount($type = Order::AMOUNT_TOTAL, $format = false)
{
return $this->_getAmountGeneric($type, false, $format);
}

public function getAmountWithTax($type = Order::AMOUNT_TOTAL, $format = false)
{
return $this->_getAmountGeneric($type, true, $format);
}

protected function _getAmountGeneric($type = Order::AMOUNT_TOTAL, $withTax = true, $format = false)
{
$amount = 0;
$totalVat = 0;
$ordersArray = $this->orders;

foreach ($ordersArray as $order) {
$order->init($this->tax_calculation_method);
$amount += $order->getAmount($type);
$totalVat += $order->getTotalVat($type);
} }


/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'name' => 'Nom',
'reference' => 'Référence',
'date' => 'Date',
'comment' => 'Commentaire',
'id_user' => 'Utilisateur',
'address' => 'Adresse',
'id_producer' => 'Producteur',
'status' => 'Statut',
];
if ($this->isTaxCalculationMethodRoundingOfTheSum()) {
$totalVat = Price::round($totalVat);
} }


/*
* Relations
*/

public function getUser()
{
return $this->hasOne(User::className(), ['id' => 'id_user']);
}

public function getProducer()
{
return $this->hasOne(Producer::className(), ['id' => 'id_producer']);
if ($withTax) {
$amount += $totalVat;
} }


public function relationOrders($fieldIdDocument)
{
$defaultOptionsSearch = Order::defaultOptionsSearch();

return $this->hasMany(Order::className(), [$fieldIdDocument => 'id'])
->with($defaultOptionsSearch['with'])
->joinWith($defaultOptionsSearch['join_with'])
->orderBy('distribution.date ASC');
if ($format) {
return Price::format($amount);
} else {
return $amount;
} }
}


public function getTotalVatArray($typeTotal)
{
$totalVatArray = [];


/*
* Méthodes
*/
$ordersArray = $this->orders;


public function getAmount($type = Order::AMOUNT_TOTAL, $format = false)
{
return $this->_getAmountGeneric($type, false, $format);
}

public function getAmountWithTax($type = Order::AMOUNT_TOTAL, $format = false)
{
return $this->_getAmountGeneric($type, true, $format);
foreach ($ordersArray as $order) {
$order->init($this->tax_calculation_method);
$fieldNameVat = $order->getFieldNameAmount($typeTotal, 'vat');
foreach ($order->$fieldNameVat as $idTaxRate => $vat) {
if (!isset($totalVatArray[$idTaxRate])) {
$totalVatArray[$idTaxRate] = 0;
}
$totalVatArray[$idTaxRate] += $vat;
}
} }


protected function _getAmountGeneric($type = Order::AMOUNT_TOTAL, $withTax = true, $format = false)
{
$amount = 0;
$ordersArray = $this->orders;
return $totalVatArray;
}


foreach ($ordersArray as $order) {
$order->init();

if ($withTax) {
$amount += $order->getAmountWithTax($type);
}
else {
$amount += $order->getAmount($type);
}
}

if ($format) {
return Price::format($amount);
} else {
return $amount;
}
public function getPointSale()
{
if (isset($this->orders) && isset($this->orders[0])) {
return $this->orders[0]->pointSale;
} else {
return '';
} }
public function getPointSale()
{
if (isset($this->orders) && isset($this->orders[0])) {
return $this->orders[0]->pointSale;
} else {
return '';
}
}

public function getDistribution()
{
if (isset($this->orders) && isset($this->orders[0])) {
return $this->orders[0]->distribution;
} else {
return '';
} }

public function getDistribution()
{
if (isset($this->orders) && isset($this->orders[0])) {
return $this->orders[0]->distribution;
} else {
return '';
}
}

public function getClass()
{
return str_replace('common\models\\', '', get_class($this));
}

public function getType()
{
$class = $this->getClass();

if ($class == 'Invoice') {
$documentType = 'Facture';
} elseif ($class == 'DeliveryNote') {
$documentType = 'Bon de livraison';
} elseif ($class == 'Quotation') {
$documentType = 'Devis';
} }


public function getClass()
{
return str_replace('common\models\\', '', get_class($this));
if (isset($documentType)) {
return $documentType;
} }


public function getType()
{
$class = $this->getClass();

if ($class == 'Invoice') {
$documentType = 'Facture';
} elseif ($class == 'DeliveryNote') {
$documentType = 'Bon de livraison';
} elseif ($class == 'Quotation') {
$documentType = 'Devis';
}
return '';
}


if (isset($documentType)) {
return $documentType;
}
public function isValidClass($typeDocument)
{
return in_array($typeDocument, ['Invoice', 'DeliveryNote', 'Quotation']);
}


return '';
public function generateReference()
{
$class = $this->getClass();
$classLower = strtolower($class);
if ($classLower == 'deliverynote') {
$classLower = 'delivery_note';
} }


public function isValidClass($typeDocument)
{
return in_array($typeDocument, ['Invoice', 'DeliveryNote', 'Quotation']);
$prefix = Producer::getConfig('document_' . $classLower . '_prefix');
$oneDocumentExist = $class::searchOne(['status' => Document::STATUS_VALID], ['orderby' => 'reference DESC']);

if ($oneDocumentExist) {
$reference = $oneDocumentExist->reference;
$pattern = '#([A-Z]+)?([0-9]+)#';
preg_match($pattern, $reference, $matches, PREG_OFFSET_CAPTURE);
$sizeNumReference = strlen($matches[2][0]);
$numReference = ((int)$matches[2][0]) + 1;
$numReference = str_pad($numReference, $sizeNumReference, '0', STR_PAD_LEFT);

return $prefix . $numReference;
} else {
$firstReference = Producer::getConfig('document_' . $classLower . '_first_reference');

if (strlen($firstReference) > 0) {
return $firstReference;
} else {
return $prefix . '00001';
}
} }
}


public function generateReference()
{
$class = $this->getClass();
$classLower = strtolower($class);
if ($classLower == 'deliverynote') {
$classLower = 'delivery_note';
}
public function downloadPdf()
{
$filenameComplete = $this->getFilenameComplete();


$prefix = Producer::getConfig('document_' . $classLower . '_prefix');
$oneDocumentExist = $class::searchOne(['status' => Document::STATUS_VALID] , ['orderby' => 'reference DESC']);

if ($oneDocumentExist) {
$reference = $oneDocumentExist->reference;
$pattern = '#([A-Z]+)?([0-9]+)#';
preg_match($pattern, $reference, $matches, PREG_OFFSET_CAPTURE);
$sizeNumReference = strlen($matches[2][0]);
$numReference = ((int)$matches[2][0]) + 1;
$numReference = str_pad($numReference, $sizeNumReference, '0', STR_PAD_LEFT);

return $prefix . $numReference;
} else {
$firstReference = Producer::getConfig('document_' . $classLower . '_first_reference');

if (strlen($firstReference) > 0) {
return $firstReference;
} else {
return $prefix . '00001';
}
}
if(!file_exists($filenameComplete)) {
$this->generatePdf(Pdf::DEST_FILE);
} }


public function generatePdf($destination)
{
$producer = GlobalParam::getCurrentProducer();
$content = Yii::$app->controller->renderPartial('/document/download', [
'producer' => $producer,
'document' => $this
]);

$contentFooter = '<div id="footer">';
$contentFooter .= '<div class="infos-bottom">' . Html::encode($producer->document_infos_bottom) . '</div>';
if ($this->isStatusValid() || $this->isStatusDraft()) {
$contentFooter .= '<div class="reference-document">';
if ($this->isStatusValid()) {
$contentFooter .= $this->getType() . ' N°' . $this->reference;
}
if ($this->isStatusDraft()) {
$contentFooter .= $this->getType() . ' non validé';
if($this->getType() == 'Facture') {
$contentFooter .= 'e' ;
}
}
$contentFooter .= '</div>';
}
$contentFooter .= '</div>';

$marginBottom = 10 ;
if(strlen(Producer::getConfig('document_infos_bottom')) > 0) {
$marginBottom = 40 ;
}

$pdf = new Pdf([
'mode' => Pdf::MODE_UTF8,
'format' => Pdf::FORMAT_A4,
'orientation' => Pdf::ORIENT_PORTRAIT,
'destination' => $destination,
'content' => $content,
'filename' => $this->getFilename(),
'cssFile' => Yii::getAlias('@webroot/css/document/download.css'),
'marginBottom' => $marginBottom,
'methods' => [
'SetHTMLFooter' => $contentFooter
]
]);

return $pdf->render();
if(file_exists($filenameComplete)) {
return Yii::$app->response->sendFile($filenameComplete, $this->getFilename(), ['inline'=>true]);
} }

public function send()
{
if(isset($this->user) && strlen($this->user->email) > 0) {
$producer = GlobalParam::getCurrentProducer();

$subjectEmail = $this->getType() ;
if($this->isStatusValid()) {
$subjectEmail .= ' N°'.$this->reference ;
}

$email = Yii::$app->mailer->compose(
[
'html' => 'sendDocument-html',
'text' => 'sendDocument-text'
], [
'document' => $this,
])
->setTo($this->user->email)
->setFrom([$producer->getEmailOpendistrib() => $producer->name])
->setSubject('['.$producer->name.'] '.$subjectEmail) ;

$this->generatePdf(Pdf::DEST_FILE) ;
$email->attach($this->getFilename());

return $email->send() ;
}

return false ;
else {
throw new ErrorException('File '.$filenameComplete.' not found');
} }

public function changeStatus($status)
{
if ($status == Document::STATUS_VALID) {
$this->status = $status;
$this->reference = $this->generateReference();
}

public function generatePdf($destination)
{
$producer = GlobalParam::getCurrentProducer();
$content = Yii::$app->controller->renderPartial('/document/download', [
'producer' => $producer,
'document' => $this
]);

$contentFooter = '<div id="footer">';
$contentFooter .= '<div class="infos-bottom">' . Html::encode($producer->document_infos_bottom) . '</div>';
if ($this->isStatusValid() || $this->isStatusDraft()) {
$contentFooter .= '<div class="reference-document">';
if ($this->isStatusValid()) {
$contentFooter .= $this->getType() . ' N°' . $this->reference;
}
if ($this->isStatusDraft()) {
$contentFooter .= $this->getType() . ' non validé';
if ($this->getType() == 'Facture') {
$contentFooter .= 'e';
} }
}
$contentFooter .= '</div>';
} }
$contentFooter .= '</div>';


public function getStatusWording()
{
return ($this->status == self::STATUS_DRAFT) ? 'Brouillon' : 'Validé';
}

public function getStatusCssClass()
{
return ($this->status == self::STATUS_DRAFT) ? 'default' : 'success';
}

public function getHtmlLabel()
{
$label = $this->getStatusWording();
$classLabel = $this->getStatusCssClass();
return '<span class="label label-' . $classLabel . '">' . $label . '</span>';
$marginBottom = 10;
if (strlen(Producer::getConfig('document_infos_bottom')) > 0) {
$marginBottom = 40;
} }


public function isStatus($status)
{
return $this->status == $status;
$this->initDirectoryPdf();

$pdf = new Pdf([
'mode' => Pdf::MODE_UTF8,
'format' => Pdf::FORMAT_A4,
'orientation' => Pdf::ORIENT_PORTRAIT,
'destination' => $destination,
'content' => $content,
'filename' => $this->getFilenameComplete(),
'cssFile' => Yii::getAlias('@webroot/css/document/download.css'),
'marginBottom' => $marginBottom,
'methods' => [
'SetHTMLFooter' => $contentFooter
]
]);

return $pdf->render();
}

public function send()
{
if (isset($this->user) && strlen($this->user->email) > 0) {
$producer = GlobalParam::getCurrentProducer();

$subjectEmail = $this->getType();
if ($this->isStatusValid()) {
$subjectEmail .= ' N°' . $this->reference;
}

$email = Yii::$app->mailer->compose(
[
'html' => 'sendDocument-html',
'text' => 'sendDocument-text'
], [
'document' => $this,
])
->setTo($this->user->email)
->setFrom([$producer->getEmailOpendistrib() => $producer->name])
->setSubject('[' . $producer->name . '] ' . $subjectEmail);

$this->generatePdf(Pdf::DEST_FILE);
$email->attach($this->getFilenameComplete());

return $email->send();
} }


public function isStatusDraft()
{
return $this->isStatus(self::STATUS_DRAFT);
}
return false;
}


public function isStatusValid()
{
return $this->isStatus(self::STATUS_VALID);
public function changeStatus($status)
{
if ($status == Document::STATUS_VALID) {
$this->status = $status;
$this->reference = $this->generateReference();
} }

public function getProductsOrders()
{
$productsOrdersArray = [];
$ordersArray = $this->orders ;
if ($ordersArray && count($ordersArray)) {
foreach ($ordersArray as $order) {
foreach ($order->productOrder as $productOrder) {
$indexProductOrder = $productOrder->product->order ;
$newProductOrder = clone $productOrder ;

if (!isset($productsOrdersArray[$indexProductOrder])) {
$productsOrdersArray[$indexProductOrder] = [$newProductOrder];
} else {
$productOrderMatch = false;
foreach ($productsOrdersArray[$indexProductOrder] as &$theProductOrder) {
if ($theProductOrder->unit == $productOrder->unit
&& ( (!$this->isInvoicePrice() && $theProductOrder->price == $productOrder->price)
|| ($this->isInvoicePrice() && $theProductOrder->invoice_price == $productOrder->invoice_price)
)) {

$theProductOrder->quantity += $productOrder->quantity;
$productOrderMatch = true;
}
}
if (!$productOrderMatch) {
$productsOrdersArray[$indexProductOrder][] = $newProductOrder;
}
}
}
}

public function getStatusWording()
{
return ($this->status == self::STATUS_DRAFT) ? 'Brouillon' : 'Validé';
}

public function getStatusCssClass()
{
return ($this->status == self::STATUS_DRAFT) ? 'default' : 'success';
}

public function getHtmlLabel()
{
$label = $this->getStatusWording();
$classLabel = $this->getStatusCssClass();
return '<span class="label label-' . $classLabel . '">' . $label . '</span>';
}

public function isStatus($status)
{
return $this->status == $status;
}

public function isStatusDraft()
{
return $this->isStatus(self::STATUS_DRAFT);
}

public function isStatusValid()
{
return $this->isStatus(self::STATUS_VALID);
}

public function getProductsOrders()
{
$productsOrdersArray = [];
$ordersArray = $this->orders;
if ($ordersArray && count($ordersArray)) {
foreach ($ordersArray as $order) {
foreach ($order->productOrder as $productOrder) {
$indexProductOrder = $productOrder->product->order;
$newProductOrder = clone $productOrder;

if (!isset($productsOrdersArray[$indexProductOrder])) {
$productsOrdersArray[$indexProductOrder] = [$newProductOrder];
} else {
$productOrderMatch = false;
foreach ($productsOrdersArray[$indexProductOrder] as &$theProductOrder) {
if ($theProductOrder->unit == $productOrder->unit
&& ((!$this->isInvoicePrice() && $theProductOrder->price == $productOrder->price)
|| ($this->isInvoicePrice() && $theProductOrder->invoice_price == $productOrder->invoice_price)
)) {

$theProductOrder->quantity += $productOrder->quantity;
$productOrderMatch = true;
}
}
if (!$productOrderMatch) {
$productsOrdersArray[$indexProductOrder][] = $newProductOrder;
} }
}
} }
}
}


// tri des orderProduct par product.order
ksort($productsOrdersArray);
// tri des orderProduct par product.order
ksort($productsOrdersArray);


return $productsOrdersArray;
}
return $productsOrdersArray;
}


public function isDisplayOrders()
{
$displayOrders = ($this->getClass() == 'Invoice') ?
Producer::getConfig('document_display_orders_invoice') :
Producer::getConfig('document_display_orders_delivery_note') ;
public function isDisplayOrders()
{
$displayOrders = ($this->getClass() == 'Invoice') ?
Producer::getConfig('document_display_orders_invoice') :
Producer::getConfig('document_display_orders_delivery_note');


return $displayOrders ;
}
return $displayOrders;
}


public function getFilename()
{
return Yii::getAlias('@app/web/pdf/'.$this->getType().'-' . $this->reference. '.pdf') ;
}
public function getAliasDirectoryBase()
{
return '@app/web/pdf/'.$this->id_producer.'/';
}


public function isInvoicePrice()
{
return $this->getClass() == 'Invoice' || $this->getClass() == 'DeliveryNote' ;
public function initDirectoryPdf()
{
$aliasDirectoryBase = $this->getAliasDirectoryBase();
$directoryPdf = Yii::getAlias($aliasDirectoryBase);
if(!file_exists($directoryPdf)) {
mkdir($directoryPdf, 0755);
} }

}

public function getFilename()
{
return $this->getType() . '-' . $this->reference . '.pdf';
}

public function getFilenameComplete()
{
return Yii::getAlias($this->getAliasDirectoryBase() . $this->getFilename());
}

public function isInvoicePrice()
{
return $this->getClass() == 'Invoice' || $this->getClass() == 'DeliveryNote';
}

public function isTaxCalculationMethodSumOfRoundings()
{
return $this->tax_calculation_method == self::TAX_CALCULATION_METHOD_SUM_OF_ROUNDINGS;
}

public function isTaxCalculationMethodRoundingOfTheSum()
{
return $this->tax_calculation_method == self::TAX_CALCULATION_METHOD_ROUNDING_OF_THE_SUM;
}

public function initTaxCalculationMethod()
{
$producerTaxCalculationMethod = Producer::getConfig('option_tax_calculation_method');

if ($producerTaxCalculationMethod) {
$this->tax_calculation_method = $producerTaxCalculationMethod;
} else {
$this->tax_calculation_method = self::TAX_CALCULATION_METHOD_DEFAULT;
}
}
} }

+ 74
- 28
common/models/Order.php View File

{ {
var $amount = 0; var $amount = 0;
var $amount_with_tax = 0; var $amount_with_tax = 0;
var $amount_vat = [];
var $invoice_amount = 0; var $invoice_amount = 0;
var $invoice_amount_with_tax = 0; var $invoice_amount_with_tax = 0;
var $invoice_amount_vat = [];
var $paid_amount = 0; var $paid_amount = 0;
var $weight = 0; var $weight = 0;


* Initialise le montant total, le montant déjà payé et le poids de la * Initialise le montant total, le montant déjà payé et le poids de la
* commande. * commande.
*/ */
public function init()
public function init($taxCalculationMethod = Document::TAX_CALCULATION_METHOD_DEFAULT)
{ {
$this->initAmount();
$this->initAmount($taxCalculationMethod);
$this->initPaidAmount(); $this->initPaidAmount();


return $this; return $this;
* Initialise le montant de la commande. * Initialise le montant de la commande.
* *
*/ */
public function initAmount()
public function initAmount($taxCalculationMethod = Document::TAX_CALCULATION_METHOD_DEFAULT)
{ {
$this->amount = 0; $this->amount = 0;
$this->amount_with_tax = 0; $this->amount_with_tax = 0;
$this->amount_vat = [];
$this->invoice_amount = 0; $this->invoice_amount = 0;
$this->invoice_amount_with_tax = 0; $this->invoice_amount_with_tax = 0;
$this->invoice_amount_vat = [];
$this->weight = 0; $this->weight = 0;


if (isset($this->productOrder)) { if (isset($this->productOrder)) {
foreach ($this->productOrder as $productOrder) { foreach ($this->productOrder as $productOrder) {
$this->amount += $productOrder->price * $productOrder->quantity;
$this->amount_with_tax += Price::getPriceWithTax(
$productOrder->price,
$productOrder->taxRate->value
) * $productOrder->quantity;

if($productOrder->invoice_price) {
$invoicePrice = $productOrder->invoice_price;
}
else {
$invoicePrice = $productOrder->price;
}

$this->invoice_amount += $invoicePrice * $productOrder->quantity;
$this->invoice_amount_with_tax += Price::getPriceWithTax(
$invoicePrice,
$productOrder->taxRate->value
) * $productOrder->quantity;
$this->addAmount(self::AMOUNT_TOTAL, $productOrder, $taxCalculationMethod);
$this->addAmount(self::INVOICE_AMOUNT_TOTAL, $productOrder, $taxCalculationMethod);
$this->addWeight($productOrder);
}
}
}


if ($productOrder->unit == 'piece') {
if (isset($productOrder->product)) {
$this->weight += ($productOrder->quantity * $productOrder->product->weight) / 1000;
}
} else {
$this->weight += $productOrder->quantity;
}
public function addWeight($productOrder)
{
if ($productOrder->unit == 'piece') {
if (isset($productOrder->product)) {
$this->weight += ($productOrder->quantity * $productOrder->product->weight) / 1000;
} }
} else {
$this->weight += $productOrder->quantity;
} }
} }


public function addAmount($typeTotal, $productOrder, $taxCalculationMethod)
{
$fieldNameAmount = $this->getFieldNameAmount($typeTotal);
$fieldNameAmountWithTax = $this->getFieldNameAmount($typeTotal, 'with_tax');
$price = $productOrder->getPriceByTypeTotal($typeTotal);
$this->$fieldNameAmount += $price * $productOrder->quantity;
$this->$fieldNameAmountWithTax += Price::getPriceWithTax(
$price,
$productOrder->taxRate->value,
$taxCalculationMethod
) * $productOrder->quantity;
$this->addVat($typeTotal, $price * $productOrder->quantity, $productOrder->taxRate, $taxCalculationMethod);
}

public function addVat($typeTotal, $priceTotalWithoutTax, $taxRate, $taxCalculationMethod)
{
$fieldName = $this->getFieldNameAmount($typeTotal, 'vat');

if(!isset($this->$fieldName[$taxRate->id])) {
$this->$fieldName[$taxRate->id] = 0;
}

$this->$fieldName[$taxRate->id] += Price::getVat($priceTotalWithoutTax, $taxRate->value, $taxCalculationMethod);
}

public function getTotalVat($typeTotal = self::AMOUNT_TOTAL)
{
$fieldName = $this->getFieldNameAmount($typeTotal, 'vat');
$totalVat = 0;

foreach($this->$fieldName as $vat) {
$totalVat += $vat;
}

return $totalVat;
}

public function getFieldNameAmount($typeTotal = self::AMOUNT_TOTAL, $typeField = '')
{
$fieldName = 'amount';
if($typeTotal == self::INVOICE_AMOUNT_TOTAL) {
$fieldName = 'invoice_amount';
}

if($typeField == 'vat') {
$fieldName = $fieldName.'_vat';
}
elseif($typeField == 'with_tax') {
$fieldName = $fieldName.'_with_tax';
}

return $fieldName;
}

/** /**
* Initialise le montant payé de la commande et le retourne. * Initialise le montant payé de la commande et le retourne.
* *

+ 143
- 6
common/models/Producer.php View File

const ORDER_ENTRY_POINT_DATE = 'date'; const ORDER_ENTRY_POINT_DATE = 'date';
const ORDER_ENTRY_POINT_POINT_SALE = 'point-sale'; const ORDER_ENTRY_POINT_POINT_SALE = 'point-sale';


const BILLING_FREQUENCY_MONTHLY = 'monthly';
const BILLING_FREQUENCY_QUARTERLY = 'quarterly';
const BILLING_FREQUENCY_BIANNUAL = 'biannual';

public static $billingFrequencyArray = [
self::BILLING_FREQUENCY_MONTHLY => 'Mensuelle',
self::BILLING_FREQUENCY_QUARTERLY => 'Trimestrielle',
self::BILLING_FREQUENCY_BIANNUAL => 'Biannuelle',
];

const BILLING_TYPE_CLASSIC = 'classic';
const BILLING_TYPE_FREE_PRICE = 'free-price';

public static $billingTypeArray = [
self::BILLING_TYPE_CLASSIC => 'Classique',
self::BILLING_TYPE_FREE_PRICE => 'Prix libre',
];

var $secret_key_payplug; var $secret_key_payplug;


/** /**
'option_stripe_public_key', 'option_stripe_public_key',
'option_stripe_private_key', 'option_stripe_private_key',
'option_stripe_endpoint_secret', 'option_stripe_endpoint_secret',
'option_online_payment_type'
'option_online_payment_type',
'option_tax_calculation_method'
], ],
'string' 'string'
], ],
'option_delivery', 'option_delivery',
'option_display_export_grid', 'option_display_export_grid',
'option_stripe_mode_test', 'option_stripe_mode_test',
'option_notify_producer_order_summary'
'option_notify_producer_order_summary',
'option_billing_reduction',
'option_export_evoliz'
], ],
'boolean' 'boolean'
], ],
'document_invoice_prefix', 'document_invoice_prefix',
'document_invoice_first_reference', 'document_invoice_first_reference',
'document_delivery_note_prefix', 'document_delivery_note_prefix',
'document_delivery_note_first_reference'
'document_delivery_note_first_reference',
'option_billing_type',
'option_billing_frequency',
], ],
'string', 'string',
'max' => 255 'max' => 255
'type' => 'number', 'type' => 'number',
'message' => 'Prix libre doit être supérieur ou égal à 0' 'message' => 'Prix libre doit être supérieur ou égal à 0'
], ],
//[['option_dashboard_date_start', 'option_dashboard_date_end'], 'date', 'format' => 'php:d/m/Y'],
[['option_dashboard_date_start', 'option_dashboard_date_end'], 'safe'], [['option_dashboard_date_start', 'option_dashboard_date_end'], 'safe'],
]; ];
} }
'option_delivery' => 'Proposer la livraison à domicile', 'option_delivery' => 'Proposer la livraison à domicile',
'option_display_export_grid' => 'Afficher l\'export grille dans les distributions', 'option_display_export_grid' => 'Afficher l\'export grille dans les distributions',
'document_display_product_description' => 'Documents : afficher la description des produits', 'document_display_product_description' => 'Documents : afficher la description des produits',
'option_notify_producer_order_summary' => 'Recevoir les récapitulatifs de commande par email'
'option_notify_producer_order_summary' => 'Recevoir les récapitulatifs de commande par email',
'option_billing_type' => 'Type de facturation',
'option_billing_frequency' => 'Fréquence de facturation',
'option_billing_reduction' => 'Réduction appliquée au moment de la facturation',
'option_tax_calculation_method' => 'Méthode de calcul de la TVA',
'option_export_evoliz' => 'Activer l\'export vers Evoliz'
]; ];
} }


} }
} }


public function getAmountToBeBilledByTurnover($turnover, $format = false)
{
$amountToBeBilled = 0;
$producerPriceRangeArray = ProducerPriceRange::find()->all();
foreach($producerPriceRangeArray as $priceRange) {
if($turnover >= $priceRange->range_begin && $turnover < $priceRange->range_end) {
$amountToBeBilled = $priceRange->price;
}
}

if($format) {
return Price::format($amountToBeBilled);
}
else {
return $amountToBeBilled;
}
}

public function getAmountToBeBilledByMonth($month, $format = false)
{
$turnover = $this->getTurnover($month);
return $this->getAmountToBeBilledByTurnover($turnover, $format);
}

public function getSummaryAmountsToBeBilled($label, $numberOfMonths = 1)
{
$text = '';
$numMonthCurrent = date('m');

if($numberOfMonths == 1
|| ($numberOfMonths == 3 && (in_array($numMonthCurrent, [1, 4, 7, 10])))
|| ($numberOfMonths == 6 && (in_array($numMonthCurrent, [1, 7])))) {

for ($i = 1; $i <= $numberOfMonths; $i++) {
$month = date('Y-m', strtotime('-' . $i . ' month'));
$turnover = $this->getTurnover($month);

if ($turnover) {
if ($this->isBillingTypeClassic()) {
$text .= '<strong>';
}

$text .= $this->getAmountToBeBilledByTurnover($turnover, true);

if ($this->isBillingTypeClassic()) {
$text .= '</strong>';
}

$text .= ' / '.Price::format($turnover);

$text .= '<br />';
}
}

if (strlen($text)) {
$text = $label . ' : <br />' . $text;
}

}

return $text;
}

public function getAmountBilledLastMonth()
{
if($this->isBillingTypeClassic()) {
$month = date('Y-m', strtotime('-1 month'));
return $this->getAmountToBeBilledByMonth($month);
}
elseif($this->isBillingTypeFreePrice()) {
return $this->free_price;
}

return 0;
}

/** /**
* Retourne le montant à facturer pour une période donnée. * Retourne le montant à facturer pour une période donnée.
* *
{ {
if (!is_null($this->free_price)) { if (!is_null($this->free_price)) {
if ($format) { if ($format) {
return number_format($this->free_price, 2, ',', false) . ' € HT';
return number_format($this->free_price, 2, ',', false) . ' €';
} else { } else {
return $this->free_price; return $this->free_price;
} }
return $this->isOnlinePaymentActive() && $this->option_online_payment_type == 'order' ; return $this->isOnlinePaymentActive() && $this->option_online_payment_type == 'order' ;
} }


public static function getBillingFrequencyPopulateDropdown()
{
return self::$billingFrequencyArray;
}

public function isBillingFrequencyMonthly()
{
return $this->option_billing_frequency == self::BILLING_FREQUENCY_MONTHLY;
}

public function isBillingFrequencyQuarterly()
{
return $this->option_billing_frequency == self::BILLING_FREQUENCY_QUARTERLY;
}

public function isBillingFrequencyBiannual()
{
return $this->option_billing_frequency == self::BILLING_FREQUENCY_BIANNUAL;
}

public static function getBillingTypePopulateDropdown()
{
return self::$billingTypeArray;
}

public function isBillingTypeClassic()
{
return $this->option_billing_type == self::BILLING_TYPE_CLASSIC;
}

public function isBillingTypeFreePrice()
{
return $this->option_billing_type == self::BILLING_TYPE_FREE_PRICE;
}
} }

+ 95
- 0
common/models/ProducerPriceRange.php View File

<?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\models;

use common\components\ActiveRecordCommon;

/**
* This is the model class for table "producer_price_range".
*
* @property integer $id
*/
class ProducerPriceRange extends ActiveRecordCommon
{
/**
* @inheritdoc
*/
public static function tableName()
{
return 'producer_price_range';
}

/**
* @inheritdoc
*/
public function rules()
{
return [
[['range_begin', 'range_end', 'price'], 'double'],
];
}

/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'range_begin' => 'Début',
'range_end' => 'Fin',
'price' => 'Tarif (HT)',
];
}

/**
* Retourne les options de base nécessaires à la fonction de recherche.
*
* @return array
*/
public static function defaultOptionsSearch()
{
return [
'with' => [],
'join_with' => [],
'orderby' => '',
'attribute_id_producer' => ''
];
}
}

+ 9
- 0
common/models/ProductOrder.php View File

return Price::getPriceWithTax($this->price, $this->taxRate->value); return Price::getPriceWithTax($this->price, $this->taxRate->value);
} }


public function getPriceByTypeTotal($typeTotal = Order::AMOUNT_TOTAL)
{
if($typeTotal == Order::INVOICE_AMOUNT_TOTAL && $this->invoice_price) {
return $this->invoice_price;
}

return $this->price;
}

} }

+ 12
- 0
common/models/TaxRate.php View File

'attribute_id_producer' => '' 'attribute_id_producer' => ''
] ; ] ;
} }

public static function getTaxRateArray()
{
$taxRateArrayReturn = [];
$taxRateArray = TaxRate::find()->all();

foreach($taxRateArray as $taxRate) {
$taxRateArrayReturn[$taxRate->id] = $taxRate;
}

return $taxRateArrayReturn;
}
} }

+ 3
- 2
common/models/User.php View File

{ {
return [ return [
[['no_mail', 'mail_distribution_monday', 'mail_distribution_tuesday', 'mail_distribution_wednesday', 'mail_distribution_thursday', 'mail_distribution_friday', 'mail_distribution_saturday', 'mail_distribution_sunday', 'is_main_contact'], 'boolean'], [['no_mail', 'mail_distribution_monday', 'mail_distribution_tuesday', 'mail_distribution_wednesday', 'mail_distribution_thursday', 'mail_distribution_friday', 'mail_distribution_saturday', 'mail_distribution_sunday', 'is_main_contact'], 'boolean'],
[['lastname', 'name', 'phone', 'address', 'type', 'name_legal_person'], 'string'],
[['lastname', 'name', 'phone', 'address', 'type', 'name_legal_person', 'evoliz_code'], 'string'],
['lastname', 'verifyOneName', 'skipOnError' => false, 'skipOnEmpty' => false], ['lastname', 'verifyOneName', 'skipOnError' => false, 'skipOnEmpty' => false],
['email', 'email', 'message' => 'Cette adresse email n\'est pas valide'], ['email', 'email', 'message' => 'Cette adresse email n\'est pas valide'],
['email', 'verifyEmail'], ['email', 'verifyEmail'],
'name_legal_person' => 'Libellé', 'name_legal_person' => 'Libellé',
'is_main_contact' => 'Contact principal', 'is_main_contact' => 'Contact principal',
'product_price_percent' => 'Prix produits : pourcentage', 'product_price_percent' => 'Prix produits : pourcentage',
'user_groups' => "Groupes d'utilisateurs"
'user_groups' => "Groupes d'utilisateurs",
'evoliz_code' => 'Code client Evoliz'
]; ];
} }



+ 31
- 0
console/migrations/m220914_091112_add_table_producer_price_range.php View File

<?php

use yii\db\Migration;
use yii\db\Schema;

/**
* Class m220914_091112_add_table_producer_price_range
*/
class m220914_091112_add_table_producer_price_range extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->createTable('producer_price_range', [
'id' => 'pk',
'range_begin' => Schema::TYPE_DOUBLE . ' NOT NULL',
'range_end' => Schema::TYPE_DOUBLE,
'price' => Schema::TYPE_DOUBLE . ' NOT NULL',
]);
}

/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropTable('producer_price_range');
}
}

+ 27
- 0
console/migrations/m220915_072309_producer_add_option_billing_frequency.php View File

<?php

use yii\db\Migration;
use yii\db\Schema;
use common\models\Producer;

/**
* Class m220915_072309_producer_add_option_billing_frequency
*/
class m220915_072309_producer_add_option_billing_frequency extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->addColumn('producer', 'option_billing_frequency', Schema::TYPE_STRING.' DEFAULT \''.Producer::BILLING_FREQUENCY_MONTHLY.'\'');
}

/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropColumn('producer','option_billing_frequency');
}
}

+ 29
- 0
console/migrations/m220915_083713_producer_add_options_billing.php View File

<?php

use yii\db\Migration;
use yii\db\Schema;
use common\models\Producer;

/**
* Class m220915_083713_producer_add_options_billing
*/
class m220915_083713_producer_add_options_billing extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->addColumn('producer', 'option_billing_type', Schema::TYPE_STRING.' DEFAULT \''.Producer::BILLING_TYPE_CLASSIC.'\'');
$this->addColumn('producer', 'option_billing_reduction', Schema::TYPE_BOOLEAN.' DEFAULT 0');
}

/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropColumn('producer','option_billing_type');
$this->dropColumn('producer','option_billing_reduction');
}
}

+ 44
- 0
console/migrations/m220916_062206_add_column_document_tax_calculation_method.php View File

<?php

use yii\db\Migration;
use yii\db\Schema;
use common\models\Document;

/**
* Class m220916_062206_add_column_document_tax_calculation_method
*/
class m220916_062206_add_column_document_tax_calculation_method extends Migration
{
public static $tableDocumentArray = ['invoice', 'delivery_note', 'quotation'];

/**
* {@inheritdoc}
*/
public function safeUp()
{
$schemaTaxCalculationMethod = Schema::TYPE_STRING.' DEFAULT \''.Document::TAX_CALCULATION_METHOD_DEFAULT.'\'';

// producer
$this->addColumn('producer', 'option_tax_calculation_method', $schemaTaxCalculationMethod);

// documents
$columnTaxCalculationMethod = 'tax_calculation_method';
foreach(self::$tableDocumentArray as $tableName) {
$this->addColumn($tableName, $columnTaxCalculationMethod, $schemaTaxCalculationMethod);
// méthode appliquée jusqu'à maintenant
$this->execute('UPDATE `'.$tableName.'` SET `'.$columnTaxCalculationMethod.'` = \''.Document::TAX_CALCULATION_METHOD_SUM_OF_ROUNDINGS.'\'');
}
}

/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropColumn('producer', 'option_tax_calculation_method');

foreach(self::$tableDocumentArray as $tableName) {
$this->dropColumn($tableName, 'tax_calculation_method');
}
}
}

+ 28
- 0
console/migrations/m220919_084020_add_fields_export_evoliz.php View File

<?php

use yii\db\Migration;
use yii\db\Schema;

/**
* Class m220919_084020_add_fields_export_evoliz
*/
class m220919_084020_add_fields_export_evoliz extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->addColumn('producer', 'option_export_evoliz', Schema::TYPE_BOOLEAN .' DEFAULT 0');
$this->addColumn('user', 'evoliz_code', Schema::TYPE_STRING);
}

/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropColumn('producer', 'option_export_evoliz');
$this->dropColumn('user', 'evoliz_code');
}
}

Loading…
Cancel
Save