@@ -73,7 +73,7 @@ class CommunicateController extends BackendController | |||
} | |||
/** | |||
* Affiche la page d'accueil de la section avec un aperçu du mpde d'emploi | |||
* Affiche la page d'accueil de la section avec un aperçu du mode d'emploi | |||
* à imprimer. | |||
*/ | |||
public function actionIndex() |
@@ -38,6 +38,7 @@ | |||
namespace backend\controllers; | |||
use common\helpers\Ajax; | |||
use common\helpers\CSV; | |||
use common\helpers\GlobalParam; | |||
use common\helpers\MeanPayment; | |||
@@ -598,7 +599,7 @@ class DistributionController extends BackendController | |||
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; | |||
$productDistributionManager = $this->getProductDistributionManager(); | |||
$productDistribution = $this->getProductDistribution($idProduct, $idDistribution); | |||
$productDistributionManager->updateProductDistributionQuantityMax($productDistribution, $quantityMax); | |||
$productDistributionManager->updateProductDistributionQuantityMax($productDistribution, (float) $quantityMax); | |||
return ['success']; | |||
} | |||
@@ -758,9 +759,13 @@ class DistributionController extends BackendController | |||
*/ | |||
public function actionAjaxProcessAddSubscriptions($date) | |||
{ | |||
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; | |||
$this->getOrderManager()->createAllOrdersFromSubscriptions($date, true); | |||
return ['success']; | |||
$ordersArray = $this->getOrderManager()->createAllOrdersFromSubscriptions($date, true); | |||
if($ordersArray && count($ordersArray)) { | |||
return Ajax::responseSuccess('Les abonnements ont bien été importés.'); | |||
} | |||
return Ajax::responseError('Aucun abonnement à importer.'); | |||
} | |||
/** | |||
@@ -857,286 +862,102 @@ class DistributionController extends BackendController | |||
return $return; | |||
} | |||
public function actionAjaxValidateDeliveryNotes($idOrders) | |||
public function actionAjaxGenerateDeliveryNote(int $idOrder) | |||
{ | |||
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; | |||
$this->generateDeliveryNote($idOrder); | |||
return Ajax::responseSuccess('Bon de livraison généré'); | |||
} | |||
public function actionAjaxGenerateDeliveryNotePointSale($idOrders) | |||
{ | |||
$orderManager = $this->getOrderManager(); | |||
$deliveryNoteManager = $this->getDeliveryNoteManager(); | |||
if (strlen($idOrders)) { | |||
$idOrders = json_decode($idOrders, true); | |||
if (is_array($idOrders) && count($idOrders) > 0) { | |||
foreach ($idOrders as $idOrder) { | |||
$order = Order::searchOne([ | |||
'id' => (int)$idOrder | |||
]); | |||
reset($idOrders); | |||
$firstOrder = $orderManager->findOneOrderById((int)$idOrders[key($idOrders)]); | |||
$ordersArray = Order::searchAll(['id' => $idOrders,]); | |||
$deliveryNote = $deliveryNoteManager->getOneDeliveryNoteExistingFromOrders($ordersArray); | |||
$isUpdate = (bool) $deliveryNote; | |||
if ($order && $order->distribution->id_producer == GlobalParam::getCurrentProducerId()) { | |||
$deliveryNote = DeliveryNote::searchOne([ | |||
'id' => (int)$order->id_delivery_note | |||
]); | |||
if ($deliveryNote && $deliveryNoteManager->isStatusValid($deliveryNote)) { | |||
return Ajax::responseError('Vous ne pouvez pas modifier un bon de livraison déjà validé.'); | |||
} | |||
if ($deliveryNote && $deliveryNoteManager->isStatusDraft($deliveryNote)) { | |||
$deliveryNoteManager->changeStatus($deliveryNote, Document::STATUS_VALID); | |||
$deliveryNoteManager->saveUpdate($deliveryNote); | |||
} | |||
} | |||
if(!$deliveryNote && $firstOrder && !$firstOrder->pointSale->id_user) { | |||
return Ajax::responseError("Vous devez définir un contact de facturation pour ce point de vente."); | |||
} | |||
return [ | |||
'return' => 'success', | |||
'alert' => [ | |||
'type' => 'success', | |||
'message' => 'Bon(s) de livraison validé(s)' | |||
] | |||
]; | |||
if ($firstOrder) { | |||
if (!$deliveryNote) { | |||
$deliveryNoteManager->createDeliveryNoteForPointSale( | |||
$firstOrder->pointSale, | |||
$firstOrder->distribution, | |||
$idOrders | |||
); | |||
} | |||
return Ajax::responseSuccess('Bon de livraison ' . ($isUpdate ? 'modifié' : 'généré')); | |||
} | |||
} | |||
} | |||
return [ | |||
'return' => 'error', | |||
'alert' => [ | |||
'type' => 'danger', | |||
'message' => 'Une erreur est survenue lors de la validation des bons de livraison' | |||
] | |||
]; | |||
return Ajax::responseError('Une erreur est survenue lors de la génération du bon de livraison.'); | |||
} | |||
public function actionAjaxGenerateDeliveryNoteEachUser($idOrders) | |||
{ | |||
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; | |||
$userManager = $this->getUserManager(); | |||
$userProducerManager = $this->getUserProducerManager(); | |||
$orderManager = $this->getOrderManager(); | |||
$deliveryNoteManager = $this->getDeliveryNoteManager(); | |||
$producerCurrent = $this->getProducerCurrent(); | |||
if (strlen($idOrders)) { | |||
$idOrders = json_decode($idOrders, true); | |||
if (is_array($idOrders) && count($idOrders) > 0) { | |||
foreach ($idOrders as $idOrder) { | |||
$order = Order::searchOne([ | |||
'id' => (int)$idOrder | |||
]); | |||
if ($order && $order->distribution->id_producer == GlobalParam::getCurrentProducerId() && $order->id_user) { | |||
$deliveryNote = null; | |||
$idDeliveryNote = $order->id_delivery_note; | |||
if ($idDeliveryNote) { | |||
$deliveryNote = DeliveryNote::searchOne([ | |||
'id' => (int)$idDeliveryNote | |||
]); | |||
} | |||
// on regénére le document si c'est un brouillon | |||
if ($deliveryNote && $deliveryNoteManager->isStatusDraft($deliveryNote)) { | |||
$deliveryNote->delete(); | |||
$deliveryNote = null; | |||
} | |||
if (!$deliveryNote) { | |||
$deliveryNote = new DeliveryNote(); | |||
$deliveryNoteManager->initTaxCalculationMethod($deliveryNote); | |||
$deliveryNote->id_producer = GlobalParam::getCurrentProducerId(); | |||
$deliveryNote->id_user = $order->id_user; | |||
$deliveryNote->name = 'Bon de livraison ' . $orderManager->getOrderUsername($order) . ' (' . date( | |||
'd/m/Y', | |||
strtotime( | |||
$order->distribution->date | |||
) | |||
) . ')'; | |||
$deliveryNote->address = $userManager->getFullAddress($order->user); | |||
$deliveryNote->save(); | |||
} | |||
if ($deliveryNote) { | |||
$order->id_delivery_note = $deliveryNote->id; | |||
$order->save(); | |||
// init invoice prices | |||
$user = $userManager->findOneUserById($deliveryNote->id_user); | |||
$userProducer = $userProducerManager->findOneUserProducer($user); | |||
$orderManager->updateOrderInvoicePrices($order, [ | |||
'user' => $user, | |||
'user_producer' => $userProducer, | |||
'point_sale' => $order->pointSale | |||
]); | |||
} | |||
} | |||
$this->generateDeliveryNote($idOrder); | |||
} | |||
} | |||
return [ | |||
'return' => 'success', | |||
'alert' => [ | |||
'type' => 'success', | |||
'message' => 'Bon(s) de livraison généré(s)' | |||
] | |||
]; | |||
return Ajax::responseSuccess('Bon(s) de livraison généré(s)'); | |||
} | |||
return [ | |||
'return' => 'error', | |||
'alert' => [ | |||
'type' => 'danger', | |||
'message' => 'Une erreur est survenue lors de la génération du bon de livraison.' | |||
] | |||
]; | |||
return Ajax::responseError('Une erreur est survenue lors de la génération du bon de livraison.'); | |||
} | |||
public function actionAjaxGenerateDeliveryNote($idOrders) | |||
public function generateDeliveryNote(int $idOrder) | |||
{ | |||
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; | |||
$userManager = $this->getUserManager(); | |||
$userProducerManager = $this->getUserProducerManager(); | |||
$orderManager = $this->getOrderManager(); | |||
$deliveryNoteManager = $this->getDeliveryNoteManager(); | |||
$producerCurrent = $this->getProducerCurrent(); | |||
$order = $orderManager->findOneOrderById($idOrder); | |||
if ($orderManager->isOrderFromProducer($order) && $order->id_user) { | |||
$deliveryNoteManager->createDeliveryNoteForOrder($order); | |||
} | |||
} | |||
public function actionAjaxValidateDeliveryNotes($idOrders) | |||
{ | |||
$orderManager = $this->getOrderManager(); | |||
$deliveryNoteManager = $this->getDeliveryNoteManager(); | |||
if (strlen($idOrders)) { | |||
$idOrders = json_decode($idOrders, true); | |||
if (is_array($idOrders) && count($idOrders) > 0) { | |||
// récupération première commande pour obtenir des infos | |||
reset($idOrders); | |||
$firstOrder = Order::searchOne([ | |||
'id' => (int)$idOrders[key($idOrders)] | |||
]); | |||
// deliveryNote existant | |||
$deliveryNote = null; | |||
$isUpdate = false; | |||
$i = 0; | |||
$ordersArray = Order::searchAll([ | |||
'id' => $idOrders, | |||
]); | |||
do { | |||
$order = $ordersArray[$i]; | |||
if ($order->distribution->id_producer == GlobalParam::getCurrentProducerId() && $order->id_delivery_note > 0) { | |||
$deliveryNote = DeliveryNote::searchOne([ | |||
'id' => $order->id_delivery_note | |||
]); | |||
$isUpdate = true; | |||
} | |||
$i++; | |||
} while ($deliveryNote == null && isset($ordersArray[$i])); | |||
if ($deliveryNote && $deliveryNote->status == Document::STATUS_VALID) { | |||
return [ | |||
'return' => 'error', | |||
'alert' => [ | |||
'type' => 'danger', | |||
'message' => 'Vous ne pouvez pas modifier un bon de livraison déjà validé.' | |||
] | |||
]; | |||
} | |||
if ($firstOrder) { | |||
// génération du BL | |||
if (!$deliveryNote) { | |||
$deliveryNote = new DeliveryNote; | |||
$deliveryNoteManager->initTaxCalculationMethod($deliveryNote); | |||
$deliveryNote->name = 'Bon de livraison ' . $firstOrder->pointSale->name . ' (' . date( | |||
'd/m/Y', | |||
strtotime( | |||
$firstOrder->distribution->date | |||
) | |||
) . ')'; | |||
$deliveryNote->id_producer = GlobalParam::getCurrentProducerId(); | |||
if ($firstOrder->pointSale->id_user) { | |||
$deliveryNote->id_user = $firstOrder->pointSale->id_user; | |||
$user = $userManager->findOneUserById($deliveryNote->id_user); | |||
$userProducer = $userProducerManager->findOneUserProducer($user); | |||
} else { | |||
$user = new User(); | |||
$user->type = User::TYPE_LEGAL_PERSON; | |||
$user->name_legal_person = $firstOrder->pointSale->name; | |||
$user->address = $firstOrder->pointSale->address; | |||
$user->id_producer = 0; | |||
$userManager->setPassword($user, Password::generate()); | |||
$userManager->generateAuthKey($user); | |||
$user->email = ''; | |||
if (!strlen($user->email)) { | |||
$user->username = 'inconnu@opendistrib.net'; | |||
} | |||
$user->save(); | |||
$userProducer = new UserProducer(); | |||
$userProducer->id_user = $user->id; | |||
$userProducer->id_producer = GlobalParam::getCurrentProducerId(); | |||
$userProducer->credit = 0; | |||
$userProducer->active = 1; | |||
$userProducer->save(); | |||
$firstOrder->pointSale->id_user = $user->id; | |||
$firstOrder->pointSale->save(); | |||
$deliveryNote->id_user = $user->id; | |||
} | |||
$deliveryNote->address = $userManager->getFullAddress($user); | |||
$deliveryNote->save(); | |||
} else { | |||
// réinitialisation des order.id_delivery_note | |||
Order::updateAll([ | |||
'id_delivery_note' => null | |||
], [ | |||
'id_delivery_note' => $deliveryNote->id | |||
]); | |||
} | |||
if (!isset($user) || !$user) { | |||
$user = $userManager->findOneUserById($deliveryNote->id_user); | |||
$userProducer = $userProducerManager->findOneUserProducer($user); | |||
} | |||
// affectation du BL aux commandes | |||
foreach ($idOrders as $idOrder) { | |||
$order = $orderManager->findOneOrderById((int)$idOrder); | |||
if ($order && $order->distribution->id_producer == GlobalParam::getCurrentProducerId()) { | |||
$order->id_delivery_note = $deliveryNote->id; | |||
$order->save(); | |||
} | |||
// init invoice price | |||
$order = $orderManager->findOneOrderById((int)$idOrder); | |||
if ($order) { | |||
$orderManager->updateOrderInvoicePrices($order, | |||
[ | |||
'user' => $user, | |||
'user_producer' => $userProducer, | |||
'point_sale' => $firstOrder->pointSale | |||
]); | |||
foreach ($idOrders as $idOrder) { | |||
$order = $orderManager->findOneOrderById($idOrder); | |||
if ($orderManager->isOrderFromProducer($order)) { | |||
$deliveryNote = $deliveryNoteManager->findOneDeliveryNoteById((int) $order->id_delivery_note); | |||
if($deliveryNote) { | |||
$deliveryNoteManager->validateDocument($deliveryNote); | |||
} | |||
} | |||
return [ | |||
'return' => 'success', | |||
'alert' => [ | |||
'type' => 'success', | |||
'message' => 'Bon de livraison ' . ($isUpdate ? 'modifié' : 'généré') | |||
] | |||
]; | |||
} | |||
return Ajax::responseSuccess('Bon(s) de livraison validé(s)'); | |||
} | |||
} | |||
return [ | |||
'return' => 'error', | |||
'alert' => [ | |||
'type' => 'danger', | |||
'message' => 'Une erreur est survenue lors de la génération du bon de livraison.' | |||
] | |||
]; | |||
return Ajax::responseError('Une erreur est survenue lors de la validation des bons de livraison'); | |||
} | |||
} |
@@ -1035,15 +1035,15 @@ class OrderController extends BackendController | |||
if (abs($order->amount - $amountPaid) < 0.0001) { | |||
$html .= '<span class="label label-success">Payé</span>'; | |||
$buttonsCredit = Html::a('Rembourser ' . $orderManager->getOrderAmountWithTax($order, Order::AMOUNT_TOTAL, true), 'javascript:void(0);', ['class' => 'btn btn-default btn-xs rembourser', 'data-montant' => $order->amount, 'data-type' => 'refund']); | |||
$buttonsCredit = Html::a('Recréditer ' . $orderManager->getOrderAmountWithTax($order, Order::AMOUNT_TOTAL, true), 'javascript:void(0);', ['class' => 'btn btn-default btn-xs rembourser', 'data-montant' => $order->amount, 'data-type' => 'refund']); | |||
} elseif ($order->amount > $amountPaid) { | |||
$amountToPay = $order->amount - $amountPaid; | |||
$html .= '<span class="label label-danger">Non payé</span> reste <strong>' . number_format($amountToPay, 2) . ' €</strong> à payer'; | |||
$buttonsCredit = Html::a('Payer ' . number_format($amountToPay, 2) . ' €', 'javascript:void(0);', ['class' => 'btn btn-default btn-xs payer', 'data-montant' => $amountToPay, 'data-type' => 'payment']); | |||
$html .= '<span class="label label-danger">Non payé</span> reste <strong>' . number_format($amountToPay, 2) . ' €</strong> à débiter'; | |||
$buttonsCredit = Html::a('Débiter ' . number_format($amountToPay, 2) . ' €', 'javascript:void(0);', ['class' => 'btn btn-default btn-xs payer', 'data-montant' => $amountToPay, 'data-type' => 'payment']); | |||
} elseif ($order->amount < $amountPaid) { | |||
$amountToRefund = $amountPaid - $order->amount; | |||
$html .= ' <span class="label label-success">Payé</span> <strong>' . number_format($amountToRefund, 2) . ' €</strong> à rembourser'; | |||
$buttonsCredit = Html::a('Rembourser ' . number_format($amountToRefund, 2) . ' €', 'javascript:void(0);', ['class' => 'btn btn-default btn-xs rembourser', 'data-montant' => $amountToRefund, 'data-type' => 'refund']); | |||
$html .= ' <span class="label label-success">Payé</span> <strong>' . number_format($amountToRefund, 2) . ' €</strong> à recréditer'; | |||
$buttonsCredit = Html::a('Recréditer ' . number_format($amountToRefund, 2) . ' €', 'javascript:void(0);', ['class' => 'btn btn-default btn-xs rembourser', 'data-montant' => $amountToRefund, 'data-type' => 'refund']); | |||
} | |||
$html .= '<span class="buttons-credit">' |
@@ -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.'); | |||
} | |||
} | |||
@@ -157,6 +157,7 @@ class UserController extends BackendController | |||
$useProducer->id_producer = GlobalParam::getCurrentProducerId(); | |||
$useProducer->credit = 0; | |||
$useProducer->active = 1; | |||
$useProducer->newsletter = $model->newsletter; | |||
$useProducer->save(); | |||
$userManager->sendMailWelcome($model, $password); | |||
@@ -178,16 +179,14 @@ class UserController extends BackendController | |||
public function actionUpdate($id) | |||
{ | |||
$userManager = $this->getUserManager(); | |||
$producerManager = $this->getProducerManager(); | |||
$pointSaleManager = $this->getPointSaleManager(); | |||
$model = $this->findModel($id); | |||
// Moodification du profil | |||
$previousMail = $model->email; | |||
$user = User::find()->with('userProducer')->where(['id' => $model['id']])->one(); | |||
$userBelongToProducer = UserProducer::findOne(['id_user' => $id, 'id_producer' => GlobalParam::getCurrentProducerId()]); | |||
if ($userBelongToProducer) { | |||
$model->newsletter = $userBelongToProducer->newsletter; | |||
if ($model->load(\Yii::$app->request->post()) && $model->save()) { | |||
// on envoie le mail de bienvenue si le mail vient d'être défini | |||
@@ -201,6 +200,13 @@ class UserController extends BackendController | |||
$this->processLinkUserGroup($model); | |||
$this->processProductPricePercent($model); | |||
if($model->newsletter) { | |||
$userManager->subscribeUserNewsletter($model); | |||
} | |||
else { | |||
$userManager->unsubscribeUserNewsletter($model); | |||
} | |||
$this->setFlash('success', 'Utilisateur <strong>'.Html::encode($userManager->getUsername($model)).'</strong> modifié.'); | |||
return $this->redirect(['index']); |
@@ -163,11 +163,21 @@ Produits disponibles : | |||
} | |||
} | |||
} | |||
if($fromProducer) { | |||
$producer = GlobalParam::getCurrentProducer() ; | |||
$fromEmail = $producerManager->getEmailOpendistrib($producer) ; | |||
$fromName = $producer->name ; | |||
// Message inscription newsletter | |||
$messageAutoText .= " | |||
-- | |||
Me désinscrire de ce bulletin d'information : | |||
".Yii::$app->urlManagerProducer->createAbsoluteUrl(['newsletter/index', 'slug_producer' => $producer->slug]); | |||
$messageAutoHtml .= "<br /><br />--<br /><br /><a href=\"".Yii::$app->urlManagerProducer->createAbsoluteUrl(['newsletter/unsubscribe', 'slug_producer' => $producer->slug])."\">Me désinscrire</a> de ce bulletin d'information"; | |||
} | |||
else { | |||
$fromEmail = 'contact@opendistrib.net' ; |
@@ -74,19 +74,14 @@ $this->addBreadcrumb($this->getTitle()); | |||
<h3 class="panel-title">Participer</h3> | |||
</div> | |||
<div class="panel-body"> | |||
<p>Le logiciel Opendistrib se construit pour et avec vous. Toutes vos suggestions et remontées | |||
de bugs sont les bienvenues et forment le terreau des versions futures !</p> | |||
<p>Pour me contacter :</p> | |||
<ul class="contacts"> | |||
<li> | |||
<span class="glyphicon glyphicon-earphone"></span> | |||
<p><?= Html::a('Prendre rendez-vous', Yii::$app->parameterBag->get('appointmentUrl'), ['class' => '', 'target' => '_blank']); ?></p> | |||
</li> | |||
<li> | |||
<span class="glyphicon glyphicon-envelope"></span> | |||
<p><a href="mailto:contact@opendistrib.net">M'envoyer un message</a></p> | |||
</li> | |||
</ul> | |||
<p>Le logiciel Opendistrib se construit pour et avec vous. Toutes vos remarques, suggestions et remontées | |||
de bugs sont les bienvenues et forment le terreau des versions futures.</p> | |||
<p> | |||
<a class="btn btn-default" href="<?= $this->getUrlManagerBackend()->createUrl(['support/index']); ?>"> | |||
<span class="glyphicon glyphicon-comment"></span> | |||
Me contacter | |||
</a> | |||
</p> | |||
</div> | |||
</div> | |||
</div> |
@@ -276,7 +276,7 @@ $this->setPageTitle('Distributions') ; | |||
<span class="caret"></span> | |||
</button> | |||
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1"> | |||
<li><a v-if="idActivePointSale > 0" @click="generateDeliveryNote" href="javascript:void(0);" >Générer un bon de livraison pour ce point de vente</a></li> | |||
<li><a v-if="idActivePointSale > 0" @click="generateDeliveryNotePointSale" href="javascript:void(0);" >Générer un bon de livraison pour ce point de vente</a></li> | |||
<li><a @click="generateDeliveryNoteEachUser" href="javascript:void(0);">Générer un bon de livraison pour chaque client</a></li> | |||
<li><a @click="validateDeliveryNotes" href="javascript:void(0);">Valider les bons de livraisons</a></li> | |||
</ul> | |||
@@ -286,7 +286,7 @@ $this->setPageTitle('Distributions') ; | |||
<button v-if="tillerIsSynchro" id="btn-tiller" class="btn btn-success btn-xs" disabled><span class="glyphicon glyphicon-refresh"></span> Synchronisé avec Tiller</button> | |||
<button v-else id="btn-tiller" class="btn btn-xs btn-default" @click="synchroTiller"><span class="glyphicon glyphicon-refresh"></span> Synchroniser avec Tiller</button> | |||
</template> | |||
<button v-if="producer && producer.credit" id="btn-pay-orders" class="btn btn-default btn-xs" @click="payOrders"><span class="glyphicon glyphicon-euro"></span> Payer les commandes</button> | |||
<button v-if="producer && producer.credit" id="btn-pay-orders" class="btn btn-default btn-xs" @click="payOrders"><span class="glyphicon glyphicon-euro"></span> Débiter les commandes</button> | |||
<button id="btn-add-order" @click="openModalFormOrderCreate" class="btn btn-xs btn-primary"><span class="glyphicon glyphicon-plus"></span> Ajouter une commande</button> | |||
</div> | |||
<div class="left"> | |||
@@ -303,7 +303,6 @@ $this->setPageTitle('Distributions') ; | |||
</div> | |||
<div class="alert alert-danger" v-if="distribution && !distribution.active && orders && orders.length > 0"> | |||
{{ distribution }} | |||
Attention, ce jour de distribution n'est pas activé et vous avez quand même des commandes enregistrées. | |||
</div> | |||
@@ -323,7 +322,7 @@ $this->setPageTitle('Distributions') ; | |||
<th class="column-user">Utilisateur</th> | |||
<th class="column-point-sale" v-if="idActivePointSale == 0">Point de vente</th> | |||
<th class="column-amount">Montant</th> | |||
<th class="column-state-payment">Paiement</th> | |||
<th class="column-state-payment">Crédit</th> | |||
<th class="column-payment"></th> | |||
<th class="column-tiller" v-if="producer && producer.tiller">Tiller</th> | |||
<th class="column-actions"></th> | |||
@@ -382,16 +381,16 @@ $this->setPageTitle('Distributions') ; | |||
<td class="column-payment" v-if="producer && producer.credit"> | |||
<div class="btn-group" v-if="order.user && !order.date_delete"> | |||
<button class="btn btn-xs btn-default" v-if="order.amount_paid == order.amount" @click="orderPaymentClick" :data-id-order="order.id" data-type="refund" :data-amount="order.amount"> | |||
<span class="glyphicon glyphicon-euro"></span> Rembourser | |||
<span class="glyphicon glyphicon-euro"></span> Recréditer | |||
</button> | |||
<button class="btn btn-xs btn-default" v-else-if="order.amount_paid == 0" @click="orderPaymentClick" :data-id-order="order.id" data-type="payment" :data-amount="order.amount"> | |||
<span class="glyphicon glyphicon-euro"></span> Payer | |||
<span class="glyphicon glyphicon-euro"></span> Débiter | |||
</button> | |||
<button class="btn btn-xs btn-default" v-else-if="order.amount_paid < order.amount" @click="orderPaymentClick" :data-id-order="order.id" data-type="payment" :data-amount="order.amount_remaining"> | |||
<span class="glyphicon glyphicon-euro"></span> Payer | |||
<span class="glyphicon glyphicon-euro"></span> Débiter | |||
</button> | |||
<button class="btn btn-xs btn-default" v-else-if="order.amount_paid > order.amount" @click="orderPaymentClick" :data-id-order="order.id" data-type="refund" :data-amount="order.amount_surplus"> | |||
<span class="glyphicon glyphicon-euro"></span> Rembourser | |||
<span class="glyphicon glyphicon-euro"></span> Recréditer | |||
</button> | |||
<button type="button" class="btn btn-xs btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> | |||
@@ -418,6 +417,7 @@ $this->setPageTitle('Distributions') ; | |||
<li><a href="javascript:void(0);" class="" :data-id-order="order.id" @click="orderViewClick"><span :class="'glyphicon ' + ((showViewProduct && idOrderView == order.id) ? 'glyphicon-eye-close' : 'glyphicon-eye-open')"></span> Voir</a></li> | |||
<li><a href="javascript:void(0);" class="" :data-id-order="order.id" @click="updateOrderClick"><span class="glyphicon glyphicon-pencil"></span> Modifier</a></li> | |||
<li><a href="javascript:void(0);" class="" :data-id-order="order.id" @click="deleteOrderClick"><span class="glyphicon glyphicon-trash"></span> Supprimer</a></li> | |||
<li><a href="javascript:void(0);" class="" :data-id-order="order.id" @click="generateDeliveryNote"><span class="glyphicon glyphicon-file"></span> Générer un bon de livraison</a></li> | |||
<li v-if="order.id_subscription > 0"><a class="" :href="baseUrl+'/subscription/update?id='+order.id_subscription"><span class="glyphicon glyphicon-repeat"></span> Modifier l'abonnement associé</a></li> | |||
<li v-else><a class="add-subscription" :href="baseUrl+'/subscription/create?idOrder='+order.id"><span class="glyphicon glyphicon-plus"></span><span class="glyphicon glyphicon-repeat"></span>Créer un abonnement sur cette base</a></li> | |||
</ul> | |||
@@ -455,10 +455,10 @@ $this->setPageTitle('Distributions') ; | |||
<span class="info-box-number">{{ order.amount.replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,")+' €' }}</span> | |||
<span class="info-box-text"> | |||
Statut<br /> | |||
<span class="label label-success" v-if="order.amount_paid == order.amount">payé</span> | |||
<span class="label label-default" v-else-if="order.amount_paid == 0">non réglé</span> | |||
<span class="label label-success" v-if="order.amount_paid == order.amount">débité</span> | |||
<span class="label label-default" v-else-if="order.amount_paid == 0">non débité</span> | |||
<span class="label label-default" v-else-if="order.amount_paid > order.amount">surplus</span> | |||
<span class="label label-warning" v-else-if="order.amount_paid < order.amount">reste à payer</span> | |||
<span class="label label-warning" v-else-if="order.amount_paid < order.amount">reste à débiter</span> | |||
</span> | |||
</div> | |||
</div> | |||
@@ -477,7 +477,7 @@ $this->setPageTitle('Distributions') ; | |||
data-type="refund" | |||
@click="orderPaymentClick" > | |||
<span class="glyphicon glyphicon-chevron-right"></span> | |||
Rembourser {{ order.amount.replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,")+' €' }} | |||
Recréditer {{ order.amount.replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,")+' €' }} | |||
</button> | |||
<button v-else-if="order.amount_paid == 0" | |||
@@ -486,7 +486,7 @@ $this->setPageTitle('Distributions') ; | |||
data-type="payment" | |||
@click="orderPaymentClick"> | |||
<span class="glyphicon glyphicon-chevron-right"></span> | |||
Payer {{ order.amount.replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,")+' €' }} | |||
Débiter {{ order.amount.replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,")+' €' }} | |||
</button> | |||
<button v-else-if="order.amount_paid > order.amount" | |||
@@ -495,7 +495,7 @@ $this->setPageTitle('Distributions') ; | |||
data-type="refund" | |||
@click="orderPaymentClick"> | |||
<span class="glyphicon glyphicon-chevron-right"></span> | |||
Rembourser {{ order.amount_surplus.replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,")+' €' }} | |||
Recréditer {{ order.amount_surplus.replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,")+' €' }} | |||
</button> | |||
<button v-else-if="order.amount_paid < order.amount" | |||
@@ -504,7 +504,7 @@ $this->setPageTitle('Distributions') ; | |||
data-type="payment" | |||
@click="orderPaymentClick"> | |||
<span class="glyphicon glyphicon-chevron-right"></span> | |||
Payer le restant {{ order.amount_remaining.replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,")+' €' }} | |||
Débiter le restant {{ order.amount_remaining.replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,")+' €' }} | |||
</button> | |||
</div> | |||
@@ -581,10 +581,10 @@ $this->setPageTitle('Distributions') ; | |||
<script type="text/x-template" id="order-state-payment"> | |||
<div class="input-group"> | |||
<span class="label label-success input-group-addon" v-if="order.amount_paid == order.amount">payé</span> | |||
<span class="label label-default input-group-addon" v-else-if="order.amount_paid == 0">non réglé</span> | |||
<span class="label label-success input-group-addon" v-if="order.amount_paid == order.amount">débité</span> | |||
<span class="label label-default input-group-addon" v-else-if="order.amount_paid == 0">non débité</span> | |||
<span class="label label-default input-group-addon" v-else-if="order.amount_paid > order.amount">surplus</span> | |||
<span class="label label-warning input-group-addon" v-else-if="order.amount_paid < order.amount">reste à payer</span> | |||
<span class="label label-warning input-group-addon" v-else-if="order.amount_paid < order.amount">reste à débiter</span> | |||
<span class="glyphicon glyphicon-time" title="Paiement automatique" v-if="order.auto_payment && producer && producer.credit && (order.amount_paid == 0 || order.amount_paid < order.amount)"></span> | |||
</div> | |||
@@ -700,9 +700,6 @@ $this->setPageTitle('Distributions') ; | |||
</div> | |||
<div slot="footer"> | |||
<div class="actions-form"> | |||
<!--<button class="modal-default-button btn btn-primary" @click="submitFormCreate" v-if="!order.id && order.id_user > 0" data-process-credit="1">Créer et payer</button> | |||
<button class="modal-default-button btn btn-primary" @click="submitFormUpdate" v-if="order.id && order.id_user > 0" data-process-credit="1">Modifier et payer</button>--> | |||
<button class="modal-default-button btn btn-primary" @click="submitFormUpdate" v-if="order.id">Modifier</button> | |||
<button class="modal-default-button btn btn-primary" @click="submitFormCreate" v-if="!order.id">Créer</button> | |||
@@ -729,7 +726,7 @@ $this->setPageTitle('Distributions') ; | |||
<span class="label label-success input-group-addon" v-if="order.amount_paid == order.amount">payé</span> | |||
<span class="label label-default input-group-addon" v-else-if="order.amount_paid == 0">non réglé</span> | |||
<span class="label label-default input-group-addon" v-else-if="order.amount_paid > order.amount">surplus</span> | |||
<span class="label label-warning input-group-addon" v-else-if="order.amount_paid < order.amount">reste à payer</span> | |||
<span class="label label-warning input-group-addon" v-else-if="order.amount_paid < order.amount">reste à débiter</span> | |||
<span class="glyphicon glyphicon-time" title="Paiement automatique" v-if="order.auto_payment && producer && producer.credit && (order.amount_paid == 0 || order.amount_paid < order.amount)"></span> | |||
</div> |
@@ -1,257 +0,0 @@ | |||
<?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 common\helpers\Price; | |||
use common\logic\Order\Order\Model\Order; | |||
use common\logic\Order\Order\Wrapper\OrderManager; | |||
use common\logic\Producer\Producer\Model\Producer; | |||
use common\logic\Product\Product\Model\Product; | |||
use common\logic\Product\Product\Wrapper\ProductManager; | |||
use common\logic\User\UserProducer\Model\UserProducer; | |||
$productManager = ProductManager::getInstance(); | |||
$orderManager = OrderManager::getInstance(); | |||
$dayWeek = date('w', strtotime($date)); | |||
$dayWeekArray = [0 => 'sunday', 1 => 'monday', 2 => 'tuesday', 3 => 'wednesday', 4 => 'thursday', 5 => 'friday', 6 => 'saturday']; | |||
$fieldInfosPointSale = 'infos_' . $dayWeekArray[$dayWeek]; | |||
$html = '' ; | |||
$count = count($productsArray) ; | |||
$limit = 100 ; | |||
$isBig = $count > $limit ; | |||
// par point de vente | |||
foreach ($pointsSaleArray as $pointSale) { | |||
if (count($pointSale->orders)) { | |||
$html .= '<h3>'.$pointSale->name.'</h3>' ; | |||
$colCredit = ($pointSale->credit) ? '<th>Rappel crédit</th>' : '' ; | |||
$html .= '<table class="">' | |||
. '<thead>' | |||
. '<tr>' | |||
. '<th>Client</th>' | |||
. '<th>Produits</th>' | |||
. ($isBig ? '<th>Produits</th>' : '') | |||
. '<th>Commentaire</th>' | |||
. $colCredit | |||
. '<th>Montant</th>' | |||
. '</tr>' | |||
. '<tbody>'; | |||
foreach ($pointSale->orders as $order) { | |||
$html .= '<tr>' ; | |||
$strUser = ''; | |||
// username | |||
$strUser .= $orderManager->getOrderUsername($order) ; | |||
if(strlen($order->comment_point_sale)) | |||
{ | |||
$strUser .= '<br /><em>'.$order->comment_point_sale.'</em>' ; | |||
} | |||
// téléphone | |||
if (isset($order->user) && strlen($order->user->phone)) { | |||
$strUser .= '<br />' . $order->user->phone . ''; | |||
} | |||
// référence | |||
if($producer->option_order_reference_type == Producer::ORDER_REFERENCE_TYPE_YEARLY && $order->reference && strlen($order->reference) > 0) { | |||
$strUser .= '<br />'.$order->reference ; | |||
} | |||
$html .= '<td>'.$strUser.'</td>'; | |||
// produits | |||
$strProducts = ''; | |||
foreach ($productsArray as $product) { | |||
$add = false; | |||
foreach ($order->productOrder as $productOrder) { | |||
if($product->id == $productOrder->id_product) { | |||
$unit = ( $productManager->strUnit($productOrder->unit, 'wording_short', true) == 'p.') ? '' : ' '. $productManager->strUnit($productOrder->unit, 'wording_short', true) ; | |||
$strProducts .= '('.$productOrder->quantity .$unit.') '.$productManager->getNameExport($product) . '<br />'; | |||
$add = true; | |||
} | |||
} | |||
} | |||
$html .= '<td>'.substr($strProducts, 0, strlen($strProducts) - 6).'</td>'; | |||
if($isBig) { | |||
$html .= '<td></td>' ; | |||
} | |||
$html .= '<td>'.$orderManager->getCommentReport($order).'</td>'; | |||
if($pointSale->credit) { | |||
$credit = '' ; | |||
if(isset($order->user) && $order->user->id) { | |||
$userProducer = UserProducer::searchOne([ | |||
'id_user' => $order->user->id | |||
]); | |||
if($userProducer) { | |||
$credit = number_format($userProducer->credit,2).' €' ; | |||
} | |||
} | |||
$html .= '<td>'.$credit.'</td>' ; | |||
} | |||
$html .= '<td><strong>'.number_format($order->amount_with_tax, 2) . ' € '; | |||
if($orderManager->getPaymentStatus($order) == Order::PAYMENT_PAID) | |||
{ | |||
$html .= '(payé)' ; | |||
} | |||
elseif($orderManager->getPaymentStatus($order) == Order::PAYMENT_UNPAID && $orderManager->getOrderAmount($order, Order::AMOUNT_PAID)) | |||
{ | |||
$html .= '(reste '.$orderManager->getOrderAmount($order, Order::AMOUNT_REMAINING, true).' à payer)' ; | |||
} | |||
elseif($orderManager->getPaymentStatus($order) == Order::PAYMENT_SURPLUS) | |||
{ | |||
$html .= '(surplus : '.$orderManager->getOrderAmount($order, Order::PAYMENT_SURPLUS, true).' à rembourser)' ; | |||
} | |||
$html .= '</strong></td>' ; | |||
$html .= '</tr>' ; | |||
} | |||
$html .= '<tr><td><strong>Total</strong></td>' ; | |||
$strProducts = ''; | |||
$cpt = 0 ; | |||
foreach ($productsArray as $product) { | |||
foreach( Product::$unitsArray as $unit => $dataUnit) { | |||
$quantity = $orderManager->getProductQuantity($product, $pointSale->orders, false, $unit); | |||
if ($quantity) { | |||
$theUnit = ( $productManager->strUnit($unit, 'wording_short', true) == 'p.') ? '' : ' '. $productManager->strUnit($unit, 'wording_short', true) ; | |||
$strProducts .= '(' .$quantity .$theUnit.') '.$productManager->getNameExport($product) . '<br />'; | |||
} | |||
} | |||
if($isBig && $cpt == $limit) { | |||
$strProducts .= '</td><td>' ; | |||
} | |||
$cpt ++ ; | |||
} | |||
$html .= '<td>'.$strProducts.'</td><td></td>' ; | |||
if($pointSale->credit) { | |||
$html .= '<td></td>' ; | |||
} | |||
$html .= '<td><strong>'.Price::format($pointSale->revenues_with_tax) . '</strong></td>'; | |||
$html .= '</tbody></table><pagebreak>' ; | |||
} | |||
} | |||
// par point de vente | |||
$html .= '<h3>Points de vente</h3>' ; | |||
$html .= '<table class="">' | |||
. '<thead>' | |||
. '<tr>' | |||
. '<th>Point de vente</th>' | |||
. '<th>Produits</th>' | |||
. ( $isBig ? '<th>Produits</th>' : '') | |||
. '<th>Montant</th>' | |||
. '</tr>' | |||
. '<tbody>'; | |||
$revenues = 0 ; | |||
foreach ($pointsSaleArray as $pointSale) | |||
{ | |||
if (count($pointSale->orders)) | |||
{ | |||
$html .= '<tr><td>'.$pointSale->name.'</td><td>' ; | |||
$cpt = 0 ; | |||
foreach ($productsArray as $product) { | |||
foreach( Product::$unitsArray as $unit => $dataUnit) { | |||
$quantity = $orderManager->getProductQuantity($product, $pointSale->orders, false, $unit); | |||
if ($quantity) { | |||
$theUnit = ( $productManager->strUnit($unit, 'wording_short', true) == 'p.') ? '' : ' '. $productManager->strUnit($unit, 'wording_short', true) ; | |||
$html .= '(' .$quantity .$theUnit.') '.$productManager->getNameExport($product) . '<br />'; | |||
} | |||
} | |||
if($isBig && $cpt == $limit) { | |||
$html .= '</td><td>' ; | |||
} | |||
$cpt ++ ; | |||
} | |||
//$html = substr($html, 0, strlen($html) - 6) ; | |||
$html .= '</td><td>'.Price::format($pointSale->revenues_with_tax, 2).'</td></tr>' ; | |||
$revenues += $pointSale->revenues_with_tax ; | |||
} | |||
} | |||
// total | |||
$html .= '<tr><td><strong>Total</strong></td><td>' ; | |||
$cpt = 0 ; | |||
foreach ($productsArray as $product) { | |||
foreach( Product::$unitsArray as $unit => $dataUnit) { | |||
$quantity = $orderManager->getProductQuantity($product, $ordersArray, false, $unit); | |||
if ($quantity) { | |||
$theUnit = ( $productManager->strUnit($unit, 'wording_short', true) == 'p.') ? '' : ' '. $productManager->strUnit($unit, 'wording_short', true) ; | |||
$html .= '(' .$quantity .$theUnit.') '.$product->name . '<br />'; | |||
} | |||
} | |||
if($isBig && $cpt == $limit) { | |||
$html .= '</td><td>' ; | |||
} | |||
$cpt ++ ; | |||
} | |||
$html .= '</td><td><strong>'.number_format($revenues, 2).' €</strong></td></tr>' ; | |||
$html .= '</tbody></table>' ; | |||
echo $html ; | |||
?> |
@@ -99,21 +99,29 @@ $producer = GlobalParam::getCurrentProducer(); | |||
<i class="fa fa-caret-down"></i> | |||
</a> | |||
<ul class="dropdown-menu"> | |||
<li class="header"> <strong>Producteurs en ligne</strong></li> | |||
<li> | |||
<input type="text" class="search-producer form-control" placeholder="Rechercher" /> | |||
</li> | |||
<li class="li-alert-no-results"> | |||
<div class="alert alert-warning">Aucun producteur trouvé</div> | |||
</li> | |||
<?php $producersArray = Producer::find()->orderBy('name ASC')->all(); ?> | |||
<?php foreach ($producersArray as $producer): ?> | |||
<?php if ($producer->active == 1): ?> | |||
<li> | |||
<li class="producer"> | |||
<a href="<?= Yii::$app->urlManagerBackend->createUrl(['site/change-producer', 'id' => $producer->id]); ?>"><?= Html::encode($producer->name) ?></a> | |||
</li> | |||
<?php endif; ?> | |||
<?php endforeach; ?> | |||
<li class="header"><a href="javascript:void(0);" id="link-display-producers-offline">Afficher | |||
les producteurs hors-ligne</a></li> | |||
<!--<li class="header"><a href="javascript:void(0);" id="link-display-producers-offline">Afficher | |||
les producteurs hors-ligne</a></li>--> | |||
<?php foreach ($producersArray as $producer): ?> | |||
<?php if ($producer->active != 1): ?> | |||
<li class="offline"> | |||
<a href="<?= Yii::$app->urlManagerBackend->createUrl(['site/change-producer', 'id' => $producer->id]); ?>"><?= Html::encode($producer->name) ?></a> | |||
<li class="producer"> | |||
<a href="<?= Yii::$app->urlManagerBackend->createUrl(['site/change-producer', 'id' => $producer->id]); ?>"> | |||
<label class="label label-danger">Hors-ligne</label> | |||
<?= Html::encode($producer->name) ?> | |||
</a> | |||
</li> | |||
<?php endif; ?> | |||
<?php endforeach; ?> |
@@ -52,7 +52,7 @@ foreach ($pointsSaleArray as $pointSale) { | |||
if (count($pointSale->orders) && strlen($pointSale->$fieldInfosPointSale)) { | |||
$html .= '<h3>'.$pointSale->name.'</h3>' ; | |||
$colCredit = ($pointSale->credit) ? '<th>Rappel crédit</th>' : '' ; | |||
$colCredit = ($pointSale->credit) ? '<th>Crédit</th>' : '' ; | |||
$html .= '<table class="table table-bordered">' | |||
. '<thead>' | |||
@@ -115,15 +115,15 @@ foreach ($pointsSaleArray as $pointSale) { | |||
if($orderManager->getPaymentStatus($order) == Order::PAYMENT_PAID) | |||
{ | |||
$html .= '(payé)' ; | |||
$html .= '(débité)' ; | |||
} | |||
elseif($orderManager->getPaymentStatus($order) == Order::PAYMENT_UNPAID && $orderManager->getOrderAmount($order, Order::AMOUNT_PAID)) | |||
{ | |||
$html .= '(reste '.$orderManager->getOrderAmount($order, Order::AMOUNT_REMAINING, true).' à payer)' ; | |||
$html .= '(reste '.$orderManager->getOrderAmount($order, Order::AMOUNT_REMAINING, true).' à débiter)' ; | |||
} | |||
elseif($orderManager->getPaymentStatus($order) == Order::PAYMENT_SURPLUS) | |||
{ | |||
$html .= '(surplus : '.$orderManager->getOrderAmount($order, Order::PAYMENT_SURPLUS, true).' à rembourser)' ; | |||
$html .= '(surplus : '.$orderManager->getOrderAmount($order, Order::PAYMENT_SURPLUS, true).' à recréditer)' ; | |||
} | |||
$html .= '</strong></td>' ; |
@@ -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> |
@@ -60,12 +60,12 @@ $this->addBreadcrumb($this->getTitle()); | |||
<div class="user-update" id="app-producer-update"> | |||
<div id="nav-params"> | |||
<button v-for="section in sectionsArray" v-if="!section.isAdminSection || (section.isAdminSection && isAdmin)" | |||
<a v-for="section in sectionsArray" v-if="!section.isAdminSection || (section.isAdminSection && isAdmin)" | |||
:class="'btn '+((currentSection == section.name) ? 'btn-primary' : 'btn-default')" | |||
@click="changeSection(section)"> | |||
@click="changeSection(section)" :href="'#'+section.name"> | |||
{{ section.nameDisplay }} | |||
<span class="glyphicon glyphicon-triangle-bottom"></span> | |||
</button> | |||
</a> | |||
</div> | |||
<div class="user-form"> | |||
@@ -306,8 +306,22 @@ $this->addBreadcrumb($this->getTitle()); | |||
0 => 'Non', | |||
1 => 'Oui' | |||
], []); ?> | |||
<?= $form->field($model, 'option_export_display_column_delivery_note') | |||
->dropDownList([ | |||
0 => 'Non', | |||
1 => 'Oui' | |||
], []); ?> | |||
<h4>Divers</h4> | |||
<?php | |||
$choicesWeeksDistributionsActivatedInAdvanceArray = [null => '--']; | |||
for($i = 1; $i < 13; $i++) { | |||
$choicesWeeksDistributionsActivatedInAdvanceArray[$i] = $i.' semaine'.(($i > 1) ? 's' : ''); | |||
} | |||
?> | |||
<?= $form->field($model, 'option_weeks_distributions_activated_in_advance') | |||
->dropDownList($choicesWeeksDistributionsActivatedInAdvanceArray) | |||
->hint("Attention, les premières semaines doivent être activées manuellement."); ?> | |||
<?= $form->field($model, 'option_order_reference_type') | |||
->dropDownList([ | |||
Producer::ORDER_REFERENCE_TYPE_NONE => '--', | |||
@@ -481,9 +495,10 @@ $this->addBreadcrumb($this->getTitle()); | |||
<div v-show="currentSection == 'software'" class="panel panel-default"> | |||
<div class="panel-body"> | |||
<h4>Opendistrib</h4> | |||
<?php $urlAboutPage = Yii::$app->urlManagerFrontend->createAbsoluteUrl(['site/about']); ?> | |||
<?= $form->field($model, 'option_testimony') | |||
->textarea(['rows' => 7]) | |||
->hint("Écrivez ici votre témoignage concernant l'utilisation du logiciel. Il sera publié sur la page 'À propos' du site.") ; ?> | |||
->hint("Écrivez ici votre témoignage concernant l'utilisation du logiciel. Il sera publié sur la page <a href=\"".$urlAboutPage."\" target=\"_blanck\">À propos</a> du site.") ; ?> | |||
<?= $form->field($model, 'option_time_saved') | |||
->dropDownList([ | |||
null => '--', | |||
@@ -497,7 +512,7 @@ $this->addBreadcrumb($this->getTitle()); | |||
7 => '7 heures', | |||
8 => '8 heures', | |||
]) | |||
->hint("Sélectionnez le temps que vous estimez gagner chaque semaine en utilisant ce logiciel. Cette donnée sera utilisée sur la page 'À propos' du site.") ; ?> | |||
->hint("Sélectionnez le temps que vous estimez gagner chaque semaine en utilisant ce logiciel. Cette donnée sera utilisée sur la page <a href=\"".$urlAboutPage."\" target=\"_blanck\">À propos</a> du site.") ; ?> | |||
<?= $form->field($model, 'option_display_message_new_opendistrib_version') | |||
->dropDownList([ | |||
1 => 'Oui', |
@@ -43,15 +43,19 @@ use yii\grid\GridView; | |||
$ticketManager = TicketManager::getInstance(); | |||
$userCurrent = $this->getUserCurrent(); | |||
$this->setTitle('Support'); | |||
$this->setTitle('Support & contact'); | |||
$this->addBreadcrumb($this->getTitle()); | |||
?> | |||
<div class="support-index"> | |||
<?php if($context == 'producer'): ?> | |||
<div class="callout callout-info"> | |||
<p><i class="icon fa fa-info-circle"></i> Pour toutes vos remarques, suggestions et remontées de bugs.</p> | |||
</div> | |||
<div> | |||
<div class="col-md-4"> | |||
<div class="col-md-6 col-left"> | |||
<div class="info-box"> | |||
<span class="info-box-icon bg-yellow"><i class="fa fa-phone"></i></span> | |||
<div class="info-box-content"> | |||
@@ -63,7 +67,7 @@ $this->addBreadcrumb($this->getTitle()); | |||
</div> | |||
</div> | |||
</div> | |||
<div class="col-md-4"> | |||
<div class="col-md-6 col-right"> | |||
<div class="info-box"> | |||
<span class="info-box-icon bg-yellow"><i class="fa fa-calendar"></i></span> | |||
<div class="info-box-content"> | |||
@@ -73,7 +77,7 @@ $this->addBreadcrumb($this->getTitle()); | |||
</div> | |||
</div> | |||
</div> | |||
<div class="col-md-4"> | |||
<div class="col-md-6 col-left"> | |||
<div class="info-box"> | |||
<span class="info-box-icon bg-yellow"><i class="fa fa-comments"></i></span> | |||
<div class="info-box-content"> | |||
@@ -81,6 +85,14 @@ $this->addBreadcrumb($this->getTitle()); | |||
</div> | |||
</div> | |||
</div> | |||
<div class="col-md-6 col-right"> | |||
<div class="info-box"> | |||
<span class="info-box-icon bg-yellow"><i class="fa fa-envelope"></i></span> | |||
<div class="info-box-content"> | |||
<span class="info-box-text"><br/><?= Html::a("M'envoyer un email", 'mailto:'.Yii::$app->parameterBag->get('adminEmail'), ['class' => 'btn btn-sm btn-default']); ?></span> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="clr"></div> | |||
<?php endif; ?> |
@@ -29,6 +29,15 @@ $this->addBreadcrumb('Voir un ticket'); | |||
<td><strong>Statut</strong></td> | |||
<td><?= $ticketManager->getTicketStatusLabelAsHtml($ticket); ?></td> | |||
</tr> | |||
<?php if($userManager->isCurrentAdmin()): ?> | |||
<tr> | |||
<td><strong>Producteur</strong></td> | |||
<td><?= $ticketManager->isTicketUnread($ticket, $ticket->user) ? | |||
'<span class="label label-warning">Non lu</span>' : | |||
'<span class="label label-success">Lu</span>'; ?> | |||
</td> | |||
</tr> | |||
<?php endif; ?> | |||
</tbody> | |||
</table> | |||
</div> |
@@ -63,6 +63,7 @@ $producerManager = $this->getProducerManager(); | |||
<?= $form->field($model, 'name')->textInput() ?> | |||
<?= $form->field($model, 'phone')->textInput() ?> | |||
<?= $form->field($model, 'email')->textInput() ?> | |||
<?= $form->field($model, 'newsletter')->checkbox() ?> | |||
<?= $form->field($model, 'address')->textarea() ?> | |||
<?php if ($producerManager->getConfig('option_export_evoliz')): ?> |
@@ -109,6 +109,22 @@ $this->render('_menu', [ | |||
return $html; | |||
} | |||
], | |||
[ | |||
'attribute' => 'newsletter', | |||
'header' => "Inscrit au bulletin<br/>d'information", | |||
'format' => 'raw', | |||
'headerOptions' => ['class' => 'column-hide-on-mobile'], | |||
'filterOptions' => ['class' => 'column-hide-on-mobile'], | |||
'contentOptions' => ['class' => 'column-hide-on-mobile'], | |||
'value' => function ($model) { | |||
$userManager = UserManager::getInstance(); | |||
if($userManager->isUserSubscribedNewsletter($model)) { | |||
return '<span class="label label-success">Oui</span>'; | |||
} | |||
return '<span class="label label-danger">Non</span>'; | |||
} | |||
], | |||
[ | |||
'class' => 'yii\grid\ActionColumn', | |||
'header' => 'Commandes', | |||
@@ -159,6 +175,7 @@ $this->render('_menu', [ | |||
) . ' | |||
</span> | |||
</div>'; | |||
return $html; | |||
} | |||
], |
@@ -431,7 +431,7 @@ a.btn.btn-primary .glyphicon-triangle-bottom, button.btn.btn-primary .glyphicon- | |||
margin-bottom: 30px; | |||
} | |||
/* line 347, ../sass/screen.scss */ | |||
#nav-params button { | |||
#nav-params a { | |||
margin-right: 10px; | |||
} | |||
@@ -1660,93 +1660,113 @@ body.skin-black .main-header .notifications-menu ul.menu li a h5 small { | |||
body.skin-black .main-header .notifications-menu ul.menu li a p { | |||
margin-left: 10px; | |||
} | |||
/* line 136, ../sass/_adminlte.scss */ | |||
/* line 137, ../sass/_adminlte.scss */ | |||
body.skin-black .main-header .navbar .nav li.producer-menu .dropdown-menu { | |||
width: 400px; | |||
} | |||
/* line 141, ../sass/_adminlte.scss */ | |||
body.skin-black .main-header .navbar .nav li.producer-menu .search-producer { | |||
margin: 10px; | |||
width: 94%; | |||
} | |||
/* line 146, ../sass/_adminlte.scss */ | |||
body.skin-black .main-header .navbar .nav li.producer-menu .li-alert-no-results { | |||
display: none; | |||
} | |||
/* line 149, ../sass/_adminlte.scss */ | |||
body.skin-black .main-header .navbar .nav li.producer-menu .li-alert-no-results .alert { | |||
margin-bottom: 0px; | |||
margin-left: 10px; | |||
margin-right: 10px; | |||
padding: 15px 15px 10px 15px; | |||
} | |||
/* line 157, ../sass/_adminlte.scss */ | |||
body.skin-black .main-header .navbar .nav li.producer-menu .label { | |||
position: relative; | |||
top: -2px; | |||
left: 0px; | |||
} | |||
/* line 142, ../sass/_adminlte.scss */ | |||
/* line 163, ../sass/_adminlte.scss */ | |||
body.skin-black .main-header .navbar .nav li.producer-menu #link-display-producers-offline { | |||
color: #F39C12; | |||
} | |||
/* line 146, ../sass/_adminlte.scss */ | |||
/* line 167, ../sass/_adminlte.scss */ | |||
body.skin-black .main-header .navbar .nav li.producer-menu .offline { | |||
display: none; | |||
} | |||
/* line 153, ../sass/_adminlte.scss */ | |||
/* line 174, ../sass/_adminlte.scss */ | |||
body.skin-black .sidebar .sidebar-menu > li.header { | |||
color: #899397; | |||
} | |||
/* line 158, ../sass/_adminlte.scss */ | |||
/* line 179, ../sass/_adminlte.scss */ | |||
body.skin-black .sidebar-menu > li.active > a { | |||
border-color: #F39C12; | |||
} | |||
/* line 163, ../sass/_adminlte.scss */ | |||
/* line 184, ../sass/_adminlte.scss */ | |||
body.skin-black section.sidebar .user-panel { | |||
text-align: center; | |||
} | |||
/* line 166, ../sass/_adminlte.scss */ | |||
/* line 187, ../sass/_adminlte.scss */ | |||
body.skin-black section.sidebar .user-panel .image { | |||
margin-bottom: 3px; | |||
} | |||
/* line 170, ../sass/_adminlte.scss */ | |||
/* line 191, ../sass/_adminlte.scss */ | |||
body.skin-black section.sidebar .user-panel .title { | |||
font-weight: bold; | |||
color: white; | |||
} | |||
/* line 177, ../sass/_adminlte.scss */ | |||
/* line 198, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper { | |||
background-color: #f5f5f5; | |||
} | |||
/* line 180, ../sass/_adminlte.scss */ | |||
/* line 201, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .content-header { | |||
background-color: #F5F5F5; | |||
padding-bottom: 15px; | |||
border-bottom: solid 1px #e0e0e0; | |||
border-top: solid 1px #e0e0e0; | |||
} | |||
/* line 186, ../sass/_adminlte.scss */ | |||
/* line 207, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .content-header .btn { | |||
padding: 3px 6px; | |||
font-size: 10px; | |||
font-family: Arial; | |||
text-transform: uppercase; | |||
} | |||
/* line 193, ../sass/_adminlte.scss */ | |||
/* line 214, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .content-header h1 { | |||
font-family: 'myriadpro-light'; | |||
font-size: 20px; | |||
} | |||
/* line 199, ../sass/_adminlte.scss */ | |||
/* line 220, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper a { | |||
color: #e08e0b; | |||
} | |||
/* line 203, ../sass/_adminlte.scss */ | |||
/* line 224, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .btn { | |||
color: white; | |||
} | |||
/* line 207, ../sass/_adminlte.scss */ | |||
/* line 228, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .btn-default { | |||
color: #333; | |||
background-color: white; | |||
} | |||
/* line 212, ../sass/_adminlte.scss */ | |||
/* line 233, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .btn-primary { | |||
background-color: #F39C12; | |||
color: white; | |||
border-color: #F39C12; | |||
} | |||
/* line 219, ../sass/_adminlte.scss */ | |||
/* line 240, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .alert a { | |||
color: white; | |||
} | |||
/* line 222, ../sass/_adminlte.scss */ | |||
/* line 243, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .alert a.btn { | |||
color: #333; | |||
text-decoration: none; | |||
} | |||
/* line 227, ../sass/_adminlte.scss */ | |||
/* line 248, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .alert .close { | |||
font-size: 30px; | |||
position: relative; | |||
@@ -1755,89 +1775,89 @@ body.skin-black .content-wrapper .alert .close { | |||
color: white; | |||
opacity: 0.6; | |||
} | |||
/* line 235, ../sass/_adminlte.scss */ | |||
/* line 256, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .alert .close:hover { | |||
opacity: 1; | |||
} | |||
/* line 242, ../sass/_adminlte.scss */ | |||
/* line 263, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .callout h4 .fa { | |||
margin-right: 7px; | |||
} | |||
/* line 245, ../sass/_adminlte.scss */ | |||
/* line 266, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .callout a { | |||
color: white; | |||
} | |||
/* line 248, ../sass/_adminlte.scss */ | |||
/* line 269, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .callout .btn { | |||
color: #333; | |||
text-decoration: none; | |||
} | |||
/* line 255, ../sass/_adminlte.scss */ | |||
/* line 276, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .table th { | |||
font-size: 13px; | |||
} | |||
/* line 258, ../sass/_adminlte.scss */ | |||
/* line 279, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .table th.column-actions, body.skin-black .content-wrapper .table td.column-actions { | |||
width: 150px; | |||
text-align: right; | |||
} | |||
/* line 262, ../sass/_adminlte.scss */ | |||
/* line 283, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .table td.text-small, body.skin-black .content-wrapper .table th.text-small { | |||
font-size: 12px; | |||
} | |||
/* line 267, ../sass/_adminlte.scss */ | |||
/* line 288, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .pagination > .active > a, body.skin-black .content-wrapper .pagination > .active > span, body.skin-black .content-wrapper .pagination > .active > a:hover, body.skin-black .content-wrapper .pagination > .active > span:hover, body.skin-black .content-wrapper .pagination > .active > a:focus, body.skin-black .content-wrapper .pagination > .active > span:focus { | |||
background-color: #F39C12; | |||
border: solid 1px #F39C12; | |||
color: white; | |||
} | |||
/* line 272, ../sass/_adminlte.scss */ | |||
/* line 293, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .pagination > li > a, body.skin-black .content-wrapper .pagination > li > span { | |||
color: #F39C12; | |||
} | |||
/* line 274, ../sass/_adminlte.scss */ | |||
/* line 295, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .pagination > li > a:hover, body.skin-black .content-wrapper .pagination > li > span:hover { | |||
color: #c87f0a; | |||
} | |||
/* line 279, ../sass/_adminlte.scss */ | |||
/* line 300, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .submenu { | |||
margin-bottom: 25px; | |||
} | |||
/* line 285, ../sass/_adminlte.scss */ | |||
/* line 306, ../sass/_adminlte.scss */ | |||
body.skin-black .main-footer a { | |||
color: #F39C12; | |||
} | |||
/* line 291, ../sass/_adminlte.scss */ | |||
/* line 312, ../sass/_adminlte.scss */ | |||
body.login-page { | |||
background: none; | |||
background-color: white; | |||
} | |||
/* line 295, ../sass/_adminlte.scss */ | |||
/* line 316, ../sass/_adminlte.scss */ | |||
body.login-page .login-box .login-logo { | |||
text-align: center; | |||
font-family: 'highvoltageregular'; | |||
} | |||
/* line 299, ../sass/_adminlte.scss */ | |||
/* line 320, ../sass/_adminlte.scss */ | |||
body.login-page .login-box .login-logo img { | |||
width: 50px; | |||
} | |||
/* line 304, ../sass/_adminlte.scss */ | |||
/* line 325, ../sass/_adminlte.scss */ | |||
body.login-page .login-box .login-box-body .btn-primary { | |||
background-color: #F39C12; | |||
border-color: #F39C12; | |||
padding: 5px 10px; | |||
} | |||
/* line 309, ../sass/_adminlte.scss */ | |||
/* line 330, ../sass/_adminlte.scss */ | |||
body.login-page .login-box .login-box-body .btn-primary:active { | |||
background-color: #f4a62a; | |||
border-color: #F39C12; | |||
} | |||
/* line 315, ../sass/_adminlte.scss */ | |||
/* line 336, ../sass/_adminlte.scss */ | |||
body.login-page .login-box .login-box-body a { | |||
color: #F39C12; | |||
} | |||
/* line 317, ../sass/_adminlte.scss */ | |||
/* line 338, ../sass/_adminlte.scss */ | |||
body.login-page .login-box .login-box-body a:hover { | |||
color: #f4a62a; | |||
} | |||
@@ -2695,24 +2715,32 @@ termes. | |||
padding-left: 25px; | |||
} | |||
/* line 6, ../sass/support/_index.scss */ | |||
/* line 4, ../sass/support/_index.scss */ | |||
.support-index .col-left { | |||
padding-left: 0px; | |||
} | |||
/* line 7, ../sass/support/_index.scss */ | |||
.support-index .col-right { | |||
padding-right: 0px; | |||
} | |||
/* line 13, ../sass/support/_index.scss */ | |||
.support-index .ticket-list .nav-tabs .label { | |||
position: relative; | |||
top: -2px; | |||
left: 2px; | |||
padding: 0.3em 0.6em 0.2em 0.6em; | |||
} | |||
/* line 15, ../sass/support/_index.scss */ | |||
/* line 22, ../sass/support/_index.scss */ | |||
.support-index .ticket-list .table .filters { | |||
display: none; | |||
} | |||
/* line 19, ../sass/support/_index.scss */ | |||
/* line 26, ../sass/support/_index.scss */ | |||
.support-index .ticket-list .table .td-created-at, | |||
.support-index .ticket-list .table .td-last-message, | |||
.support-index .ticket-list .table .td-messages { | |||
width: 100px; | |||
} | |||
/* line 24, ../sass/support/_index.scss */ | |||
/* line 31, ../sass/support/_index.scss */ | |||
.support-index .ticket-list .table .td-producer { | |||
width: 200px; | |||
} |
@@ -64,6 +64,40 @@ var UrlManager = { | |||
}; | |||
function opendistrib_dropdown_producers() { | |||
$('.producer-menu .dropdown-toggle').click(function() { | |||
$('.producer-menu .search-producer').focus(); | |||
}); | |||
$('.producer-menu .search-producer').keyup(function() { | |||
var $alertNoResults = $('.producer-menu .li-alert-no-results'); | |||
var searchWords = $(this).val().toLowerCase(); | |||
var count = 0; | |||
if(searchWords && searchWords.length > 0) { | |||
$('.producer-menu li.producer').each(function() { | |||
if($(this).find('a').text().toLowerCase().indexOf(searchWords) >= 0 || !searchWords) { | |||
$(this).show(); | |||
count ++; | |||
} | |||
else { | |||
$(this).hide(); | |||
} | |||
}); | |||
if(count) { | |||
$alertNoResults.hide(); | |||
} | |||
else { | |||
$alertNoResults.show(); | |||
} | |||
} | |||
else { | |||
$alertNoResults.hide(); | |||
$('.producer-menu li.producer').show(); | |||
} | |||
}); | |||
$('#link-display-producers-offline').click(function() { | |||
$(this).hide(); | |||
$('.producer-menu .offline').show(); |
@@ -39,7 +39,7 @@ var app = new Vue({ | |||
el: '#app-producer-update', | |||
data() { | |||
return Object.assign({ | |||
currentSection: 'general', | |||
currentSection: this.getInitialSection(), | |||
sectionsArray: [ | |||
{ | |||
name: 'general', | |||
@@ -92,7 +92,18 @@ var app = new Vue({ | |||
methods: { | |||
changeSection: function(section) { | |||
this.currentSection = section.name ; | |||
}, | |||
getInitialSection: function() { | |||
var hash = window.location.hash.substring(1); | |||
if(hash && hash.length) { | |||
return hash; | |||
} | |||
return 'general'; | |||
} | |||
}, | |||
mounted: function() { | |||
} | |||
}); | |||
@@ -133,6 +133,27 @@ body.skin-black { | |||
} | |||
.navbar .nav li.producer-menu { | |||
.dropdown-menu { | |||
width: 400px; | |||
} | |||
.search-producer { | |||
margin: 10px; | |||
width: 94%; | |||
} | |||
.li-alert-no-results { | |||
display: none; | |||
.alert { | |||
margin-bottom: 0px; | |||
margin-left: 10px; | |||
margin-right: 10px; | |||
padding: 15px 15px 10px 15px; | |||
} | |||
} | |||
.label { | |||
position: relative ; | |||
top: -2px ; |
@@ -344,7 +344,7 @@ a.btn, button.btn { | |||
#nav-params { | |||
margin-bottom: 30px ; | |||
button { | |||
a { | |||
margin-right: 10px ; | |||
} | |||
} |
@@ -1,7 +1,14 @@ | |||
.support-index { | |||
.ticket-list { | |||
.col-left { | |||
padding-left: 0px; | |||
} | |||
.col-right { | |||
padding-right: 0px; | |||
} | |||
.ticket-list { | |||
.nav-tabs { | |||
.label { | |||
position: relative; |
@@ -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; | |||
} | |||
} |
@@ -18,6 +18,7 @@ use common\logic\Document\Invoice\Wrapper\InvoiceContainer; | |||
use common\logic\Document\Invoice\Wrapper\InvoiceManager; | |||
use common\logic\Document\Quotation\Wrapper\QuotationContainer; | |||
use common\logic\Document\Quotation\Wrapper\QuotationManager; | |||
use common\logic\Opinion\Wrapper\OpinionManager; | |||
use common\logic\Order\Order\Wrapper\OrderContainer; | |||
use common\logic\Order\Order\Wrapper\OrderManager; | |||
use common\logic\Order\ProductOrder\Wrapper\ProductOrderContainer; | |||
@@ -61,6 +62,11 @@ use common\logic\User\UserUserGroup\Wrapper\UserUserGroupManager; | |||
trait BusinessLogicTrait | |||
{ | |||
public function getOpinionManager(): OpinionManager | |||
{ | |||
return OpinionManager::getInstance(); | |||
} | |||
public function getUserProducerManager(): UserProducerManager | |||
{ | |||
return UserProducerManager::getInstance(); |
@@ -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); | |||
} | |||
} |
@@ -21,9 +21,12 @@ class MailerService | |||
$message->send(); | |||
} | |||
public function sendAdmin(string $subject, string $view, array $params = []) | |||
public function sendAdmin(string $subject, string $view, array $params = [], string $replyTo = null) | |||
{ | |||
$message = $this->composeBase(\Yii::$app->parameterBag->get('adminEmail'), $view, $params); | |||
if($replyTo) { | |||
$message->setReplyTo($replyTo); | |||
} | |||
$this->initMessageFromSite($message, $subject); | |||
$message->send(); | |||
} |
@@ -37,7 +37,9 @@ | |||
*/ | |||
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; | |||
use common\logic\User\CreditHistory\Model\CreditHistory; | |||
@@ -128,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(); | |||
}, | |||
@@ -141,6 +149,9 @@ return [ | |||
Distribution::class => [ | |||
common\logic\Subscription\Subscription\Event\DistributionObserver::class | |||
], | |||
DeliveryNote::class => [ | |||
common\logic\Order\Order\Event\DeliveryNoteObserver::class | |||
], | |||
Ticket::class => [ | |||
common\logic\User\User\Event\TicketObserver::class, | |||
], |
@@ -0,0 +1,45 @@ | |||
<?php | |||
namespace common\helpers; | |||
class Ajax | |||
{ | |||
const RESPONSE_TYPE_ERROR = 'error'; | |||
const RESPONSE_TYPE_SUCCESS = 'success'; | |||
public static function responseSuccess(string $message): array | |||
{ | |||
return self::response(self::RESPONSE_TYPE_SUCCESS, $message); | |||
} | |||
public static function responseError(string $message): array | |||
{ | |||
return self::response(self::RESPONSE_TYPE_ERROR, $message); | |||
} | |||
private static function response(string $responseType, string $message): array | |||
{ | |||
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; | |||
return [ | |||
'return' => $responseType, | |||
'alert' => [ | |||
'type' => self::getAlertClass($responseType), | |||
'message' => $message | |||
] | |||
]; | |||
} | |||
private static function getAlertClass(string $responseType) | |||
{ | |||
$class = ''; | |||
if($responseType == self::RESPONSE_TYPE_SUCCESS) { | |||
$class = 'success'; | |||
} | |||
elseif($responseType == self::RESPONSE_TYPE_ERROR) { | |||
$class = 'danger'; | |||
} | |||
return $class; | |||
} | |||
} |
@@ -0,0 +1,8 @@ | |||
<?php | |||
namespace common\logic; | |||
abstract class AbstractUtils extends AbstractService implements UtilsInterface | |||
{ | |||
} |
@@ -5,5 +5,5 @@ namespace common\logic; | |||
interface ContainerInterface | |||
{ | |||
public function getServices(): array; | |||
public function getDefinition(): DefinitionInterface; | |||
//public function getDefinition(): DefinitionInterface; | |||
} |
@@ -182,7 +182,6 @@ class DistributionBuilder extends AbstractBuilder | |||
/** | |||
* Active ou désactive la distribution. | |||
*/ | |||
// active | |||
public function activeDistribution(Distribution $distribution, bool $active = true): void | |||
{ | |||
$distribution->active = (int) $active; | |||
@@ -196,4 +195,10 @@ class DistributionBuilder extends AbstractBuilder | |||
$distribution->trigger(Distribution::EVENT_ACTIVE, $distributionActiveEvent); | |||
} | |||
} | |||
public function activeDistributionByDate(\DateTime $date): void | |||
{ | |||
$distribution = $this->createDistributionIfNotExist($date->format('Y-m-d')); | |||
$this->activeDistribution($distribution); | |||
} | |||
} |
@@ -78,7 +78,6 @@ class DistributionReportGridPdfGenerator extends AbstractGenerator | |||
$orientationPdf = Pdf::ORIENT_LANDSCAPE; | |||
} | |||
// get your HTML raw content without any layouts or scripts | |||
$content = \Yii::$app->getView()->render($viewPdf, [ | |||
'date' => $distribution->date, | |||
'distribution' => $distribution, | |||
@@ -92,17 +91,11 @@ class DistributionReportGridPdfGenerator extends AbstractGenerator | |||
$dateStr = date('d/m/Y', strtotime($distribution->date)); | |||
if ($save) { | |||
$destination = Pdf::DEST_FILE; | |||
} else { | |||
$destination = Pdf::DEST_BROWSER; | |||
} | |||
$pdf = new Pdf([ | |||
'mode' => Pdf::MODE_UTF8, | |||
'format' => Pdf::FORMAT_A4, | |||
'orientation' => $orientationPdf, | |||
'destination' => $destination, | |||
'destination' => $save ? Pdf::DEST_FILE : Pdf::DEST_BROWSER, | |||
'filename' => \Yii::getAlias( | |||
'@app/web/pdf/Commandes-' . $distribution->date . '-' . $producer->id . '.pdf' | |||
), |
@@ -2,22 +2,36 @@ | |||
namespace common\logic\Distribution\Distribution\Service; | |||
use common\helpers\Price; | |||
use common\logic\AbstractGenerator; | |||
use common\logic\Distribution\Distribution\Model\Distribution; | |||
use common\logic\Distribution\ProductDistribution\Repository\ProductDistributionRepository; | |||
use common\logic\Document\Document\Service\DocumentSolver; | |||
use common\logic\Order\Order\Model\Order; | |||
use common\logic\Order\Order\Repository\OrderRepository; | |||
use common\logic\Order\Order\Service\OrderBuilder; | |||
use common\logic\Order\Order\Service\OrderSolver; | |||
use common\logic\PointSale\PointSale\Model\PointSale; | |||
use common\logic\PointSale\PointSale\Repository\PointSaleRepository; | |||
use common\logic\Producer\Producer\Model\Producer; | |||
use common\logic\Product\Product\Model\Product; | |||
use common\logic\Product\Product\Repository\ProductRepository; | |||
use common\logic\Product\Product\Service\ProductSolver; | |||
use common\logic\User\UserProducer\Model\UserProducer; | |||
use kartik\mpdf\Pdf; | |||
class DistributionReportPdfGenerator extends AbstractGenerator | |||
{ | |||
const LIMIT_PRODUCTS = 100; | |||
protected OrderRepository $orderRepository; | |||
protected OrderBuilder $orderBuilder; | |||
protected ProductRepository $productRepository; | |||
protected ProductDistributionRepository $productDistributionRepository; | |||
protected PointSaleRepository $pointSaleRepository; | |||
protected OrderSolver $orderSolver; | |||
protected ProductSolver $productSolver; | |||
protected DocumentSolver $documentSolver; | |||
public function loadDependencies(): void | |||
{ | |||
@@ -26,6 +40,9 @@ class DistributionReportPdfGenerator extends AbstractGenerator | |||
$this->productRepository = $this->loadService(ProductRepository::class); | |||
$this->productDistributionRepository = $this->loadService(ProductDistributionRepository::class); | |||
$this->pointSaleRepository = $this->loadService(PointSaleRepository::class); | |||
$this->orderSolver = $this->loadService(OrderSolver::class); | |||
$this->productSolver = $this->loadService(ProductSolver::class); | |||
$this->documentSolver = $this->loadService(DocumentSolver::class); | |||
} | |||
public function generateDistributionReportPdf(Distribution $distribution, bool $save = false) | |||
@@ -38,39 +55,31 @@ class DistributionReportPdfGenerator extends AbstractGenerator | |||
foreach ($pointsSaleArray as $pointSale) { | |||
$this->orderBuilder->initPointSaleOrders($pointSale, $ordersArray); | |||
} | |||
$viewPdf = '@backend/views/distribution/report'; | |||
$orientationPdf = Pdf::ORIENT_PORTRAIT; | |||
$isBig = count($productsArray) > self::LIMIT_PRODUCTS; | |||
if ($producer->slug == 'bourlinguepacotille') { | |||
$viewPdf = '@backend/views/distribution/report-bourlingue'; | |||
$orientationPdf = Pdf::ORIENT_LANDSCAPE; | |||
$content = \Yii::$app->getView()->render($viewPdf, [ | |||
'date' => $distribution->date, | |||
'distribution' => $distribution, | |||
'selectedProductsArray' => $selectedProductsArray, | |||
'pointsSaleArray' => $pointsSaleArray, | |||
'productsArray' => $productsArray, | |||
'ordersArray' => $ordersArray, | |||
'producer' => $producer | |||
]); | |||
} | |||
// get your HTML raw content without any layouts or scripts | |||
$content = \Yii::$app->getView()->render($viewPdf, [ | |||
'date' => $distribution->date, | |||
'distribution' => $distribution, | |||
'selectedProductsArray' => $selectedProductsArray, | |||
'pointsSaleArray' => $pointsSaleArray, | |||
'productsArray' => $productsArray, | |||
'ordersArray' => $ordersArray, | |||
'producer' => $producer | |||
]); | |||
$dateStr = date('d/m/Y', strtotime($distribution->date)); | |||
if ($save) { | |||
$destination = Pdf::DEST_FILE; | |||
} else { | |||
$destination = Pdf::DEST_BROWSER; | |||
else { | |||
$orientationPdf = Pdf::ORIENT_PORTRAIT; | |||
$content = $this->buildReportHtml($pointsSaleArray, $productsArray, $ordersArray, $isBig); | |||
} | |||
$pdf = new Pdf([ | |||
'mode' => Pdf::MODE_UTF8, | |||
'format' => Pdf::FORMAT_A4, | |||
'orientation' => $orientationPdf, | |||
'destination' => $destination, | |||
'destination' => $save ? Pdf::DEST_FILE : Pdf::DEST_BROWSER, | |||
'filename' => \Yii::getAlias( | |||
'@app/web/pdf/Commandes-' . $distribution->date . '-' . $this->getProducerContextId() . '.pdf' | |||
), | |||
@@ -103,11 +112,272 @@ class DistributionReportPdfGenerator extends AbstractGenerator | |||
} | |||
', | |||
'methods' => [ | |||
'SetHeader' => ['Commandes du ' . $dateStr], | |||
'SetHeader' => ['Commandes du ' . date('d/m/Y', strtotime($distribution->date))], | |||
'SetFooter' => ['{PAGENO}'], | |||
] | |||
]); | |||
return $pdf->render(); | |||
} | |||
public function buildReportHtml(array $pointsSaleArray, array $productsArray, array $ordersArray, bool $isBig): string | |||
{ | |||
$html = $this->buildReportPointsSaleHtml($pointsSaleArray, $productsArray, $isBig); | |||
$html .= $this->buildReportPointsSaleTotalHtml($pointsSaleArray, $productsArray, $ordersArray, $isBig); | |||
return $html; | |||
} | |||
public function buildReportPointsSaleHtml(array $pointsSaleArray, array $productsArray, bool $isBig): string | |||
{ | |||
$producer = $this->getProducerContext(); | |||
$html = '' ; | |||
foreach ($pointsSaleArray as $pointSale) { | |||
if (count($pointSale->orders)) { | |||
$html .= '<h3>'.$pointSale->name.'</h3>' ; | |||
$columnDeliveryNote = ($producer->option_export_display_column_delivery_note) ? '<th>BL</th>' : ''; | |||
$colCredit = ($pointSale->credit) ? '<th>Crédit</th>' : '' ; | |||
$html .= '<table class="">' | |||
. '<thead>' | |||
. '<tr>' | |||
. '<th>Client</th>' | |||
. '<th>Produits</th>' | |||
. ($isBig ? '<th>Produits</th>' : '') | |||
. '<th>Commentaire</th>' | |||
. $columnDeliveryNote | |||
. $colCredit | |||
. '<th>Montant</th>' | |||
. '</tr>' | |||
. '</thead>' | |||
. '<tbody>'; | |||
foreach ($pointSale->orders as $order) { | |||
$html .= '<tr>' ; | |||
$html .= $this->columnUsername($order); | |||
$html .= $this->columnOrderProducts($order, $productsArray); | |||
$html .= $this->columnIfIsBig($isBig); | |||
$html .= $this->columnComment($order); | |||
$html .= $this->columnDeliveryNote($order); | |||
$html .= $this->columnCredit($order, $pointSale); | |||
$html .= $this->columnOrderAmount($order); | |||
$html .= '</tr>' ; | |||
} | |||
$html .= '<tr><td><strong>Total</strong></td>' ; | |||
$strProducts = ''; | |||
$cpt = 0 ; | |||
foreach ($productsArray as $product) { | |||
foreach( Product::$unitsArray as $unit => $dataUnit) { | |||
$quantity = $this->orderSolver->getProductQuantity($product, $pointSale->orders, false, $unit); | |||
if ($quantity) { | |||
$theUnit = ( $this->productSolver->strUnit($unit, 'wording_short', true) == 'p.') ? '' : ' '. $this->productSolver->strUnit($unit, 'wording_short', true) ; | |||
$strProducts .= '(' .$quantity .$theUnit.') '.$this->productSolver->getNameExport($product) . '<br />'; | |||
} | |||
} | |||
if($isBig && $cpt == self::LIMIT_PRODUCTS) { | |||
$strProducts .= '</td><td>' ; | |||
} | |||
$cpt ++ ; | |||
} | |||
$html .= '<td>'.$strProducts.'</td><td></td>' ; | |||
if($pointSale->credit) { | |||
$html .= '<td></td>' ; | |||
} | |||
if($producer->option_export_display_column_delivery_note) { | |||
$html .= '<td></td>' ; | |||
} | |||
$html .= '<td><strong>'.Price::format($pointSale->revenues_with_tax) . '</strong></td>'; | |||
$html .= '</tbody></table><pagebreak>' ; | |||
} | |||
} | |||
return $html; | |||
} | |||
public function columnUsername(Order $order): string | |||
{ | |||
$producer = $this->getProducerContext(); | |||
$strUser = $this->orderSolver->getOrderUsername($order) ; | |||
if(strlen($order->comment_point_sale)) | |||
{ | |||
$strUser .= '<br /><em>'.$order->comment_point_sale.'</em>' ; | |||
} | |||
if (isset($order->user) && strlen($order->user->phone)) { | |||
$strUser .= '<br />' . $order->user->phone . ''; | |||
} | |||
if($producer->option_order_reference_type == Producer::ORDER_REFERENCE_TYPE_YEARLY && $order->reference && strlen($order->reference) > 0) { | |||
$strUser .= '<br />'.$order->reference ; | |||
} | |||
return '<td>'.$strUser.'</td>'; | |||
} | |||
public function columnOrderProducts(Order $order, array $productsArray): string | |||
{ | |||
$strProducts = ''; | |||
foreach ($productsArray as $product) { | |||
foreach ($order->productOrder as $productOrder) { | |||
if($product->id == $productOrder->id_product) { | |||
$unit = ( $this->productSolver->strUnit($productOrder->unit, 'wording_short', true) == 'p.') ? '' : ' '. $this->productSolver->strUnit($productOrder->unit, 'wording_short', true) ; | |||
$strProducts .= '('.$productOrder->quantity .$unit.') '.$this->productSolver->getNameExport($product) . '<br />'; | |||
} | |||
} | |||
} | |||
return '<td>'.substr($strProducts, 0, strlen($strProducts) - 6).'</td>'; | |||
} | |||
public function columnIfIsBig(bool $isBig): string | |||
{ | |||
if($isBig) { | |||
return '<td></td>' ; | |||
} | |||
return ''; | |||
} | |||
public function columnComment(Order $order): string | |||
{ | |||
return '<td>'.$this->orderSolver->getCommentReport($order).'</td>';; | |||
} | |||
public function columnDeliveryNote(Order $order): string | |||
{ | |||
$producer = $this->getProducerContext(); | |||
if($producer->option_export_display_column_delivery_note) { | |||
$contentColumnDeliveryNote = ''; | |||
if($order->deliveryNote) { | |||
if($this->documentSolver->isStatusDraft($order->deliveryNote)) { | |||
$contentColumnDeliveryNote = 'Brouillon'; | |||
} | |||
elseif($this->documentSolver->isStatusValid($order->deliveryNote)) { | |||
$contentColumnDeliveryNote = 'Oui'; | |||
} | |||
} | |||
return '<td>'.$contentColumnDeliveryNote.'</td>'; | |||
} | |||
return ''; | |||
} | |||
public function columnCredit(Order $order, PointSale $pointSale): string | |||
{ | |||
if($pointSale->credit) { | |||
$credit = '' ; | |||
if(isset($order->user) && $order->user->id) { | |||
$userProducer = UserProducer::searchOne([ | |||
'id_user' => $order->user->id | |||
]); | |||
if($userProducer) { | |||
$credit = number_format($userProducer->credit,2).' €' ; | |||
} | |||
} | |||
return '<td>'.$credit.'</td>' ; | |||
} | |||
return ''; | |||
} | |||
public function columnOrderAmount(Order $order): string | |||
{ | |||
$html = '<td><strong>'.number_format($order->amount_with_tax, 2) . ' € '; | |||
if($this->orderSolver->getPaymentStatus($order) == Order::PAYMENT_PAID) | |||
{ | |||
$html .= '(débité)' ; | |||
} | |||
elseif($this->orderSolver->getPaymentStatus($order) == Order::PAYMENT_UNPAID && $this->orderSolver->getOrderAmount($order, Order::AMOUNT_PAID)) | |||
{ | |||
$html .= '(reste '.$this->orderSolver->getOrderAmount($order, Order::AMOUNT_REMAINING, true).' à débiter)' ; | |||
} | |||
elseif($this->orderSolver->getPaymentStatus($order) == Order::PAYMENT_SURPLUS) | |||
{ | |||
$html .= '(surplus : '.$this->orderSolver->getOrderAmount($order, Order::PAYMENT_SURPLUS, true).' à recréditer)' ; | |||
} | |||
$html .= '</strong></td>' ; | |||
return $html; | |||
} | |||
public function buildReportPointsSaleTotalHtml(array $pointsSaleArray, array $productsArray, array $ordersArray, bool $isBig): string | |||
{ | |||
$html = ''; | |||
$html .= '<h3>Points de vente</h3>' ; | |||
$html .= '<table class="">' | |||
. '<thead>' | |||
. '<tr>' | |||
. '<th>Point de vente</th>' | |||
. '<th>Produits</th>' | |||
. ( $isBig ? '<th>Produits</th>' : '') | |||
. '<th>Montant</th>' | |||
. '</tr>' | |||
. '<tbody>'; | |||
$revenues = 0 ; | |||
foreach ($pointsSaleArray as $pointSale) | |||
{ | |||
if (count($pointSale->orders)) | |||
{ | |||
$html .= '<tr><td>'.$pointSale->name.'</td><td>' ; | |||
$cpt = 0 ; | |||
foreach ($productsArray as $product) { | |||
foreach( Product::$unitsArray as $unit => $dataUnit) { | |||
$quantity = $this->orderSolver->getProductQuantity($product, $pointSale->orders, false, $unit); | |||
if ($quantity) { | |||
$theUnit = ( $this->productSolver->strUnit($unit, 'wording_short', true) == 'p.') ? '' : ' '. $this->productSolver->strUnit($unit, 'wording_short', true) ; | |||
$html .= '(' .$quantity .$theUnit.') '.$this->productSolver->getNameExport($product) . '<br />'; | |||
} | |||
} | |||
if($isBig && $cpt == self::LIMIT_PRODUCTS) { | |||
$html .= '</td><td>' ; | |||
} | |||
$cpt ++ ; | |||
} | |||
$html .= '</td><td>'.Price::format($pointSale->revenues_with_tax, 2).'</td></tr>' ; | |||
$revenues += $pointSale->revenues_with_tax ; | |||
} | |||
} | |||
// total | |||
$html .= '<tr><td><strong>Total</strong></td><td>' ; | |||
$cpt = 0 ; | |||
foreach ($productsArray as $product) { | |||
foreach( Product::$unitsArray as $unit => $dataUnit) { | |||
$quantity = $this->orderSolver->getProductQuantity($product, $ordersArray, false, $unit); | |||
if ($quantity) { | |||
$theUnit = ( $this->productSolver->strUnit($unit, 'wording_short', true) == 'p.') ? '' : ' '. $this->productSolver->strUnit($unit, 'wording_short', true) ; | |||
$html .= '(' .$quantity .$theUnit.') '.$product->name . '<br />'; | |||
} | |||
} | |||
if($isBig && $cpt == self::LIMIT_PRODUCTS) { | |||
$html .= '</td><td>' ; | |||
} | |||
$cpt ++ ; | |||
} | |||
$html .= '</td><td><strong>'.number_format($revenues, 2).' €</strong></td></tr>' ; | |||
$html .= '</tbody></table>' ; | |||
return $html; | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
<?php | |||
namespace common\logic\Document\DeliveryNote\Event; | |||
use common\logic\Document\DeliveryNote\Model\DeliveryNote; | |||
use yii\base\Event; | |||
class DeliveryNoteCreateEvent extends Event | |||
{ | |||
public DeliveryNote $deliveryNote; | |||
public array $idOrders = []; | |||
} |
@@ -42,6 +42,8 @@ use common\logic\Document\Document\Model\Document; | |||
class DeliveryNote extends Document | |||
{ | |||
const EVENT_CREATE = 'deliverynote.event.create'; | |||
/** | |||
* @inheritdoc | |||
*/ |
@@ -4,6 +4,7 @@ namespace common\logic\Document\DeliveryNote\Repository; | |||
use common\logic\AbstractRepository; | |||
use common\logic\Document\DeliveryNote\Model\DeliveryNote; | |||
use common\logic\Order\Order\Model\Order; | |||
class DeliveryNoteRepository extends AbstractRepository | |||
{ | |||
@@ -30,4 +31,29 @@ class DeliveryNoteRepository extends AbstractRepository | |||
->filterById($id) | |||
->findOne(); | |||
} | |||
public function getOneDeliveryNoteExistingFromOrders(array $ordersArray): ?DeliveryNote | |||
{ | |||
$i = 0; | |||
$deliveryNote = null; | |||
do { | |||
$order = $ordersArray[$i]; | |||
if ($order->distribution->id_producer == $this->getProducerContextId() && $order->id_delivery_note > 0) { | |||
$deliveryNote = $this->findOneDeliveryNoteById($order->id_delivery_note); | |||
} | |||
$i++; | |||
} while ($deliveryNote == null && isset($ordersArray[$i])); | |||
return $deliveryNote; | |||
} | |||
public function findOneDeliveryNoteByOrder(Order $order): ?DeliveryNote | |||
{ | |||
$deliveryNoteExist = null; | |||
if ($order->id_delivery_note) { | |||
$deliveryNoteExist = $this->findOneDeliveryNoteById($order->id_delivery_note); | |||
} | |||
return $deliveryNoteExist; | |||
} | |||
} |
@@ -2,15 +2,123 @@ | |||
namespace common\logic\Document\DeliveryNote\Service; | |||
use common\logic\Distribution\Distribution\Model\Distribution; | |||
use common\logic\Document\DeliveryNote\Event\DeliveryNoteCreateEvent; | |||
use common\logic\Document\DeliveryNote\Model\DeliveryNote; | |||
use common\logic\Document\DeliveryNote\Repository\DeliveryNoteRepository; | |||
use common\logic\Document\Document\Service\DocumentBuilder; | |||
use common\logic\Order\Order\Model\Order; | |||
use common\logic\Order\Order\Service\OrderSolver; | |||
use common\logic\PointSale\PointSale\Model\PointSale; | |||
use common\logic\User\User\Repository\UserRepository; | |||
use common\logic\User\User\Service\UserSolver; | |||
use yii\base\ErrorException; | |||
class DeliveryNoteBuilder extends DocumentBuilder | |||
{ | |||
protected UserSolver $userSolver; | |||
protected UserRepository $userRepository; | |||
protected DeliveryNoteRepository $deliveryNoteRepository; | |||
protected OrderSolver $orderSolver; | |||
public function loadDependencies(): void | |||
{ | |||
parent::loadDependencies(); | |||
$this->userSolver = $this->loadService(UserSolver::class); | |||
$this->userRepository = $this->loadService(UserRepository::class); | |||
$this->deliveryNoteRepository = $this->loadService(DeliveryNoteRepository::class); | |||
$this->orderSolver = $this->loadService(OrderSolver::class); | |||
} | |||
public function instanciateDeliveryNote(): DeliveryNote | |||
{ | |||
$deliveryNote = new DeliveryNote(); | |||
$this->initDocumentProducer($deliveryNote); | |||
$this->initTaxCalculationMethod($deliveryNote); | |||
return $deliveryNote; | |||
} | |||
public function createDeliveryNoteForPointSale(PointSale $pointSale, Distribution $distribution, array $idOrders): DeliveryNote | |||
{ | |||
$deliveryNote = $this->instanciateDeliveryNote(); | |||
$this->initDeliveryNoteNameByPointSale($deliveryNote, $distribution, $pointSale); | |||
$this->initDeliveryNoteUserFromPointSale($deliveryNote, $pointSale); | |||
$this->initDeliveryNoteAddress($deliveryNote); | |||
$deliveryNote->save(); | |||
$this->triggerDeliveryNoteCreateEvent($deliveryNote, $idOrders); | |||
return $deliveryNote; | |||
} | |||
public function createDeliveryNoteForOrder(Order $order): DeliveryNote | |||
{ | |||
$deliveryNote = $this->deliveryNoteRepository->findOneDeliveryNoteByOrder($order); | |||
$deliveryNote = $this->deleteDeliveryNoteIfStatusDraft($deliveryNote); | |||
if(!$deliveryNote) { | |||
$deliveryNote = $this->instanciateDeliveryNote(); | |||
$this->initDeliveryNoteNameByOrder($deliveryNote, $order); | |||
$this->initDeliveryNoteUserFromOrder($deliveryNote, $order); | |||
$this->initDeliveryNoteAddress($deliveryNote); | |||
$deliveryNote->save(); | |||
$this->triggerDeliveryNoteCreateEvent($deliveryNote, [$order->id]); | |||
} | |||
return $deliveryNote; | |||
} | |||
public function triggerDeliveryNoteCreateEvent(DeliveryNote $deliveryNote, array $idOrders) | |||
{ | |||
$deliveryNoteCreateEvent = new DeliveryNoteCreateEvent(); | |||
$deliveryNoteCreateEvent->deliveryNote = $deliveryNote; | |||
$deliveryNoteCreateEvent->idOrders = $idOrders; | |||
$deliveryNote->trigger(DeliveryNote::EVENT_CREATE, $deliveryNoteCreateEvent); | |||
} | |||
public function initDeliveryNoteUserFromPointSale(DeliveryNote $deliveryNote, PointSale $pointSale) | |||
{ | |||
$deliveryNote->id_user = $pointSale->id_user; | |||
} | |||
public function initDeliveryNoteUserFromOrder(DeliveryNote $deliveryNote, Order $order) | |||
{ | |||
$deliveryNote->id_user = $order->id_user; | |||
} | |||
public function initDeliveryNoteNameByPointSale(DeliveryNote $deliveryNote, Distribution $distribution, PointSale $pointSale) | |||
{ | |||
$deliveryNote->name = 'Bon de livraison ' . $pointSale->name . | |||
' (' . date('d/m/Y', strtotime($distribution->date)) . ')'; | |||
} | |||
public function initDeliveryNoteNameByOrder(DeliveryNote $deliveryNote, Order $order) | |||
{ | |||
$deliveryNote->name = 'Bon de livraison ' . $this->orderSolver->getOrderUsername($order) . | |||
' (' . date('d/m/Y', strtotime($order->distribution->date)) . ')'; | |||
} | |||
public function initDeliveryNoteAddress(DeliveryNote $deliveryNote) | |||
{ | |||
$user = $this->userRepository->findOneUserById($deliveryNote->id_user); | |||
if($user) { | |||
$deliveryNote->address = $this->userSolver->getFullAddress($user); | |||
} | |||
else { | |||
throw new ErrorException("L'utilisateur du bon de livraison n'est pas défini."); | |||
} | |||
} | |||
public function deleteDeliveryNoteIfStatusDraft(DeliveryNote $deliveryNote = null): ?DeliveryNote | |||
{ | |||
if ($deliveryNote && $this->documentSolver->isStatusDraft($deliveryNote)) { | |||
$deliveryNote->delete(); | |||
$deliveryNote = null; | |||
} | |||
return $deliveryNote; | |||
} | |||
} |
@@ -21,6 +21,11 @@ class DocumentBuilder extends AbstractBuilder | |||
$this->producerRepository = $this->loadService(ProducerRepository::class); | |||
} | |||
public function initDocumentProducer(Document $document): void | |||
{ | |||
$document->id_producer = $this->getProducerContextId(); | |||
} | |||
public function generateReference(DocumentInterface $document): void | |||
{ | |||
$class = $this->documentSolver->getClass($document); | |||
@@ -64,6 +69,14 @@ class DocumentBuilder extends AbstractBuilder | |||
} | |||
} | |||
public function validateDocument(Document $document): void | |||
{ | |||
if($this->documentSolver->isStatusDraft($document)) { | |||
$this->changeStatus($document, Document::STATUS_VALID); | |||
$this->update($document); | |||
} | |||
} | |||
public function initTaxCalculationMethod(DocumentInterface $document): void | |||
{ | |||
$producerTaxCalculationMethod = $this->producerRepository->getConfig('option_tax_calculation_method'); |
@@ -0,0 +1,30 @@ | |||
<?php | |||
namespace common\logic\Opinion\Service; | |||
use common\logic\AbstractUtils; | |||
use common\logic\User\User\Model\User; | |||
use common\logic\User\User\Service\UserSolver; | |||
class OpinionUtils extends AbstractUtils | |||
{ | |||
protected UserSolver $userSolver; | |||
public function loadDependencies(): void | |||
{ | |||
$this->userSolver = $this->loadService(UserSolver::class); | |||
} | |||
public function sendOpinionEmailAdmin($opinionFormModel, User $userCurrent = null) | |||
{ | |||
\Yii::$app->mailerService->sendAdmin( | |||
'Nouvel avis', | |||
'newOpinionAdmin', | |||
[ | |||
'username' => $userCurrent ? $this->userSolver->getUsername($userCurrent) : $opinionFormModel->name, | |||
'message' => $opinionFormModel->message, | |||
], | |||
$userCurrent ? $userCurrent->email : $opinionFormModel->email | |||
); | |||
} | |||
} |
@@ -0,0 +1,16 @@ | |||
<?php | |||
namespace common\logic\Opinion\Wrapper; | |||
use common\logic\AbstractContainer; | |||
use common\logic\Opinion\Service\OpinionUtils; | |||
class OpinionContainer extends AbstractContainer | |||
{ | |||
public function getServices(): array | |||
{ | |||
return [ | |||
OpinionUtils::class | |||
]; | |||
} | |||
} |
@@ -0,0 +1,17 @@ | |||
<?php | |||
namespace common\logic\Opinion\Wrapper; | |||
use common\logic\AbstractManager; | |||
use common\logic\Opinion\Service\OpinionUtils; | |||
/** | |||
* @mixin OpinionUtils | |||
*/ | |||
class OpinionManager extends AbstractManager | |||
{ | |||
public function getContainerFqcn(): string | |||
{ | |||
return OpinionContainer::class; | |||
} | |||
} |
@@ -0,0 +1,24 @@ | |||
<?php | |||
namespace common\logic\Order\Order\Event; | |||
use common\logic\Document\DeliveryNote\Event\DeliveryNoteCreateEvent; | |||
use common\logic\Document\DeliveryNote\Model\DeliveryNote; | |||
use common\logic\Order\Order\Wrapper\OrderManager; | |||
use justcoded\yii2\eventlistener\observers\Observer; | |||
class DeliveryNoteObserver extends Observer | |||
{ | |||
public function events() | |||
{ | |||
return [ | |||
DeliveryNote::EVENT_CREATE => 'onDeliveryNoteCreate' | |||
]; | |||
} | |||
public function onDeliveryNoteCreate(DeliveryNoteCreateEvent $event) | |||
{ | |||
$orderManager = OrderManager::getInstance(); | |||
$orderManager->assignAllOrdersDeliveryNote($event->idOrders, $event->deliveryNote); | |||
} | |||
} |
@@ -10,6 +10,8 @@ use common\logic\Config\TaxRate\Model\TaxRate; | |||
use common\logic\Distribution\Distribution\Model\Distribution; | |||
use common\logic\Distribution\Distribution\Repository\DistributionRepository; | |||
use common\logic\Distribution\Distribution\Service\DistributionSolver; | |||
use common\logic\Document\DeliveryNote\Model\DeliveryNote; | |||
use common\logic\Document\DeliveryNote\Service\DeliveryNoteBuilder; | |||
use common\logic\Document\Document\Model\Document; | |||
use common\logic\Order\Order\Model\Order; | |||
use common\logic\Order\Order\Repository\OrderRepository; | |||
@@ -30,6 +32,7 @@ use common\logic\Subscription\Subscription\Service\SubscriptionSolver; | |||
use common\logic\User\CreditHistory\Model\CreditHistory; | |||
use common\logic\User\CreditHistory\Service\CreditHistoryBuilder; | |||
use common\logic\User\CreditHistory\Repository\CreditHistoryRepository; | |||
use common\logic\User\User\Repository\UserRepository; | |||
use common\logic\User\User\Service\UserSolver; | |||
use common\logic\User\UserProducer\Repository\UserProducerRepository; | |||
use yii\web\NotFoundHttpException; | |||
@@ -54,6 +57,8 @@ class OrderBuilder extends AbstractBuilder | |||
protected SubscriptionSolver $subscriptionSolver; | |||
protected ProductSolver $productSolver; | |||
protected DistributionSolver $distributionSolver; | |||
protected UserRepository $userRepository; | |||
protected DeliveryNoteBuilder $deliveryNoteBuilder; | |||
public function loadDependencies(): void | |||
{ | |||
@@ -75,6 +80,8 @@ class OrderBuilder extends AbstractBuilder | |||
$this->subscriptionSolver = $this->loadService(SubscriptionSolver::class); | |||
$this->productSolver = $this->loadService(ProductSolver::class); | |||
$this->distributionSolver = $this->loadService(DistributionSolver::class); | |||
$this->userRepository = $this->loadService(UserRepository::class); | |||
$this->deliveryNoteBuilder = $this->loadService(DeliveryNoteBuilder::class); | |||
} | |||
public function instanciateOrder(Distribution $distribution): Order | |||
@@ -130,7 +137,7 @@ class OrderBuilder extends AbstractBuilder | |||
*/ | |||
public function createAllOrdersFromSubscriptions(string $date, bool $force = false): array | |||
{ | |||
$orderArray = []; | |||
$ordersSubscriptionsArray = []; | |||
$distribution = $this->distributionRepository->findOneDistribution(date('Y-m-d', strtotime($date))); | |||
if ($distribution) { | |||
@@ -138,12 +145,15 @@ class OrderBuilder extends AbstractBuilder | |||
$subscriptionArray = $this->subscriptionRepository->findSubscriptionsByDate($date); | |||
foreach ($subscriptionArray as $subscription) { | |||
if (!$this->subscriptionSolver->hasOrderAlreadyExist($subscription, $orderArray)) { | |||
$this->createOrderFromSubscription($subscription, $date, $force); | |||
$order = $this->createOrderFromSubscription($subscription, $date, $force); | |||
if ($order) { | |||
$ordersSubscriptionsArray[] = $order; | |||
} | |||
} | |||
} | |||
} | |||
return $orderArray; | |||
return $ordersSubscriptionsArray; | |||
} | |||
public function updateOrdersIncomingDistributionsFromSubscription(Subscription $subscription, $update = false): array | |||
@@ -195,7 +205,7 @@ class OrderBuilder extends AbstractBuilder | |||
$countOrdersDeleted = 0; | |||
if ($ordersArray && count($ordersArray)) { | |||
foreach ($ordersArray as $order) { | |||
if($this->distributionSolver->isDistributionAvailable($order->distribution)) { | |||
if ($this->distributionSolver->isDistributionAvailable($order->distribution)) { | |||
$theOrder = $this->orderRepository->findOneOrderById($order->id); | |||
$this->initOrder($theOrder); | |||
@@ -601,4 +611,47 @@ class OrderBuilder extends AbstractBuilder | |||
} | |||
} | |||
public function updateOrderDeliveryNote(Order $order, DeliveryNote $deliveryNote): bool | |||
{ | |||
$order->id_delivery_note = $deliveryNote->id; | |||
return $order->save(); | |||
} | |||
public function assignAllOrdersDeliveryNote(array $idOrders, DeliveryNote $deliveryNote) | |||
{ | |||
$this->unassignAllOrdersDeliveryNote($deliveryNote); | |||
foreach ($idOrders as $idOrder) { | |||
$order = $this->orderRepository->findOneOrderById((int)$idOrder); | |||
if ($order) { | |||
$this->assignOrderDeliveryNote($order, $deliveryNote); | |||
} | |||
} | |||
} | |||
public function assignOrderDeliveryNote(Order $order, DeliveryNote $deliveryNote) | |||
{ | |||
if ($this->orderSolver->isOrderFromProducer($order)) { | |||
$this->updateOrderDeliveryNote($order, $deliveryNote); | |||
$order = $this->orderRepository->findOneOrderById($order->id); | |||
$user = $this->userRepository->findOneUserById($deliveryNote->id_user); | |||
$userProducer = $this->userProducerRepository->findOneUserProducer($user); | |||
$this->updateOrderInvoicePrices($order, | |||
[ | |||
'user' => $user, | |||
'user_producer' => $userProducer, | |||
'point_sale' => $order->pointSale | |||
]); | |||
} | |||
} | |||
public function unassignAllOrdersDeliveryNote(DeliveryNote $deliveryNote) | |||
{ | |||
Order::updateAll([ | |||
'id_delivery_note' => null | |||
], [ | |||
'id_delivery_note' => $deliveryNote->id | |||
]); | |||
} | |||
} |
@@ -6,6 +6,7 @@ use common\helpers\Price; | |||
use common\logic\AbstractService; | |||
use common\logic\Document\Document\Service\DocumentSolver; | |||
use common\logic\Order\Order\Model\Order; | |||
use common\logic\Producer\Producer\Model\Producer; | |||
use common\logic\Product\Product\Model\Product; | |||
use common\logic\SolverInterface; | |||
use common\logic\User\CreditHistory\Model\CreditHistory; | |||
@@ -123,9 +124,24 @@ class OrderSolver extends AbstractService implements SolverInterface | |||
public function isLinkedToValidDocument(Order $order): bool | |||
{ | |||
return ($order->deliveryNote && $this->documentSolver->isStatusValid($order->deliveryNote)) | |||
|| ($order->quotation && $this->documentSolver->isStatusValid($order->quotation)) | |||
|| ($order->invoice && $this->documentSolver->isStatusValid($order->invoice)); | |||
return ($this->isLinkedToValidDeliveryNote($order) | |||
|| $this->isLinkedToValidQuotation($order) | |||
|| $this->isLinkedToValidInvoice($order)); | |||
} | |||
public function isLinkedToValidDeliveryNote(Order $order): bool | |||
{ | |||
return $order->deliveryNote && $this->documentSolver->isStatusValid($order->deliveryNote); | |||
} | |||
public function isLinkedToValidQuotation(Order $order): bool | |||
{ | |||
return $order->quotation && $this->documentSolver->isStatusValid($order->quotation); | |||
} | |||
public function isLinkedToValidInvoice(Order $order): bool | |||
{ | |||
return $order->invoice && $this->documentSolver->isStatusValid($order->invoice); | |||
} | |||
public function getCommentReport(Order $order): string | |||
@@ -361,7 +377,6 @@ class OrderSolver extends AbstractService implements SolverInterface | |||
} | |||
} | |||
// belongsToUser | |||
public function isOrderBelongsToUser(Order $order, User $user = null): bool | |||
{ | |||
if($user) { | |||
@@ -371,6 +386,11 @@ class OrderSolver extends AbstractService implements SolverInterface | |||
return false; | |||
} | |||
public function isOrderFromProducer(Order $order = null): bool | |||
{ | |||
return $order && $order->distribution->id_producer == $this->getProducerContextId(); | |||
} | |||
/** | |||
* Retourne les informations relatives à la commande au format JSON. | |||
*/ |
@@ -151,6 +151,9 @@ class Producer extends ActiveRecordCommon | |||
'option_online_payment_minimum_amount', | |||
'option_document_price_decimals', | |||
'option_billing_reduction_percentage', | |||
'dolibarr_socid', | |||
'dolibarr_product_id', | |||
'option_weeks_distributions_activated_in_advance' | |||
], | |||
'integer' | |||
], | |||
@@ -253,7 +256,8 @@ class Producer extends ActiveRecordCommon | |||
'option_billing_reduction', | |||
'option_export_evoliz', | |||
'option_display_message_new_opendistrib_version', | |||
'option_billing_permanent_transfer' | |||
'option_billing_permanent_transfer', | |||
'option_export_display_column_delivery_note' | |||
], | |||
'boolean' | |||
], | |||
@@ -415,7 +419,11 @@ 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', | |||
'option_export_display_column_delivery_note' => "Récapitulatif PDF : afficher une colonne bon de livraison", | |||
'option_weeks_distributions_activated_in_advance' => "Semaines de distributions à activer à l'avance", | |||
]; | |||
} | |||
@@ -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é | |||
*/ | |||
@@ -241,7 +247,7 @@ class ProducerRepository extends AbstractRepository | |||
{ | |||
if (strlen($config)) { | |||
if (!$idProducer) { | |||
$idProducer = GlobalParam::getCurrentProducerId(); | |||
$idProducer = $this->getProducerContextId(); | |||
} | |||
$producer = $this->findOneProducerById($idProducer); |
@@ -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; | |||
} | |||
} |
@@ -64,15 +64,15 @@ class ProducerBuilder extends AbstractBuilder | |||
/** | |||
* Lie un utilisateur à un producteur. | |||
*/ | |||
public function addUser(User $user, Producer $producer, int $bookmark = 1): UserProducer | |||
public function addUser(User $user, Producer $producer, bool $bookmark = true, bool $newsletter = true): UserProducer | |||
{ | |||
$userProducer = $this->userProducerBuilder->createUserProducerIfNotExist($user, $producer, $bookmark); | |||
$userProducer = $this->userProducerBuilder->createUserProducerIfNotExist($user, $producer, $bookmark, $newsletter); | |||
if (!$userProducer->getActive()) { | |||
$userProducer->setActive(1); | |||
$userProducer->setActive(true); | |||
} | |||
$this->saveUpdate($userProducer); | |||
$this->update($userProducer); | |||
return $userProducer; | |||
} |
@@ -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; |
@@ -71,7 +71,7 @@ class TicketSolver extends AbstractSolver | |||
return false; | |||
} | |||
public function isTicketUnread(Ticket $ticket, User $user): int | |||
public function isTicketUnread(Ticket $ticket, User $user): bool | |||
{ | |||
$ticketUser = $this->getTicketUser($ticket, $user); | |||
@@ -51,9 +51,9 @@ class CreditHistorySolver extends AbstractService implements SolverInterface | |||
} elseif (CreditHistory::TYPE_CREDIT == $type) { | |||
$str = 'Crédit'; | |||
} elseif (CreditHistory::TYPE_PAYMENT == $type) { | |||
$str = 'Paiement'; | |||
$str = 'Débit'; | |||
} elseif (CreditHistory::TYPE_REFUND == $type) { | |||
$str = 'Remboursement'; | |||
$str = 'Recrédit'; | |||
} elseif (CreditHistory::TYPE_DEBIT == $type) { | |||
$str = 'Débit'; | |||
} |
@@ -70,6 +70,7 @@ class User extends ActiveRecordCommon implements IdentityInterface | |||
var $user_groups = []; | |||
var $one_name; | |||
var $product_price_percent; | |||
var $newsletter; | |||
/** | |||
* @inheritdoc | |||
@@ -95,7 +96,7 @@ class User extends ActiveRecordCommon implements IdentityInterface | |||
public function rules() | |||
{ | |||
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', 'newsletter'], 'boolean'], | |||
[['lastname', 'name', 'phone', 'address', 'type', 'name_legal_person', 'evoliz_code'], 'string'], | |||
['lastname', 'verifyOneName', 'skipOnError' => false, 'skipOnEmpty' => false], | |||
['email', 'email', 'message' => 'Cette adresse email n\'est pas valide'], | |||
@@ -137,7 +138,8 @@ class User extends ActiveRecordCommon implements IdentityInterface | |||
'is_main_contact' => 'Contact principal', | |||
'product_price_percent' => 'Prix produits : pourcentage', | |||
'user_groups' => "Groupes d'utilisateurs", | |||
'evoliz_code' => 'Code client Evoliz' | |||
'evoliz_code' => 'Code client Evoliz', | |||
'newsletter' => "Inscrit au bulletin d'information" | |||
]; | |||
} | |||
@@ -62,9 +62,6 @@ class UserSearch extends User | |||
public function search($params = []) | |||
{ | |||
$userRepository = UserRepository::getInstance(); | |||
$optionsSearch = $userRepository->getDefaultOptionsSearch(); | |||
$query = User::find() | |||
->select( | |||
'`user`.id, ' | |||
@@ -91,14 +88,24 @@ class UserSearch extends User | |||
. '`user`.type, ' | |||
. '(SELECT COUNT(*) FROM `order` WHERE `user`.id = `order`.id_user) AS count_orders'); | |||
$query->innerJoin('user_producer', 'user.id = user_producer.id_user AND user_producer.id_producer = :id_producer AND user_producer.active = 1', [':id_producer' => GlobalParam::getCurrentProducerId()]); | |||
$dataProvider = new ActiveDataProvider([ | |||
'query' => $query, | |||
'sort' => ['attributes' => ['username', 'credit', 'orders']], | |||
'sort' => [ | |||
'attributes' => ['username', 'credit', 'orders'], | |||
'defaultOrder' => ['created_at' => SORT_DESC] | |||
], | |||
'pagination' => [ | |||
'pageSize' => 20, | |||
], | |||
]); | |||
$dataProvider->sort->attributes['created_at'] = [ | |||
'asc' => ['user.created_at' => SORT_ASC], | |||
'desc' => ['user.created_at' => SORT_DESC], | |||
]; | |||
$dataProvider->sort->attributes['username'] = [ | |||
'asc' => ['user.lastname' => SORT_ASC, 'user.name' => SORT_ASC], | |||
'desc' => ['user.lastname' => SORT_DESC, 'user.name' => SORT_DESC], | |||
@@ -114,10 +121,7 @@ class UserSearch extends User | |||
return $dataProvider; | |||
} | |||
$query->innerJoin('user_producer', 'user.id = user_producer.id_user AND user_producer.id_producer = :id_producer AND user_producer.active = 1', [':id_producer' => GlobalParam::getCurrentProducerId()]); | |||
if (isset($this->id_point_sale) && $this->id_point_sale) { | |||
$pointSale = PointSale::findOne(['id' => $this->id_point_sale]); | |||
$query->innerJoin('user_point_sale', 'user.id = user_point_sale.id_user AND user_point_sale.id_point_sale = :id_point_sale', [':id_point_sale' => $this->id_point_sale]); | |||
} | |||
@@ -142,8 +146,6 @@ class UserSearch extends User | |||
['like', 'user.name_legal_person', $this->username], | |||
]); | |||
$query->orderBy('user.created_at DESC'); | |||
return $dataProvider; | |||
} | |||
@@ -91,7 +91,7 @@ class UserRepository extends AbstractRepository | |||
->from('user'); | |||
$active = (isset($params['inactive']) && $params['inactive']) ? 0 : 1; | |||
$query->innerJoin('user_producer', 'user.id = user_producer.id_user AND user_producer.active = ' . $active . ' AND user_producer.id_producer = :id_producer', [':id_producer' => $params['id_producer']]); | |||
$query->innerJoin('user_producer', 'user.id = user_producer.id_user AND user_producer.active = ' . $active . ' AND user_producer.newsletter = 1 AND user_producer.id_producer = :id_producer', [':id_producer' => $params['id_producer']]); | |||
if (isset($params['id_point_sale']) && $params['id_point_sale']) { | |||
$point_sale = PointSale::findOne(['id' => $params['id_point_sale']]); |
@@ -0,0 +1,49 @@ | |||
<?php | |||
namespace common\logic\User\User\Service; | |||
use common\logic\AbstractService; | |||
use common\logic\User\User\Model\User; | |||
use common\logic\User\UserProducer\Repository\UserProducerRepository; | |||
use common\logic\User\UserProducer\Service\UserProducerBuilder; | |||
use common\logic\UtilsInterface; | |||
class NewsletterUtils extends AbstractService implements UtilsInterface | |||
{ | |||
protected UserProducerRepository $userProducerRepository; | |||
protected UserProducerBuilder $userProducerBuilder; | |||
public function loadDependencies(): void | |||
{ | |||
$this->userProducerRepository = $this->loadService(UserProducerRepository::class); | |||
$this->userProducerBuilder = $this->loadService(UserProducerBuilder::class); | |||
} | |||
public function isUserSubscribedNewsletter(User $user = null): bool | |||
{ | |||
if($user) { | |||
$userProducer = $this->userProducerRepository->findOneUserProducer($user); | |||
if($userProducer && $userProducer->newsletter) { | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
public function subscribeUserNewsletter(User $user): bool | |||
{ | |||
$userProducer = $this->userProducerBuilder->createUserProducerIfNotExist($user, $this->getProducerContext()); | |||
return $this->userProducerBuilder->updateUserProducerNewsletter($userProducer, true); | |||
} | |||
public function unsubscribeUserNewsletter(User $user): bool | |||
{ | |||
$userProducer = $this->userProducerRepository->findOneUserProducer($user); | |||
if($userProducer) { | |||
return $this->userProducerBuilder->updateUserProducerNewsletter($userProducer, false); | |||
} | |||
return false; | |||
} | |||
} |
@@ -137,6 +137,11 @@ class UserSolver extends AbstractService implements SolverInterface | |||
return null; | |||
} | |||
public function isCurrentGuest(): bool | |||
{ | |||
return \Yii::$app->user->isGuest; | |||
} | |||
/** | |||
* Retourne si l'utilisateur courant est connecté ou non. | |||
* |
@@ -41,7 +41,7 @@ class UsersCreditCsvGenerator extends AbstractGenerator | |||
$this->userSolver->getUsernameFromArray($user, true), | |||
$user['email'], | |||
$user['phone'], | |||
Price::format($user['credit']), | |||
CSV::formatPrice($user['credit']), | |||
]; | |||
} | |||
@@ -5,6 +5,7 @@ namespace common\logic\User\User\Wrapper; | |||
use common\logic\AbstractContainer; | |||
use common\logic\User\User\Repository\UserRepository; | |||
use common\logic\User\User\Repository\UserRepositoryQuery; | |||
use common\logic\User\User\Service\NewsletterUtils; | |||
use common\logic\User\User\Service\UserBuilder; | |||
use common\logic\User\User\Service\UserDefinition; | |||
use common\logic\User\User\Service\UsersCreditCsvGenerator; | |||
@@ -23,6 +24,7 @@ class UserContainer extends AbstractContainer | |||
UserBuilder::class, | |||
UsersCreditCsvGenerator::class, | |||
UserUtils::class, | |||
NewsletterUtils::class, | |||
]; | |||
} | |||
@@ -4,6 +4,7 @@ namespace common\logic\User\User\Wrapper; | |||
use common\logic\AbstractManager; | |||
use common\logic\User\User\Repository\UserRepository; | |||
use common\logic\User\User\Service\NewsletterUtils; | |||
use common\logic\User\User\Service\UserBuilder; | |||
use common\logic\User\User\Service\UserDefinition; | |||
use common\logic\User\User\Service\UsersCreditCsvGenerator; | |||
@@ -17,6 +18,7 @@ use common\logic\User\User\Service\UserUtils; | |||
* @mixin UserBuilder | |||
* @mixin UserUtils | |||
* @mixin UsersCreditCsvGenerator | |||
* @mixin NewsletterUtils | |||
*/ | |||
class UserManager extends AbstractManager | |||
{ |
@@ -64,7 +64,7 @@ class UserProducer extends ActiveRecordCommon | |||
return [ | |||
[['id_user', 'id_producer'], 'required'], | |||
[['id_user', 'id_producer', 'product_price_percent'], 'integer'], | |||
[['active', 'bookmark', 'credit_active'], 'boolean'], | |||
[['active', 'bookmark', 'credit_active', 'newsletter'], 'boolean'], | |||
[['credit', 'product_price_percent'], 'double'], | |||
]; | |||
} | |||
@@ -152,6 +152,13 @@ class UserProducer extends ActiveRecordCommon | |||
return $this; | |||
} | |||
public function setNewsletter(bool $newsletter): self | |||
{ | |||
$this->newsletter = $newsletter; | |||
return $this; | |||
} | |||
public function getCredit(): float | |||
{ | |||
return $this->credit; |
@@ -32,30 +32,31 @@ class UserProducerBuilder extends AbstractBuilder | |||
$this->orderSolver = $this->loadService(OrderSolver::class); | |||
} | |||
public function instanciateUserProducer(User $user, Producer $producer, int $bookmark = 1) | |||
public function instanciateUserProducer(User $user, Producer $producer, bool $bookmark = true, bool $newsletter = true) | |||
{ | |||
$userProducer = new UserProducer(); | |||
$userProducer->populateUser($user); | |||
$userProducer->populateproducer($producer); | |||
$userProducer->setCredit(0); | |||
$userProducer->setActive(1); | |||
$userProducer->setActive(true); | |||
$userProducer->setBookmark($bookmark); | |||
$userProducer->setNewsletter($newsletter); | |||
return $userProducer; | |||
} | |||
public function createUserProducer(User $user, Producer $producer, int $bookmark = 1): UserProducer | |||
public function createUserProducer(User $user, Producer $producer, bool $bookmark = true, bool $newsletter = true): UserProducer | |||
{ | |||
$userProducer = $this->instanciateUserProducer($user, $producer, $bookmark); | |||
$userProducer = $this->instanciateUserProducer($user, $producer, $bookmark, $newsletter); | |||
$this->create($userProducer); | |||
return $userProducer; | |||
} | |||
public function createUserProducerIfNotExist(User $user, Producer $producer, int $bookmark = 1): UserProducer | |||
public function createUserProducerIfNotExist(User $user, Producer $producer, bool $bookmark = true, bool $newsletter = true): UserProducer | |||
{ | |||
return $this->userProducerRepository->findOneUserProducer($user) | |||
?? $this->createUserProducer($user, $producer, $bookmark); | |||
?? $this->createUserProducer($user, $producer, $bookmark, $newsletter); | |||
} | |||
public function updateCredit(CreditHistory $creditHistory): void | |||
@@ -176,4 +177,10 @@ class UserProducerBuilder extends AbstractBuilder | |||
$userProducer->bookmark = 0; | |||
return $this->update($userProducer); | |||
} | |||
public function updateUserProducerNewsletter(UserProducer $userProducer, bool $newsletter) | |||
{ | |||
$userProducer->newsletter = $newsletter; | |||
return $this->update($userProducer); | |||
} | |||
} |
@@ -5,4 +5,4 @@ namespace common\logic; | |||
interface UtilsInterface | |||
{ | |||
} | |||
} |
@@ -0,0 +1,49 @@ | |||
<?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; | |||
?> | |||
<p>Un nouvel avis vient d'être envoyé par <em><?= Html::encode($username) ?></em> :</p><br /> | |||
<div> | |||
<?= Html::encode($message) ?> | |||
</div> | |||
@@ -0,0 +1,47 @@ | |||
<?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; | |||
?> | |||
Un nouvel avis vient d'être envoyé par <?= Html::encode($username) ?> : | |||
<?= Html::encode($message) ?> | |||
@@ -0,0 +1,33 @@ | |||
<?php | |||
require_once dirname(__FILE__).'/_macros.php'; | |||
version( | |||
'11/09/2023', | |||
[ | |||
[ | |||
"[Site & espace producteur] Avis & suggestions : possibilité pour les clients d'envoyer des avis et suggestions à l'administrateur", | |||
"[Administration et espace producteur] Bulletins d'informations : gestion inscription / désinscription", | |||
"[Administration] Distributions > Commandes : possibilité de générer un BL pour une commande via le bouton 'Action'", | |||
"[Administration] Crédit : statut 'Payé' remplacé par 'Débité'", | |||
"[Administration] Distributions > Récapitulatif commandes : ajout d'une colonne BL (paramétrable dans Paramètres > Commandes > Exports)", | |||
"[Administration] Distributions : activation automatique de X semaines à l'avance (paramétrable dans Paramètres > Commandes > Divers)" | |||
], | |||
[ | |||
"[Administration] Utilisateurs > Crédit : formatage du montant du crédit dans les exports CSV", | |||
"[Administration] Utilisateurs > Liste : correctif tri par crédit" | |||
] | |||
], | |||
[ | |||
[ | |||
"[Administration] Header > liste producteurs : champs de recherche rapide", | |||
"[Administration] Dolibarr : génération automatique des factures producteurs" | |||
], | |||
[ | |||
"[Administration] Distributions : refactoring gestion des bons de livraisons", | |||
"[Administration] Tickets admin : flag pour savoir si un ticket a été lu par le producteur" | |||
] | |||
], | |||
); | |||
?> |
@@ -34,7 +34,9 @@ | |||
"loveorigami/yii2-bootstrap-toggle": "*", | |||
"justcoded/yii2-event-listener": "*", | |||
"ext-pdo": "*", | |||
"weluse/yii2-mailjet": "^0.2.0" | |||
"weluse/yii2-mailjet": "^0.2.0", | |||
"ext-json": "*", | |||
"ext-curl": "*" | |||
}, | |||
"require-dev": { | |||
"yiisoft/yii2-codeception": "*", |
@@ -0,0 +1,28 @@ | |||
<?php | |||
namespace console\commands; | |||
use common\logic\Distribution\Distribution\Wrapper\DistributionManager; | |||
use common\logic\Producer\Producer\Wrapper\ProducerManager; | |||
use yii\console\Controller; | |||
class ActiveDistributionsInAdvanceController extends Controller | |||
{ | |||
public function actionIndex() | |||
{ | |||
$producerManager = ProducerManager::getInstance(); | |||
$distributionManager = DistributionManager::getInstance(); | |||
$producersArray = $producerManager->findProducersActive(); | |||
foreach($producersArray as $producer) { | |||
\Yii::$app->logic->setProducerContext($producer); | |||
$weeksDistributionsActivatedInAdvance = $producerManager->getConfig('option_weeks_distributions_activated_in_advance'); | |||
if($weeksDistributionsActivatedInAdvance) { | |||
$date = new \DateTime('+'.$weeksDistributionsActivatedInAdvance.' weeks'); | |||
$distributionManager->activeDistributionByDate($date); | |||
} | |||
} | |||
} | |||
} | |||
?> |
@@ -0,0 +1,27 @@ | |||
<?php | |||
use yii\db\Migration; | |||
use yii\db\Schema; | |||
/** | |||
* Class m230904_064216_add_column_user_producer_newsletter | |||
*/ | |||
class m230904_064216_add_column_user_producer_newsletter extends Migration | |||
{ | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeUp() | |||
{ | |||
$this->addColumn('user_producer', 'newsletter', Schema::TYPE_BOOLEAN); | |||
$this->execute('UPDATE user_producer SET newsletter = 1;'); | |||
} | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeDown() | |||
{ | |||
$this->dropColumn('user_producer', 'newsletter'); | |||
} | |||
} |
@@ -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'); | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
<?php | |||
use yii\db\Migration; | |||
use yii\db\Schema; | |||
/** | |||
* Class m230906_060202_add_column_producer_option_export_display_column_delivery_note | |||
*/ | |||
class m230906_060202_add_column_producer_option_export_display_column_delivery_note extends Migration | |||
{ | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeUp() | |||
{ | |||
$this->addColumn('producer', 'option_export_display_column_delivery_note', Schema::TYPE_BOOLEAN); | |||
} | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeDown() | |||
{ | |||
$this->dropColumn('producer', 'option_export_display_column_delivery_note'); | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
<?php | |||
use yii\db\Migration; | |||
use yii\db\Schema; | |||
/** | |||
* Class m230908_085432_add_column_producer_option_weeks_distributions_activated_in_advance | |||
*/ | |||
class m230908_085432_add_column_producer_option_weeks_distributions_activated_in_advance extends Migration | |||
{ | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeUp() | |||
{ | |||
$this->addColumn('producer', 'option_weeks_distributions_activated_in_advance', Schema::TYPE_INTEGER); | |||
} | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeDown() | |||
{ | |||
$this->dropColumn('producer', 'option_weeks_distributions_activated_in_advance'); | |||
} | |||
} |
@@ -39,6 +39,7 @@ | |||
namespace frontend\controllers; | |||
use common\helpers\GlobalParam; | |||
use frontend\forms\OpinionForm; | |||
use frontend\forms\ProducerCodeForm; | |||
use GuzzleHttp\Client; | |||
use Yii; | |||
@@ -82,6 +83,9 @@ class SiteController extends FrontendController | |||
'roles' => ['@'], | |||
], | |||
], | |||
'denyCallback' => function($rule, $action) { | |||
return $this->redirect('index'); | |||
} | |||
], | |||
'verbs' => [ | |||
'class' => VerbFilter::class, | |||
@@ -294,22 +298,16 @@ class SiteController extends FrontendController | |||
public function actionContact() | |||
{ | |||
$model = new ContactForm(); | |||
$messageSent = false; | |||
if ($model->load(Yii::$app->request->post()) && $model->validate()) { | |||
if ($model->sendEmail(Yii::$app->parameterBag->get('adminEmail'))) { | |||
$this->setFlash('success', 'Votre message a bien été envoyé. Nous vous répondrons dès que possible.'); | |||
} | |||
else { | |||
$this->setFlash('error', 'Il y a eu une erreur lors de l\'envoi de votre message.'); | |||
} | |||
return $this->refresh(); | |||
} | |||
else { | |||
return $this->render('contact', [ | |||
'model' => $model, | |||
]); | |||
$model->sendEmail(Yii::$app->parameterBag->get('adminEmail')); | |||
$messageSent = true; | |||
} | |||
return $this->render('contact', [ | |||
'model' => $model, | |||
'messageSent' => $messageSent, | |||
]); | |||
} | |||
/** | |||
@@ -501,6 +499,21 @@ class SiteController extends FrontendController | |||
]); | |||
} | |||
public function actionOpinion() | |||
{ | |||
$opinionFormModel = new OpinionForm(); | |||
$opinionSent = false; | |||
if ($opinionFormModel->load(Yii::$app->request->post()) && $opinionFormModel->validate()) { | |||
$this->getOpinionManager()->sendOpinionEmailAdmin($opinionFormModel, $this->getUserCurrent()); | |||
$opinionSent = true; | |||
} | |||
return $this->render('opinion', [ | |||
'model' => $opinionFormModel, | |||
'opinionSent' => $opinionSent | |||
]); | |||
} | |||
/** | |||
* Affiche les mentions légales. | |||
*/ |
@@ -0,0 +1,87 @@ | |||
<?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 frontend\forms; | |||
use common\logic\User\User\Wrapper\UserManager; | |||
use Yii; | |||
use yii\base\Model; | |||
/** | |||
* ContactForm is the model behind the contact form. | |||
*/ | |||
class OpinionForm extends Model | |||
{ | |||
public $name; | |||
public $email; | |||
public $message; | |||
public $verifyCode; | |||
public $isTest; | |||
/** | |||
* @inheritdoc | |||
*/ | |||
public function rules() | |||
{ | |||
$userManager = UserManager::getInstance(); | |||
return [ | |||
[['message'], 'required', 'message' => 'Champs obligatoire'], | |||
[['name', 'email'], 'required', 'message' => 'Champs obligatoire', 'when' => function($model) use($userManager) { | |||
return $userManager->isCurrentGuest(); | |||
}], | |||
['email', 'email', 'message' => 'Email incorrect'], | |||
['isTest', 'string'], | |||
['verifyCode', 'captcha', 'message' => 'Veuillez recopier le code de vérification', 'when' => function($model) use($userManager) { | |||
return $model->isTest != 'isTest' && $userManager->isCurrentGuest(); | |||
}], | |||
]; | |||
} | |||
/** | |||
* @inheritdoc | |||
*/ | |||
public function attributeLabels() | |||
{ | |||
return [ | |||
'name' => 'Nom', | |||
'email' => 'Email', | |||
'message' => 'Message', | |||
'verifyCode' => 'Code de vérification', | |||
]; | |||
} | |||
} |
@@ -70,6 +70,7 @@ class SignupForm extends Model | |||
public $id_tax_rate_default; | |||
public $verifyCode; | |||
public $is_test; | |||
public $newsletter = true; | |||
/** | |||
* @inheritdoc | |||
@@ -96,7 +97,7 @@ class SignupForm extends Model | |||
[['name', 'lastname', 'phone', 'option_user_producer'], 'string', 'min' => 2, 'max' => 255], | |||
['password', 'required', 'message' => 'Champs obligatoire'], | |||
['password', 'string', 'min' => 6, 'tooShort' => 'Votre mot de passe doit contenir au moins 6 caractères'], | |||
['is_producer', 'boolean'], | |||
[['is_producer', 'newsletter'], 'boolean'], | |||
['cgv', 'boolean'], | |||
['cgv', function ($attribute, $params) { | |||
$cgv = $this->$attribute; | |||
@@ -222,6 +223,7 @@ class SignupForm extends Model | |||
// 'free_price' => 'Prix libre', | |||
'id_tax_rate_default' => 'TVA par défaut', | |||
'verifyCode' => 'Code de vérification', | |||
'newsletter' => "S'abonner au bulletin d'information de ce producteur" | |||
]; | |||
} | |||
@@ -253,7 +255,7 @@ class SignupForm extends Model | |||
\Yii::$app->logic->setProducerContext($producer); | |||
$producerManager->addUser($user, $producer); | |||
$producerManager->addUser($user, $producer, true, $this->newsletter); | |||
$userManager->sendEmailSignup($user, $producer); | |||
return $user; |
@@ -169,6 +169,7 @@ if ($userManager->isCurrentProducer()) { | |||
<footer id="footer"> | |||
<div class="container"> | |||
<a href="<?php echo $this->getUrlManager()->createUrl('site/service'); ?>">Fonctionnalités, services & tarifs</a> <span class="bull">•</span> | |||
<a href="<?php echo $this->getUrlManager()->createUrl('site/opinion'); ?>">Avis & suggestions</a> <span class="bull">•</span> | |||
<a href="<?php echo $this->getUrlManager()->createUrl('site/mentions'); ?>">Mentions légales</a> <span class="bull">•</span> | |||
<a href="<?php echo $this->getUrlManager()->createUrl('site/cgv'); ?>">Conditions générales de service</a> <span class="bull">•</span> | |||
<a href="<?php echo $this->getUrlManager()->createUrl('site/source-code'); ?>">Code source</a> |
@@ -45,34 +45,40 @@ use yii\captcha\Captcha; | |||
$this->setTitle('Contact'); | |||
$this->setIcon('envelope'); | |||
$this->setMeta('description', 'Pour toute remarque ou demande d\'information, nous vous proposons d\'utiliser ce formulaire de contact.') ; | |||
$this->setMeta('description', 'Pour toute demande d\'information, nous vous proposons d\'utiliser ce formulaire de contact.') ; | |||
$this->params['breadcrumbs'][] = $this->title; | |||
?> | |||
<div class="site-contact"> | |||
<div class="row"> | |||
<div class="col-lg-5"> | |||
<div class="alert alert-info"> | |||
Ce formulaire de contact vous permet de joindre le développeur de la plateforme Opendistrib. | |||
Si vous souhaitez joindre un producteur, merci de le faire directement depuis son espace producteur. | |||
</div> | |||
<div class="panel panel-default"> | |||
<div class="panel-body"> | |||
<?php $form = ActiveForm::begin(['id' => 'contact-form']); ?> | |||
<?= $form->field($model, 'name') ?> | |||
<?= $form->field($model, 'email') ?> | |||
<?= $form->field($model, 'subject') ?> | |||
<?= $form->field($model, 'body')->textArea(['rows' => 6]) ?> | |||
<?= $form->field($model, 'verifyCode')->widget(Captcha::className(), [ | |||
'template' => '<div class="row"><div class="col-lg-3">{image}</div><div class="col-lg-6">{input}</div></div>', | |||
]) ?> | |||
<?= $form->field($model, 'isTest')->hiddenInput() ?> | |||
<div class="form-group submit"> | |||
<?= Html::submitButton('Envoyer', ['class' => 'btn btn-primary', 'name' => 'contact-button']) ?> | |||
<div class="col-lg-6"> | |||
<?php if($messageSent): ?> | |||
<div class="alert alert-success text-center"> | |||
Merci pour votre message, je vous réponds dès que possible. | |||
</div> | |||
<?php else: ?> | |||
<div class="alert alert-warning"> | |||
Ce formulaire de contact vous permet de joindre le développeur de la plateforme Opendistrib. | |||
Si vous souhaitez joindre un producteur, merci de le faire directement depuis son espace producteur. | |||
</div> | |||
<div class="panel panel-default"> | |||
<div class="panel-body"> | |||
<?php $form = ActiveForm::begin(['id' => 'contact-form']); ?> | |||
<?= $form->field($model, 'name') ?> | |||
<?= $form->field($model, 'email') ?> | |||
<?= $form->field($model, 'subject') ?> | |||
<?= $form->field($model, 'body')->textArea(['rows' => 6]) ?> | |||
<?= $form->field($model, 'verifyCode')->widget(Captcha::className(), [ | |||
'template' => '<div class="row"><div class="col-lg-3">{image}</div><div class="col-lg-6">{input}</div></div>', | |||
]) ?> | |||
<?= $form->field($model, 'isTest')->hiddenInput() ?> | |||
<div class="form-group submit"> | |||
<?= Html::submitButton('Envoyer', ['class' => 'btn btn-primary', 'name' => 'contact-button']) ?> | |||
</div> | |||
<?php ActiveForm::end(); ?> | |||
</div> | |||
<?php ActiveForm::end(); ?> | |||
</div> | |||
</div> | |||
<?php endif; ?> | |||
</div> | |||
</div> | |||
@@ -0,0 +1,87 @@ | |||
<?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\bootstrap\ActiveForm; | |||
use yii\captcha\Captcha; | |||
/* @var $this yii\web\View */ | |||
/* @var $form yii\bootstrap\ActiveForm */ | |||
$this->setTitle('Avis & suggestions'); | |||
$this->setIcon('star'); | |||
//$this->setMeta('description', '') ; | |||
$this->params['breadcrumbs'][] = $this->title; | |||
?> | |||
<div class="site-opinion"> | |||
<div class="row"> | |||
<div class="col-lg-6"> | |||
<?php if($opinionSent): ?> | |||
<div class="alert alert-success text-center"> | |||
Merci pour votre participation, je vous fais un retour dès que possible. | |||
</div> | |||
<?php else: ?> | |||
<div class="alert alert-warning"> | |||
Vous pouvez utiliser ce formulaire pour m'envoyer toutes vos remarques et suggestions d'amélioration. | |||
</div> | |||
<div class="panel panel-default"> | |||
<div class="panel-body"> | |||
<?php $form = ActiveForm::begin(['id' => 'opinion-form']); ?> | |||
<?php if (Yii::$app->user->isGuest): ?> | |||
<?= $form->field($model, 'name') ?> | |||
<?= $form->field($model, 'email') ?> | |||
<?php endif; ?> | |||
<?= $form->field($model, 'message')->textArea(['rows' => 6]) ?> | |||
<?php if (Yii::$app->user->isGuest): ?> | |||
<?= $form->field($model, 'verifyCode')->widget(Captcha::className(), [ | |||
'template' => '<div class="row"><div class="col-lg-3">{image}</div><div class="col-lg-6">{input}</div></div>', | |||
]) ?> | |||
<?php endif; ?> | |||
<?= $form->field($model, 'isTest')->hiddenInput() ?> | |||
<div class="form-group submit"> | |||
<?= Html::submitButton('Envoyer', ['class' => 'btn btn-primary', 'name' => 'opinion-button']) ?> | |||
</div> | |||
<?php ActiveForm::end(); ?> | |||
</div> | |||
</div> | |||
<?php endif; ?> | |||
</div> | |||
</div> | |||
</div> |
@@ -100,6 +100,7 @@ $this->setMeta('description', 'Veuillez vous connecter pour réserver les produi | |||
<?= $form->field($signupForm, 'lastname') ?> | |||
<?= $form->field($signupForm, 'name') ?> | |||
<?= $form->field($signupForm, 'phone') ?> | |||
<?= $form->field($signupForm, 'newsletter')->checkbox() ?> | |||
<?php if(strlen($producer->code)): ?> | |||
<?= $form->field($signupForm, 'code',[ | |||
'inputTemplate' => '<div class="input-group"><span class="input-group-addon"><span class="glyphicon glyphicon-lock"></span></span>{input}</div>', |
@@ -87,7 +87,9 @@ $this->params['breadcrumbs'][] = $this->title; | |||
<?= $form->field($model, 'cgv')->checkbox()->label('J\'accepte les <button type="button" class="btn btn-xs btn-default btn-modal-cgv" data-toggle="modal" data-target="#modal-cgv">conditions générales de service</button> et les <button type="button" class="btn btn-xs btn-default btn-modal-prices" data-toggle="modal" data-target="#modal-prices">conditions tarifaires</button>.') ?> | |||
</div> | |||
<div id="fields-user"> | |||
<?= $form->field($model, 'id_producer')->dropDownList($dataProducers, ['prompt' => '--','encode' => false,'options' => $optionsProducers]) ?> | |||
<?= $form->field($model, 'id_producer') | |||
->dropDownList($dataProducers, ['prompt' => '--','encode' => false,'options' => $optionsProducers]) ?> | |||
<?= $form->field($model, 'newsletter')->checkbox() ?> | |||
<div id="bloc-code-acces"> | |||
<?= $form->field($model, 'code',[ | |||
'inputTemplate' => '<div class="input-group"><span class="input-group-addon"><span class="glyphicon glyphicon-lock"></span></span>{input}</div>', |
@@ -1326,7 +1326,7 @@ nav#menu-producer ul li a:hover { | |||
} | |||
/* line 1395, ../sass/screen.scss */ | |||
.site-contact .col-lg-5 { | |||
.site-contact .col-lg-6 { | |||
margin: 0px auto; | |||
float: none; | |||
} | |||
@@ -1335,12 +1335,26 @@ nav#menu-producer ul li a:hover { | |||
text-align: center; | |||
} | |||
/* line 1407, ../sass/screen.scss */ | |||
/* line 1406, ../sass/screen.scss */ | |||
.site-opinion .col-lg-6 { | |||
margin: 0px auto; | |||
float: none; | |||
} | |||
/* line 1411, ../sass/screen.scss */ | |||
.site-opinion .field-opinionform-istest { | |||
display: none; | |||
} | |||
/* line 1415, ../sass/screen.scss */ | |||
.site-opinion .form-group.submit { | |||
text-align: center; | |||
} | |||
/* line 1422, ../sass/screen.scss */ | |||
#site-prices .panel p { | |||
padding-bottom: 0px; | |||
} | |||
/* line 1414, ../sass/screen.scss */ | |||
/* line 1429, ../sass/screen.scss */ | |||
#contact-form .field-contactform-istest { | |||
display: none; | |||
} |
@@ -197,8 +197,10 @@ function opendistrib_signup() { | |||
}); | |||
opendistrib_signup_code_producer(); | |||
opendistrib_signup_newsletter(); | |||
$('#signupform-id_producer').change(function () { | |||
opendistrib_signup_code_producer(); | |||
opendistrib_signup_newsletter(); | |||
}); | |||
// modals | |||
@@ -231,4 +233,16 @@ function opendistrib_signup_code_producer() { | |||
} | |||
} | |||
function opendistrib_signup_newsletter() { | |||
if($('#signupform-id_producer').length) { | |||
var $fieldNewsletter = $('.field-signupform-newsletter'); | |||
if($('#signupform-id_producer').val()) { | |||
$fieldNewsletter.show(); | |||
} | |||
else { | |||
$fieldNewsletter.hide(); | |||
} | |||
} | |||
} | |||
@@ -1392,7 +1392,7 @@ nav#menu-producer { | |||
} | |||
.site-contact { | |||
.col-lg-5 { | |||
.col-lg-6 { | |||
margin: 0px auto; | |||
float: none; | |||
} | |||
@@ -1402,6 +1402,21 @@ nav#menu-producer { | |||
} | |||
} | |||
.site-opinion { | |||
.col-lg-6 { | |||
margin: 0px auto; | |||
float: none; | |||
} | |||
.field-opinionform-istest { | |||
display: none; | |||
} | |||
.form-group.submit { | |||
text-align: center; | |||
} | |||
} | |||
#site-prices { | |||
.panel { | |||
p { |
@@ -0,0 +1,75 @@ | |||
<?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 producer\controllers; | |||
class NewsletterController extends ProducerBaseController | |||
{ | |||
public function behaviors() | |||
{ | |||
return []; | |||
} | |||
public function actionIndex() | |||
{ | |||
return $this->render('index', [ | |||
'user' => $this->getUserCurrent(), | |||
'producer' => $this->getProducerCurrent() | |||
]); | |||
} | |||
public function actionSubscribe() | |||
{ | |||
$userManager = $this->getUserManager(); | |||
$userCurrent = $this->getUserCurrent(); | |||
$userManager->subscribeUserNewsletter($userCurrent); | |||
$this->setFlash('success', "Votre inscription au bulletin d'information a bien été prise en compte."); | |||
return $this->redirect('index'); | |||
} | |||
public function actionUnsubscribe() | |||
{ | |||
$userManager = $this->getUserManager(); | |||
$userCurrent = $this->getUserCurrent(); | |||
$userManager->unsubscribeUserNewsletter($userCurrent); | |||
$this->setFlash('success', "À partir de maintenant, vous ne recevrez plus d'email de la part de ce producteur."); | |||
return $this->redirect('index'); | |||
} | |||
} | |||
?> |
@@ -128,6 +128,7 @@ if (!Yii::$app->user->isGuest) { | |||
->count(); | |||
$labelOrders = $countOrders > 0 ? 'success' : 'default'; | |||
$isUserSubscribedNewsletter = $userManager->isUserSubscribedNewsletter($userCurrent); | |||
echo Nav::widget([ | |||
'encodeLabels' => false, | |||
@@ -168,17 +169,17 @@ if (!Yii::$app->user->isGuest) { | |||
'visible' => !Yii::$app->user->isGuest && $producer->credit, | |||
'active' => $this->getControllerAction() == 'credit/history', | |||
], | |||
[ | |||
'label' => '<span class="glyphicon glyphicon-bullhorn"></span> Bulletin d\'information <span class="label label-'.($isUserSubscribedNewsletter ? 'success' : 'danger').'">'.($isUserSubscribedNewsletter ? 'Oui' : 'Non').'</span>', | |||
'url' => $this->getUrlManagerProducer()->createUrl(['newsletter/index']), | |||
'visible' => !Yii::$app->user->isGuest, | |||
'active' => $this->getControllerAction() == 'newsletter/index', | |||
], | |||
[ | |||
'label' => '<span class="glyphicon glyphicon-envelope"></span> Contact', | |||
'url' => $this->getUrlManagerProducer()->createUrl(['site/contact']), | |||
'active' => $this->getControllerAction() == 'site/contact', | |||
], | |||
/*[ | |||
'label' => '<span class="glyphicon glyphicon-cog"></span> Administration', | |||
'url' => $this->getUrlManagerBackend()->createAbsoluteUrl(['site/index']), | |||
'visible' => isset(Yii::$app->user->identity) && $this->getUserManager()->isProducer(\Yii::$app->user->identity), | |||
'options' => ['id' => 'btn-administration'] | |||
],*/ | |||
], | |||
]); | |||
?> | |||
@@ -276,6 +277,7 @@ if (!Yii::$app->user->isGuest) { | |||
<footer id="footer" class="container"> | |||
<div class="content"> | |||
<a href="<?php echo \Yii::$app->urlManagerFrontend->createAbsoluteUrl(['site/index']); ?>">Opendistrib</a> • | |||
<a href="<?php echo \Yii::$app->urlManagerFrontend->createAbsoluteUrl(['site/opinion']); ?>">Avis & suggestions</a> • | |||
<a href="<?php echo \Yii::$app->urlManagerFrontend->createAbsoluteUrl(['site/mentions']); ?>">Mentions | |||
légales</a> • | |||
<a href="<?php echo \Yii::$app->urlManagerFrontend->createAbsoluteUrl(['site/cgv']); ?>">CGS</a> • |
@@ -0,0 +1,71 @@ | |||
<?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 common\logic\User\User\Wrapper\UserManager; | |||
use yii\helpers\Html; | |||
$userManager = UserManager::getInstance(); | |||
$this->setTitle("Bulletin d'information"); | |||
?> | |||
<div class="newsletter-index"> | |||
<?php if($userManager->isUserSubscribedNewsletter($user)): ?> | |||
<div class="panel panel-default"> | |||
<div class="panel-body"> | |||
Vous êtes inscrit au bulletin d'information <strong><?= Html::encode($producer->name) ?></strong>. | |||
</div> | |||
</div> | |||
<p> | |||
<a class="btn btn-danger" href="<?= $this->getUrlManagerProducer()->createUrl(['newsletter/unsubscribe']) ?>"> | |||
Me désinscrire | |||
</a> | |||
</p> | |||
<?php else: ?> | |||
<div class="panel panel-default"> | |||
<div class="panel-body"> | |||
Vous n'êtes pas inscrit au bulletin d'information <strong><?= Html::encode($producer->name) ?></strong>. | |||
</div> | |||
</div> | |||
<p> | |||
<a class="btn btn-success" href="<?= $this->getUrlManagerProducer()->createUrl(['newsletter/subscribe']) ?>"> | |||
M'inscrire | |||
</a> | |||
</p> | |||
<?php endif; ?> | |||
</div> |
@@ -148,79 +148,84 @@ body { | |||
clear: both; | |||
} | |||
/* line 64, ../sass/_layout.scss */ | |||
/* line 63, ../sass/_layout.scss */ | |||
.panel strong { | |||
font-weight: bold; | |||
} | |||
/* line 68, ../sass/_layout.scss */ | |||
.modal-backdrop.in { | |||
z-index: 10; | |||
} | |||
/* line 69, ../sass/_layout.scss */ | |||
/* line 73, ../sass/_layout.scss */ | |||
#section-user-top .navbar-default { | |||
background-color: white; | |||
} | |||
/* line 74, ../sass/_layout.scss */ | |||
/* line 78, ../sass/_layout.scss */ | |||
#main { | |||
position: relative; | |||
} | |||
/* line 76, ../sass/_layout.scss */ | |||
/* line 80, ../sass/_layout.scss */ | |||
#main .btn-primary { | |||
background-color: #F39C12; | |||
border: solid 1px #F39C12; | |||
color: white; | |||
} | |||
/* line 81, ../sass/_layout.scss */ | |||
/* line 85, ../sass/_layout.scss */ | |||
#main .btn-primary:hover, #main .btn-primary:active, #main .btn-primary:focus { | |||
background-color: #e08e0b; | |||
border: solid 1px #F39C12; | |||
color: white; | |||
} | |||
/* line 90, ../sass/_layout.scss */ | |||
/* line 94, ../sass/_layout.scss */ | |||
.btn { | |||
background-image: none; | |||
} | |||
/* line 94, ../sass/_layout.scss */ | |||
/* line 98, ../sass/_layout.scss */ | |||
#main .alert { | |||
background-image: none; | |||
background-color: white; | |||
border-bottom-width: 3px; | |||
} | |||
/* line 102, ../sass/_layout.scss */ | |||
/* line 106, ../sass/_layout.scss */ | |||
.alert.alert-warning a { | |||
color: #8a6d3b; | |||
text-decoration: underline; | |||
} | |||
/* line 109, ../sass/_layout.scss */ | |||
/* line 113, ../sass/_layout.scss */ | |||
.alert.alert-danger a { | |||
color: #a94442; | |||
text-decoration: underline; | |||
} | |||
/* line 119, ../sass/_layout.scss */ | |||
/* line 123, ../sass/_layout.scss */ | |||
ul.pagination li.active a { | |||
background-color: #F39C12; | |||
border: solid 1px #F39C12; | |||
} | |||
/* line 123, ../sass/_layout.scss */ | |||
/* line 127, ../sass/_layout.scss */ | |||
ul.pagination li.active a:hover { | |||
background-color: white; | |||
border: solid 1px white; | |||
color: #F39C12; | |||
} | |||
/* line 130, ../sass/_layout.scss */ | |||
/* line 134, ../sass/_layout.scss */ | |||
ul.pagination li a { | |||
color: #F39C12; | |||
} | |||
/* line 133, ../sass/_layout.scss */ | |||
/* line 137, ../sass/_layout.scss */ | |||
ul.pagination li a:hover, ul.pagination li a:focus, ul.pagination li a:active { | |||
background-color: white; | |||
border: solid 1px white; | |||
color: #F39C12; | |||
} | |||
/* line 143, ../sass/_layout.scss */ | |||
/* line 147, ../sass/_layout.scss */ | |||
.product-name-description-block .name { | |||
font-family: "capsuularegular"; | |||
color: black; | |||
@@ -228,28 +233,28 @@ ul.pagination li a:hover, ul.pagination li a:focus, ul.pagination li a:active { | |||
line-height: 25px; | |||
font-weight: bold; | |||
} | |||
/* line 151, ../sass/_layout.scss */ | |||
/* line 155, ../sass/_layout.scss */ | |||
.product-name-description-block .other { | |||
font-family: "capsuularegular"; | |||
color: black; | |||
font-weight: bold; | |||
font-size: 17px; | |||
} | |||
/* line 158, ../sass/_layout.scss */ | |||
/* line 162, ../sass/_layout.scss */ | |||
.product-name-description-block .description, | |||
.product-name-description-block .description-long { | |||
color: gray; | |||
} | |||
/* line 164, ../sass/_layout.scss */ | |||
/* line 168, ../sass/_layout.scss */ | |||
.product-name-description-block .description-long a { | |||
color: #F39C12; | |||
} | |||
/* line 167, ../sass/_layout.scss */ | |||
/* line 171, ../sass/_layout.scss */ | |||
.product-name-description-block .description-long .content { | |||
display: none; | |||
} | |||
/* line 173, ../sass/_layout.scss */ | |||
/* line 177, ../sass/_layout.scss */ | |||
#left { | |||
background-color: #FFF8DC; | |||
text-align: center; | |||
@@ -257,12 +262,12 @@ ul.pagination li a:hover, ul.pagination li a:focus, ul.pagination li a:active { | |||
padding: 0px; | |||
position: relative; | |||
} | |||
/* line 180, ../sass/_layout.scss */ | |||
/* line 184, ../sass/_layout.scss */ | |||
#left .fixed { | |||
position: fixed; | |||
display: none; | |||
} | |||
/* line 186, ../sass/_layout.scss */ | |||
/* line 190, ../sass/_layout.scss */ | |||
#left #logo { | |||
position: relative; | |||
background-color: white; | |||
@@ -277,7 +282,7 @@ ul.pagination li a:hover, ul.pagination li a:focus, ul.pagination li a:active { | |||
text-align: center; | |||
overflow: hidden; | |||
} | |||
/* line 198, ../sass/_layout.scss */ | |||
/* line 202, ../sass/_layout.scss */ | |||
#left #logo img { | |||
position: absolute; | |||
top: 50%; | |||
@@ -286,11 +291,11 @@ ul.pagination li a:hover, ul.pagination li a:focus, ul.pagination li a:active { | |||
max-width: 90px; | |||
max-height: 90px; | |||
} | |||
/* line 208, ../sass/_layout.scss */ | |||
/* line 212, ../sass/_layout.scss */ | |||
#left h1, #left h2, #left #infos, #left #infos a { | |||
color: #323232; | |||
} | |||
/* line 212, ../sass/_layout.scss */ | |||
/* line 216, ../sass/_layout.scss */ | |||
#left h1 { | |||
text-transform: uppercase; | |||
font-family: "highvoltageregular"; | |||
@@ -301,37 +306,37 @@ ul.pagination li a:hover, ul.pagination li a:focus, ul.pagination li a:active { | |||
text-align: center; | |||
font-weight: normal; | |||
} | |||
/* line 223, ../sass/_layout.scss */ | |||
/* line 227, ../sass/_layout.scss */ | |||
#left h2 { | |||
font-family: "capsuularegular"; | |||
font-size: 15px; | |||
font-weight: normal; | |||
text-align: center; | |||
} | |||
/* line 229, ../sass/_layout.scss */ | |||
/* line 233, ../sass/_layout.scss */ | |||
#left h2 .favorite { | |||
padding-left: 0px; | |||
} | |||
/* line 232, ../sass/_layout.scss */ | |||
/* line 236, ../sass/_layout.scss */ | |||
#left h2 .favorite .glyphicon { | |||
font-size: 14px; | |||
} | |||
/* line 237, ../sass/_layout.scss */ | |||
/* line 241, ../sass/_layout.scss */ | |||
#left h2 a { | |||
color: #323232; | |||
} | |||
/* line 243, ../sass/_layout.scss */ | |||
/* line 247, ../sass/_layout.scss */ | |||
#left nav#main-nav { | |||
background-color: white; | |||
border: solid 1px #e0e0e0; | |||
border-bottom: 0px none; | |||
margin-top: 20px; | |||
} | |||
/* line 250, ../sass/_layout.scss */ | |||
/* line 254, ../sass/_layout.scss */ | |||
#left nav#main-nav ul li { | |||
display: block; | |||
} | |||
/* line 253, ../sass/_layout.scss */ | |||
/* line 257, ../sass/_layout.scss */ | |||
#left nav#main-nav ul li a { | |||
color: #323232; | |||
color: black; | |||
@@ -341,23 +346,23 @@ ul.pagination li a:hover, ul.pagination li a:focus, ul.pagination li a:active { | |||
display: block; | |||
text-align: left; | |||
} | |||
/* line 262, ../sass/_layout.scss */ | |||
/* line 266, ../sass/_layout.scss */ | |||
#left nav#main-nav ul li a .glyphicon { | |||
font-size: 15px; | |||
margin-right: 3px; | |||
} | |||
/* line 267, ../sass/_layout.scss */ | |||
/* line 271, ../sass/_layout.scss */ | |||
#left nav#main-nav ul li a span.label { | |||
padding-bottom: 3px; | |||
font-family: "Arial"; | |||
float: right; | |||
} | |||
/* line 275, ../sass/_layout.scss */ | |||
/* line 279, ../sass/_layout.scss */ | |||
#left nav#main-nav ul li.active span.label, #left nav#main-nav ul li a:hover span.label { | |||
background-color: #e08e0b; | |||
color: white; | |||
} | |||
/* line 281, ../sass/_layout.scss */ | |||
/* line 285, ../sass/_layout.scss */ | |||
#left nav#main-nav ul li a:hover, #left nav#main-nav ul li.active a { | |||
background: #F39C12; | |||
color: white; | |||
@@ -365,22 +370,22 @@ ul.pagination li a:hover, ul.pagination li a:focus, ul.pagination li a:active { | |||
-webkit-border-radius: 0px; | |||
border-radius: 0px; | |||
} | |||
/* line 290, ../sass/_layout.scss */ | |||
/* line 294, ../sass/_layout.scss */ | |||
#left nav#main-nav ul li#btn-administration a { | |||
color: #F39C12; | |||
} | |||
/* line 293, ../sass/_layout.scss */ | |||
/* line 297, ../sass/_layout.scss */ | |||
#left nav#main-nav ul li#btn-administration a:hover { | |||
color: white; | |||
} | |||
/* line 301, ../sass/_layout.scss */ | |||
/* line 305, ../sass/_layout.scss */ | |||
#left nav#main-nav #user { | |||
color: #F39C12; | |||
float: right; | |||
padding: 10px; | |||
} | |||
/* line 309, ../sass/_layout.scss */ | |||
/* line 313, ../sass/_layout.scss */ | |||
#main { | |||
background-color: #FFF8DC; | |||
border: solid 1px #e0e0e0; | |||
@@ -388,13 +393,13 @@ ul.pagination li a:hover, ul.pagination li a:focus, ul.pagination li a:active { | |||
padding: 0px; | |||
background-color: white; | |||
} | |||
/* line 316, ../sass/_layout.scss */ | |||
/* line 320, ../sass/_layout.scss */ | |||
#main #img-big { | |||
height: 130px; | |||
overflow: hidden; | |||
position: relative; | |||
} | |||
/* line 321, ../sass/_layout.scss */ | |||
/* line 325, ../sass/_layout.scss */ | |||
#main #img-big img.img-photo { | |||
width: 100%; | |||
position: absolute; | |||
@@ -402,7 +407,7 @@ ul.pagination li a:hover, ul.pagination li a:focus, ul.pagination li a:active { | |||
left: 50%; | |||
transform: translate(-50%, -50%); | |||
} | |||
/* line 331, ../sass/_layout.scss */ | |||
/* line 335, ../sass/_layout.scss */ | |||
#main #infos-producer { | |||
padding: 5px 10px; | |||
margin-bottom: 0px; | |||
@@ -412,20 +417,20 @@ ul.pagination li a:hover, ul.pagination li a:focus, ul.pagination li a:active { | |||
border-bottom: solid 1px #e0e0e0; | |||
color: gray; | |||
} | |||
/* line 340, ../sass/_layout.scss */ | |||
/* line 344, ../sass/_layout.scss */ | |||
#main #infos-producer strong { | |||
font-weight: bold; | |||
} | |||
/* line 344, ../sass/_layout.scss */ | |||
/* line 348, ../sass/_layout.scss */ | |||
#main #infos-producer .favorite { | |||
float: right; | |||
color: gray; | |||
} | |||
/* line 347, ../sass/_layout.scss */ | |||
/* line 351, ../sass/_layout.scss */ | |||
#main #infos-producer .favorite a { | |||
color: black; | |||
} | |||
/* line 353, ../sass/_layout.scss */ | |||
/* line 357, ../sass/_layout.scss */ | |||
#main h2#page-title { | |||
padding-left: 15px; | |||
padding-right: 15px; | |||
@@ -440,36 +445,36 @@ ul.pagination li a:hover, ul.pagination li a:focus, ul.pagination li a:active { | |||
top: -10px; | |||
text-align: left; | |||
} | |||
/* line 367, ../sass/_layout.scss */ | |||
/* line 371, ../sass/_layout.scss */ | |||
#main h2#page-title #buttons { | |||
margin-bottom: 15px; | |||
font-family: "Arial"; | |||
} | |||
/* line 374, ../sass/_layout.scss */ | |||
/* line 378, ../sass/_layout.scss */ | |||
#main #content { | |||
padding: 0px 20px 20px 20px; | |||
padding-bottom: 40px; | |||
min-height: 300px; | |||
} | |||
/* line 379, ../sass/_layout.scss */ | |||
/* line 383, ../sass/_layout.scss */ | |||
#main #content h1, #main #content h2, #main #content h3, #main #content h4, #main #content h5, #main #content h6 { | |||
font-family: "highvoltageregular"; | |||
margin-top: 30px; | |||
margin-bottom: 20px; | |||
} | |||
/* line 384, ../sass/_layout.scss */ | |||
/* line 388, ../sass/_layout.scss */ | |||
#main #content h1.first, #main #content h2.first, #main #content h3.first, #main #content h4.first, #main #content h5.first, #main #content h6.first { | |||
margin-top: 0px; | |||
} | |||
/* line 389, ../sass/_layout.scss */ | |||
/* line 393, ../sass/_layout.scss */ | |||
#main #content h1 { | |||
font-size: 30px; | |||
} | |||
/* line 393, ../sass/_layout.scss */ | |||
/* line 397, ../sass/_layout.scss */ | |||
#main #content h2 { | |||
font-size: 25px; | |||
} | |||
/* line 398, ../sass/_layout.scss */ | |||
/* line 402, ../sass/_layout.scss */ | |||
#main #content h3 { | |||
font-family: "capsuularegular"; | |||
text-transform: uppercase; | |||
@@ -478,29 +483,29 @@ ul.pagination li a:hover, ul.pagination li a:focus, ul.pagination li a:active { | |||
margin-bottom: 30px; | |||
margin-top: 45px; | |||
} | |||
/* line 406, ../sass/_layout.scss */ | |||
/* line 410, ../sass/_layout.scss */ | |||
#main #content h3 span { | |||
padding-top: 14px; | |||
color: #323232; | |||
} | |||
/* line 412, ../sass/_layout.scss */ | |||
/* line 416, ../sass/_layout.scss */ | |||
#main #content h4 { | |||
font-size: 20px; | |||
} | |||
/* line 416, ../sass/_layout.scss */ | |||
/* line 420, ../sass/_layout.scss */ | |||
#main #content h5 { | |||
font-size: 18px; | |||
} | |||
/* line 420, ../sass/_layout.scss */ | |||
/* line 424, ../sass/_layout.scss */ | |||
#main #content h6 { | |||
font-size: 16px; | |||
} | |||
/* line 426, ../sass/_layout.scss */ | |||
/* line 430, ../sass/_layout.scss */ | |||
#main #content form .form-group .hint-block { | |||
color: gray; | |||
} | |||
/* line 434, ../sass/_layout.scss */ | |||
/* line 438, ../sass/_layout.scss */ | |||
#footer-producer { | |||
text-align: center; | |||
position: absolute; | |||
@@ -508,28 +513,28 @@ ul.pagination li a:hover, ul.pagination li a:focus, ul.pagination li a:active { | |||
left: 0px; | |||
width: 100%; | |||
} | |||
/* line 441, ../sass/_layout.scss */ | |||
/* line 445, ../sass/_layout.scss */ | |||
#footer-producer a { | |||
color: #F39C12; | |||
} | |||
/* line 443, ../sass/_layout.scss */ | |||
/* line 447, ../sass/_layout.scss */ | |||
#footer-producer a:active { | |||
text-decoration: underline; | |||
} | |||
/* line 449, ../sass/_layout.scss */ | |||
/* line 453, ../sass/_layout.scss */ | |||
#footer { | |||
background-color: #FFF8DC; | |||
height: 100px; | |||
float: right; | |||
text-align: center; | |||
} | |||
/* line 455, ../sass/_layout.scss */ | |||
/* line 459, ../sass/_layout.scss */ | |||
#footer .content { | |||
padding-top: 20px; | |||
color: black; | |||
} | |||
/* line 459, ../sass/_layout.scss */ | |||
/* line 463, ../sass/_layout.scss */ | |||
#footer .content a { | |||
color: black; | |||
font-family: "capsuularegular"; | |||
@@ -537,11 +542,11 @@ ul.pagination li a:hover, ul.pagination li a:focus, ul.pagination li a:active { | |||
padding-left: 10px; | |||
padding-right: 10px; | |||
} | |||
/* line 466, ../sass/_layout.scss */ | |||
/* line 470, ../sass/_layout.scss */ | |||
#footer .content a:hover { | |||
text-decoration: underline; | |||
} | |||
/* line 473, ../sass/_layout.scss */ | |||
/* line 477, ../sass/_layout.scss */ | |||
#footer #code-source img { | |||
height: 20px; | |||
} |
@@ -59,6 +59,10 @@ body { | |||
a { | |||
//color: $color1; | |||
} | |||
strong { | |||
font-weight: bold; | |||
} | |||
} | |||
.modal-backdrop.in { |