<?php | |||||
/** | |||||
* Copyright Souke (2018) | |||||
* | |||||
* contact@souke.fr | |||||
* | |||||
* Ce logiciel est un programme informatique servant à aider les producteurs | |||||
* à distribuer leur production en circuits courts. | |||||
* | |||||
* Ce logiciel est régi par la licence CeCILL soumise au droit français et | |||||
* respectant les principes de diffusion des logiciels libres. Vous pouvez | |||||
* utiliser, modifier et/ou redistribuer ce programme sous les conditions | |||||
* de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA | |||||
* sur le site "http://www.cecill.info". | |||||
* | |||||
* En contrepartie de l'accessibilité au code source et des droits de copie, | |||||
* de modification et de redistribution accordés par cette licence, il n'est | |||||
* offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons, | |||||
* seule une responsabilité restreinte pèse sur l'auteur du programme, le | |||||
* titulaire des droits patrimoniaux et les concédants successifs. | |||||
* | |||||
* A cet égard l'attention de l'utilisateur est attirée sur les risques | |||||
* associés au chargement, à l'utilisation, à la modification et/ou au | |||||
* développement et à la reproduction du logiciel par l'utilisateur étant | |||||
* donné sa spécificité de logiciel libre, qui peut le rendre complexe à | |||||
* manipuler et qui le réserve donc à des développeurs et des professionnels | |||||
* avertis possédant des connaissances informatiques approfondies. Les | |||||
* utilisateurs sont donc invités à charger et tester l'adéquation du | |||||
* logiciel à leurs besoins dans des conditions permettant d'assurer la | |||||
* sécurité de leurs systèmes et ou de leurs données et, plus généralement, | |||||
* à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. | |||||
* | |||||
* Le fait que vous puissiez accéder à cet en-tête signifie que vous avez | |||||
* pris connaissance de la licence CeCILL, et que vous en avez accepté les | |||||
* termes. | |||||
*/ | |||||
namespace backend\controllers; | |||||
use backend\controllers\BackendController; | |||||
use domain\Communication\AutomaticEmail\AutomaticEmail; | |||||
use domain\Feature\Feature\Feature; | |||||
use domain\Product\Accessory\Accessory; | |||||
use yii\base\Response; | |||||
use yii\db\StaleObjectException; | |||||
use yii\filters\AccessControl; | |||||
use yii\web\NotFoundHttpException; | |||||
class AutomaticEmailController extends BackendController | |||||
{ | |||||
public function behaviors() | |||||
{ | |||||
return [ | |||||
'access' => [ | |||||
'class' => AccessControl::class, | |||||
'rules' => [ | |||||
[ | |||||
'allow' => true, | |||||
'roles' => ['@'], | |||||
'matchCallback' => function ($rule, $action) { | |||||
return $this->getUserModule()->getAuthorizationChecker() | |||||
->isGrantedAsProducer($this->getUserCurrent()) | |||||
&& $this->getFeatureModule()->getChecker() | |||||
->isEnabled(Feature::ALIAS_AUTOMATIC_EMAIL); | |||||
} | |||||
] | |||||
], | |||||
], | |||||
]; | |||||
} | |||||
public function actionIndex() | |||||
{ | |||||
return $this->render('index', [ | |||||
'dataProvider' => $this->getAutomaticEmailModule()->getRepository() | |||||
->queryAutomaticEmails()->getDataProvider(20), | |||||
]); | |||||
} | |||||
public function actionCreate() | |||||
{ | |||||
$automaticEmailModule = $this->getAutomaticEmailModule(); | |||||
$automaticEmailModel = $automaticEmailModule->getBuilder()->instanciateAutomaticEmail($this->getProducerCurrent()); | |||||
if ($automaticEmailModel->load(\Yii::$app->request->post()) && $automaticEmailModel->validate()) { | |||||
$automaticEmail = $automaticEmailModule->getManager()->createAutomaticEmail( | |||||
$this->getProducerCurrent(), | |||||
$automaticEmailModel->getDay(), | |||||
$automaticEmailModel->getDelayBeforeDistribution(), | |||||
$automaticEmailModel->getSubject(), | |||||
$automaticEmailModel->getMessage(), | |||||
$automaticEmailModel->getIntegrateProductList() | |||||
); | |||||
$this->setFlash('success', "Email automatique ajouté"); | |||||
return $this->redirectAfterSave('automatic-email', $automaticEmail->getId()); | |||||
} | |||||
return $this->render('create', [ | |||||
'automaticEmail' => $automaticEmailModel | |||||
]); | |||||
} | |||||
public function actionUpdate(int $id) | |||||
{ | |||||
$automaticEmail = $this->findAutomaticEmail($id); | |||||
if ($automaticEmail->load(\Yii::$app->request->post()) && $automaticEmail->validate() && $automaticEmail->save()) { | |||||
$this->setFlash('success', "Email automatique modifié"); | |||||
return $this->redirectAfterSave('automatic-email', $automaticEmail->getId()); | |||||
} | |||||
return $this->render('update', [ | |||||
'automaticEmail' => $automaticEmail | |||||
]); | |||||
} | |||||
public function actionDelete(int $id): Response | |||||
{ | |||||
$automaticEmail = $this->findAutomaticEmail($id); | |||||
if($automaticEmail->delete()) { | |||||
$this->setFlash('success', "Email automatique supprimé"); | |||||
} | |||||
return $this->redirect('index'); | |||||
} | |||||
protected function findAutomaticEmail($id): AutomaticEmail | |||||
{ | |||||
if (($automaticEmail = $this->getAutomaticEmailModule()->getRepository()->findOneAutomaticEmailById($id)) !== null) { | |||||
return $automaticEmail; | |||||
} else { | |||||
throw new NotFoundHttpException("L'email automatique n'a pas été trouvé."); | |||||
} | |||||
} | |||||
} |
use backend\models\MailForm; | use backend\models\MailForm; | ||||
use common\helpers\GlobalParam; | use common\helpers\GlobalParam; | ||||
use kartik\mpdf\Pdf; | |||||
use domain\Communication\Email\ContactListResolver; | |||||
use domain\Communication\Email\EmailGenerator; | |||||
use domain\PointSale\PointSale\PointSale; | use domain\PointSale\PointSale\PointSale; | ||||
use kartik\mpdf\Pdf; | |||||
use yii\filters\AccessControl; | use yii\filters\AccessControl; | ||||
use yii\filters\VerbFilter; | use yii\filters\VerbFilter; | ||||
$usersPointSaleHasOrder = 0, | $usersPointSaleHasOrder = 0, | ||||
$idDistribution = 0) | $idDistribution = 0) | ||||
{ | { | ||||
$producerCurrent = $this->getProducerCurrent(); | |||||
$userModule = $this->getUserModule(); | |||||
$distributionModule = $this->getDistributionModule(); | |||||
$emailModule = $this->getEmailModule(); | |||||
$mailForm = new MailForm(); | $mailForm = new MailForm(); | ||||
// Sujet et message par défaut | // Sujet et message par défaut | ||||
$mailForm->subject = $this->getProducerModule()->getSolver()->getConfig('option_communicate_email_default_subject'); | $mailForm->subject = $this->getProducerModule()->getSolver()->getConfig('option_communicate_email_default_subject'); | ||||
$mailForm->message = $this->getProducerModule()->getSolver()->getConfig('option_communicate_email_default_message'); | $mailForm->message = $this->getProducerModule()->getSolver()->getConfig('option_communicate_email_default_message'); | ||||
if ($idPointSale && !$usersPointSaleLink && !$usersPointSaleHasOrder) { | |||||
$usersPointSaleLink = 1; | |||||
} | |||||
if ($idDistribution && !$usersPointSaleLink && !$usersPointSaleHasOrder) { | |||||
$usersPointSaleLink = 1; | |||||
} | |||||
if($idDistribution) { | |||||
$users = []; | |||||
$distribution = $distributionModule->getRepository()->findOneDistributionById($idDistribution); | |||||
if($distribution) { | |||||
$mailForm->id_distribution = $idDistribution; | |||||
foreach($distribution->pointSaleDistribution as $pointSaleDistribution) { | |||||
if($pointSaleDistribution->delivery) { | |||||
$usersPointSaleArray = $userModule->getRepository()->queryUsersBy([ | |||||
'id_producer' => $producerCurrent->id, | |||||
'id_point_sale' => $pointSaleDistribution->id_point_sale, | |||||
'users_point_sale_link' => $usersPointSaleLink, | |||||
'users_point_sale_has_order' => $usersPointSaleHasOrder, | |||||
'newsletter' => true | |||||
])->all(); | |||||
foreach($usersPointSaleArray as $user) { | |||||
$users[$user['id']] = $user; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
else { | |||||
$users = $userModule->queryUsersBy([ | |||||
'id_producer' => GlobalParam::getCurrentProducerId(), | |||||
'id_point_sale' => $idPointSale, | |||||
'users_point_sale_link' => $usersPointSaleLink, | |||||
'users_point_sale_has_order' => $usersPointSaleHasOrder, | |||||
'subscribers' => $sectionSubscribers, | |||||
'inactive' => $sectionInactiveUsers, | |||||
'newsletter' => true | |||||
])->all(); | |||||
} | |||||
$usersArray = []; | |||||
foreach ($users as $key => $user) { | |||||
if (isset($user['email']) && strlen($user['email']) > 0) { | |||||
if($this->getProducerCurrent()->isDemoAccount()) { | |||||
$usersArray[] = \Yii::$app->faker->email(); | |||||
} | |||||
else { | |||||
$usersArray[] = $user['email']; | |||||
} | |||||
} else { | |||||
unset($users[$key]); | |||||
} | |||||
} | |||||
$pointsSaleArray = PointSale::find()->where(['id_producer' => GlobalParam::getCurrentProducerId(), 'status' => 1])->all(); | |||||
$pointSale = null; | |||||
if ($idPointSale) { | |||||
$pointSale = PointSale::findOne(['id' => $idPointSale]); | |||||
$pointSale = $idPointSale ? $this->getPointSaleModule()->getRepository()->findOnePointSaleById($idPointSale) : null; | |||||
$distribution = $idDistribution ? $this->getDistributionModule()->getRepository()->findOneDistributionById($idDistribution) : null; | |||||
if($distribution) { | |||||
$mailForm->id_distribution = $distribution->id; | |||||
} | } | ||||
$usersArray = $emailModule->getContactListResolver()->search( | |||||
$this->getProducerCurrent(), | |||||
$distribution, | |||||
$pointSale, | |||||
$usersPointSaleLink, | |||||
$usersPointSaleHasOrder, | |||||
$sectionSubscribers, | |||||
$sectionInactiveUsers | |||||
); | |||||
if ($mailForm->load(\Yii::$app->request->post()) && $mailForm->validate()) { | if ($mailForm->load(\Yii::$app->request->post()) && $mailForm->validate()) { | ||||
if($this->getProducerCurrent()->isDemoAccount()) { | if($this->getProducerCurrent()->isDemoAccount()) { | ||||
$this->setFlash('error', "Fonctionnalité désactivée sur le compte de démo."); | $this->setFlash('error', "Fonctionnalité désactivée sur le compte de démo."); | ||||
} | } | ||||
else { | else { | ||||
$mailForm->sendEmail($users); | |||||
$distribution = $mailForm->id_distribution | |||||
? $this->getDistributionModule()->getRepository()->findOneDistributionById($mailForm->id_distribution) | |||||
: null; | |||||
$email = $emailModule->getGenerator()->createEmail( | |||||
$mailForm->subject, | |||||
$mailForm->message, | |||||
$mailForm->integrate_product_list, | |||||
$this->getProducerCurrent(), | |||||
$distribution | |||||
); | |||||
$emailModule->getBulkMailer()->sendEmail($email, $usersArray); | |||||
$this->setFlash('success', 'Votre email a bien été envoyé.'); | $this->setFlash('success', 'Votre email a bien été envoyé.'); | ||||
} | } | ||||
return $this->redirect(['email', 'idPointSale' => $idPointSale]); | return $this->redirect(['email', 'idPointSale' => $idPointSale]); | ||||
} | } | ||||
$incomingDistributionsArray = $distributionModule->findDistributionsIncoming(); | |||||
$pointsSaleArray = PointSale::find()->where(['id_producer' => GlobalParam::getCurrentProducerId(), 'status' => 1])->all(); | |||||
$incomingDistributionsArray = $this->getDistributionModule()->getRepository()->findDistributionsIncoming(); | |||||
$incomingDistributionsDatesArray = ['0' => '--']; | $incomingDistributionsDatesArray = ['0' => '--']; | ||||
foreach ($incomingDistributionsArray as $distribution) { | foreach ($incomingDistributionsArray as $distribution) { | ||||
$incomingDistributionsDatesArray[$distribution->id] = strftime('%A %d %B %Y', strtotime($distribution->date)); | $incomingDistributionsDatesArray[$distribution->id] = strftime('%A %d %B %Y', strtotime($distribution->date)); |
} | } | ||||
$jsonProduct['quantity_max'] = $orderModule->getResolver()->getProductQuantityMax($product, $distribution); | $jsonProduct['quantity_max'] = $orderModule->getResolver()->getProductQuantityMax($product, $distribution); | ||||
$jsonProduct['quantity_remaining'] = $orderModule->getResolver()->getProductQuantityRemaining($product, $distribution); | |||||
$jsonProduct['quantity_form'] = 0; | $jsonProduct['quantity_form'] = 0; | ||||
$jsonProduct['accessories'] = []; | |||||
foreach($product->getProductAccessories() as $productAccessory) { | |||||
$jsonProduct['accessories'][] = [ | |||||
'id_accessory' => $productAccessory->getAccessory()->getId(), | |||||
'quantity' => $productAccessory->getQuantity(), | |||||
]; | |||||
} | |||||
if ($product->taxRate) { | if ($product->taxRate) { | ||||
$jsonProduct['taxRate'] = $product->taxRate->getAttributes(); | $jsonProduct['taxRate'] = $product->taxRate->getAttributes(); | ||||
} | } | ||||
$idDistribution, | $idDistribution, | ||||
$idUser = false, | $idUser = false, | ||||
$idPointSale = false, | $idPointSale = false, | ||||
$idOrder = false | |||||
$idOrder = false, | |||||
$productOrderFormArray = [] | |||||
) | ) | ||||
{ | { | ||||
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; | \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; | ||||
$productOrderFormArray = json_decode($productOrderFormArray, true); | |||||
$distributionModule = $this-> getDistributionModule(); | $distributionModule = $this-> getDistributionModule(); | ||||
$orderModule = $this->getOrderModule(); | $orderModule = $this->getOrderModule(); | ||||
$userModule = $this->getUserModule(); | $userModule = $this->getUserModule(); | ||||
if (isset($order->productOrder)) { | if (isset($order->productOrder)) { | ||||
foreach ($order->productOrder as $productOrder) { | foreach ($order->productOrder as $productOrder) { | ||||
if ($productOrder->id_product == $product['id']) { | |||||
if ($productOrder->id_product == $product->id) { | |||||
if ($productOrder->invoice_price) { | if ($productOrder->invoice_price) { | ||||
$invoicePrice = number_format($productOrder->invoice_price, 5); | $invoicePrice = number_format($productOrder->invoice_price, 5); | ||||
} else { | } else { | ||||
} | } | ||||
} | } | ||||
$productOrderArray[$product['id']] = [ | |||||
// Quantité définie dans le formulaire | |||||
if(isset($productOrderFormArray[$product->id]['quantity'])) { | |||||
$quantity = $productOrderFormArray[$product->id]['quantity'] / $productModule->getSolver()->getUnitCoefficient($product); | |||||
} | |||||
$productOrderArray[$product->id] = [ | |||||
'quantity' => $quantity, | 'quantity' => $quantity, | ||||
'unit' => $product->unit, | 'unit' => $product->unit, | ||||
'prices' => $priceArray, | 'prices' => $priceArray, | ||||
'active' => $product->productDistribution[0]->active | 'active' => $product->productDistribution[0]->active | ||||
&& (!$pointSale || $productModule->isAvailableOnPointSale($product, $pointSale)), | && (!$pointSale || $productModule->isAvailableOnPointSale($product, $pointSale)), | ||||
'invoice_price' => $invoicePrice | |||||
'invoice_price' => $invoicePrice, | |||||
]; | ]; | ||||
} | } | ||||
// construction de $orderOverride | |||||
$orderOverride = $orderModule->getBuilder()->instanciateOrderFromProductOrdersArray($productOrderArray, $order); | |||||
foreach($productOrderArray as $idProduct => $productOrder) { | |||||
$product = $productModule->getRepository()->findOneProductById($idProduct); | |||||
$productOrderArray[$idProduct]['quantity_remaining'] = $orderModule->getResolver()->getProductQuantityRemaining($product, $distribution, $orderOverride); | |||||
} | |||||
return $productOrderArray; | return $productOrderArray; | ||||
} | } | ||||
use common\helpers\Price; | use common\helpers\Price; | ||||
use domain\Order\Order\OrderRepositoryQuery; | use domain\Order\Order\OrderRepositoryQuery; | ||||
use domain\Order\OrderStatus\OrderStatus; | use domain\Order\OrderStatus\OrderStatus; | ||||
use backend\forms\ReportPaymentsForm; | |||||
use Yii; | use Yii; | ||||
use yii\filters\AccessControl; | use yii\filters\AccessControl; | ||||
return $condition; | return $condition; | ||||
} | } | ||||
public function actionPayments(string $dateStart, string $dateEnd) | |||||
public function actionPayments() | |||||
{ | { | ||||
$orderModule = $this->getOrderModule(); | |||||
$ordersArray = $orderModule->getRepository() | |||||
->findOrdersByPeriod( | |||||
new \DateTime($dateStart), | |||||
new \DateTime($dateEnd) | |||||
); | |||||
$datas = [ | |||||
[ | |||||
'Date', | |||||
'Client', | |||||
'Montant', | |||||
'Facture', | |||||
'Crédit', | |||||
'Espèce', | |||||
'Chèque', | |||||
'Virement', | |||||
'Carte bancaire', | |||||
'Total' | |||||
] | |||||
]; | |||||
$dateStart = $dateEnd = null; | |||||
$reportPaymentsForm = new ReportPaymentsForm(); | |||||
if($reportPaymentsForm->load(Yii::$app->request->post()) && $reportPaymentsForm->validate()) { | |||||
$dateStart = date('Y-m-d', strtotime(str_replace('/', '-', $reportPaymentsForm->date_start))); | |||||
$dateEnd = date('Y-m-d', strtotime(str_replace('/', '-', $reportPaymentsForm->date_end))); | |||||
} | |||||
if($dateStart && $dateEnd) { | |||||
$orderModule = $this->getOrderModule(); | |||||
$ordersArray = $orderModule->getRepository() | |||||
->findOrdersByPeriod( | |||||
new \DateTime($dateStart), | |||||
new \DateTime($dateEnd) | |||||
); | |||||
$sumAmountTotalSpentByCredit = 0; | |||||
$sumAmountTotalSpentByMoney = 0; | |||||
$sumAmountTotalSpentByCheque = 0; | |||||
$sumAmountTotalSpentByTransfer = 0; | |||||
$sumAmountTotalSpentByCreditCard = 0; | |||||
$datas = [ | |||||
[ | |||||
'Date', | |||||
'Client', | |||||
'Montant', | |||||
'Facture', | |||||
'Crédit', | |||||
'Espèce', | |||||
'Chèque', | |||||
'Virement', | |||||
'Carte bancaire', | |||||
'Total' | |||||
] | |||||
]; | |||||
foreach($ordersArray as $order) { | |||||
$orderModule->getBuilder()->initOrder($order); | |||||
$sumAmountTotalSpentByCredit = 0; | |||||
$sumAmountTotalSpentByMoney = 0; | |||||
$sumAmountTotalSpentByCheque = 0; | |||||
$sumAmountTotalSpentByTransfer = 0; | |||||
$sumAmountTotalSpentByCreditCard = 0; | |||||
$hasInvoice = false; | |||||
$referenceInvoice = 'Non'; | |||||
if($order->invoice) { | |||||
$hasInvoice = true; | |||||
$referenceInvoice = $order->invoice->reference.""; | |||||
} | |||||
foreach($ordersArray as $order) { | |||||
$orderModule->getBuilder()->initOrder($order); | |||||
$hasInvoice = false; | |||||
$referenceInvoice = 'Non'; | |||||
if($order->invoice) { | |||||
$hasInvoice = true; | |||||
$referenceInvoice = $order->invoice->reference.""; | |||||
} | |||||
$amountTotalSpentByCredit = $orderModule->getSolver()->getAmountTotalSpentByMeanPayment($order, MeanPayment::CREDIT); | |||||
$sumAmountTotalSpentByCredit += $amountTotalSpentByCredit; | |||||
$amountTotalSpentByMoney = $orderModule->getSolver()->getAmountTotalSpentByMeanPayment($order, MeanPayment::MONEY); | |||||
$sumAmountTotalSpentByMoney += $amountTotalSpentByMoney; | |||||
$amountTotalSpentByCheque = $orderModule->getSolver()->getAmountTotalSpentByMeanPayment($order, MeanPayment::CHEQUE); | |||||
$sumAmountTotalSpentByCheque += $amountTotalSpentByCheque; | |||||
$amountTotalSpentByTransfer = $orderModule->getSolver()->getAmountTotalSpentByMeanPayment($order, MeanPayment::TRANSFER); | |||||
$sumAmountTotalSpentByTransfer += $amountTotalSpentByTransfer; | |||||
$amountTotalSpentByCreditCard = $orderModule->getSolver()->getAmountTotalSpentByMeanPayment($order, MeanPayment::CREDIT_CARD); | |||||
$sumAmountTotalSpentByCreditCard += $amountTotalSpentByCreditCard; | |||||
$amountTotalSpentByCredit = $orderModule->getSolver()->getAmountTotalSpentByMeanPayment($order, MeanPayment::CREDIT); | |||||
$sumAmountTotalSpentByCredit += $amountTotalSpentByCredit; | |||||
$amountTotalSpentByMoney = $orderModule->getSolver()->getAmountTotalSpentByMeanPayment($order, MeanPayment::MONEY); | |||||
$sumAmountTotalSpentByMoney += $amountTotalSpentByMoney; | |||||
$amountTotalSpentByCheque = $orderModule->getSolver()->getAmountTotalSpentByMeanPayment($order, MeanPayment::CHEQUE); | |||||
$sumAmountTotalSpentByCheque += $amountTotalSpentByCheque; | |||||
$amountTotalSpentByTransfer = $orderModule->getSolver()->getAmountTotalSpentByMeanPayment($order, MeanPayment::TRANSFER); | |||||
$sumAmountTotalSpentByTransfer += $amountTotalSpentByTransfer; | |||||
$amountTotalSpentByCreditCard = $orderModule->getSolver()->getAmountTotalSpentByMeanPayment($order, MeanPayment::CREDIT_CARD); | |||||
$sumAmountTotalSpentByCreditCard += $amountTotalSpentByCreditCard; | |||||
$datas[] = [ | |||||
$order->distribution->date, | |||||
$orderModule->getSolver()->getOrderUsername($order), | |||||
CSV::formatNumber($orderModule->getSolver()->getOrderAmountWithTax($order)), | |||||
$referenceInvoice, | |||||
$hasInvoice ? '' : CSV::formatNumber($amountTotalSpentByCredit), | |||||
$hasInvoice ? '' : CSV::formatNumber($amountTotalSpentByMoney), | |||||
$hasInvoice ? '' : CSV::formatNumber($amountTotalSpentByCheque), | |||||
$hasInvoice ? '' : CSV::formatNumber($amountTotalSpentByTransfer), | |||||
$hasInvoice ? '' : CSV::formatNumber($amountTotalSpentByCreditCard) | |||||
]; | |||||
} | |||||
$datas[] = [ | $datas[] = [ | ||||
$order->distribution->date, | |||||
$orderModule->getSolver()->getOrderUsername($order), | |||||
CSV::formatNumber($orderModule->getSolver()->getOrderAmountWithTax($order)), | |||||
$referenceInvoice, | |||||
$hasInvoice ? '' : CSV::formatNumber($amountTotalSpentByCredit), | |||||
$hasInvoice ? '' : CSV::formatNumber($amountTotalSpentByMoney), | |||||
$hasInvoice ? '' : CSV::formatNumber($amountTotalSpentByCheque), | |||||
$hasInvoice ? '' : CSV::formatNumber($amountTotalSpentByTransfer), | |||||
$hasInvoice ? '' : CSV::formatNumber($amountTotalSpentByCreditCard) | |||||
'', | |||||
'', | |||||
'', | |||||
'Totaux paiements', | |||||
CSV::formatNumber($sumAmountTotalSpentByCredit), | |||||
CSV::formatNumber($sumAmountTotalSpentByMoney), | |||||
CSV::formatNumber($sumAmountTotalSpentByCheque), | |||||
CSV::formatNumber($sumAmountTotalSpentByTransfer), | |||||
CSV::formatNumber($sumAmountTotalSpentByCreditCard), | |||||
CSV::formatNumber($sumAmountTotalSpentByCredit + $sumAmountTotalSpentByMoney + $sumAmountTotalSpentByCheque + | |||||
$sumAmountTotalSpentByTransfer + $sumAmountTotalSpentByCreditCard) | |||||
]; | ]; | ||||
} | |||||
$datas[] = [ | |||||
'', | |||||
'', | |||||
'', | |||||
'Totaux paiements', | |||||
CSV::formatNumber($sumAmountTotalSpentByCredit), | |||||
CSV::formatNumber($sumAmountTotalSpentByMoney), | |||||
CSV::formatNumber($sumAmountTotalSpentByCheque), | |||||
CSV::formatNumber($sumAmountTotalSpentByTransfer), | |||||
CSV::formatNumber($sumAmountTotalSpentByCreditCard), | |||||
CSV::formatNumber($sumAmountTotalSpentByCredit + $sumAmountTotalSpentByMoney + $sumAmountTotalSpentByCheque + | |||||
$sumAmountTotalSpentByTransfer + $sumAmountTotalSpentByCreditCard) | |||||
]; | |||||
CSV::send('commandes.csv', $datas); | |||||
} | |||||
CSV::send('commandes.csv', $datas); | |||||
return $this->render('payments', [ | |||||
'reportPaymentsForm' => $reportPaymentsForm | |||||
]); | |||||
} | } | ||||
} | } |
); | ); | ||||
$userCreate->points_sale = $model->points_sale; | $userCreate->points_sale = $model->points_sale; | ||||
$userCreate->user_groups = $model->user_groups; | $userCreate->user_groups = $model->user_groups; | ||||
$userCreate->exclusive_access_selected_points_sale = $model->exclusive_access_selected_points_sale; | |||||
$this->processLinkPointSale($userCreate); | $this->processLinkPointSale($userCreate); | ||||
$this->processLinkUserGroup($userCreate); | $this->processLinkUserGroup($userCreate); | ||||
$model->newsletter = $userBelongToProducer->newsletter; | $model->newsletter = $userBelongToProducer->newsletter; | ||||
$model->trust_alert = $userBelongToProducer->trust_alert; | $model->trust_alert = $userBelongToProducer->trust_alert; | ||||
$model->trust_alert_comment = $userBelongToProducer->trust_alert_comment; | $model->trust_alert_comment = $userBelongToProducer->trust_alert_comment; | ||||
$model->exclusive_access_selected_points_sale = $userBelongToProducer->exclusive_access_selected_points_sale; | |||||
if ($model->load(\Yii::$app->request->post()) && $model->save()) { | if ($model->load(\Yii::$app->request->post()) && $model->save()) { | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// Accès exclusif aux points de vente sélectionnés | |||||
$userProducer = UserProducer::findOne(['id_user' => $modelUser->id, 'id_producer' => GlobalParam::getCurrentProducerId()]); | |||||
$userProducer->setExclusiveAccessSelectedPointsSale($modelUser->exclusive_access_selected_points_sale); | |||||
$userProducer->save(); | |||||
} | } | ||||
/** | /** |
<?php | |||||
namespace backend\forms; | |||||
use yii\base\Model; | |||||
/** | |||||
* UploadForm is the model behind the upload form. | |||||
*/ | |||||
class ReportPaymentsForm extends Model | |||||
{ | |||||
var $date_start; | |||||
var $date_end; | |||||
/** | |||||
* @return array the validation rules. | |||||
*/ | |||||
public function rules() | |||||
{ | |||||
return [ | |||||
[['date_start', 'date_end'], 'required'], | |||||
[['date_start', 'date_end'], 'safe'], | |||||
]; | |||||
} | |||||
public function attributeLabels() | |||||
{ | |||||
return [ | |||||
'date_start' => "Date de début", | |||||
'date_end' => "Date de fin" | |||||
]; | |||||
} | |||||
} | |||||
?> |
namespace backend\models; | namespace backend\models; | ||||
use common\helpers\GlobalParam; | use common\helpers\GlobalParam; | ||||
use common\helpers\Mailjet; | |||||
use common\helpers\Price; | |||||
use domain\Config\Unit\UnitDefinition; | |||||
use domain\Distribution\Distribution\Distribution; | |||||
use domain\Communication\Email\EmailGenerator; | |||||
use domain\Distribution\Distribution\DistributionModule; | use domain\Distribution\Distribution\DistributionModule; | ||||
use domain\Producer\Producer\ProducerModule; | |||||
use domain\Product\Product\Product; | |||||
use domain\Product\Product\ProductModule; | |||||
use GuzzleHttp\Client; | |||||
use GuzzleHttp\Psr7\Response; | |||||
use Psr\Http\Message\ResponseInterface; | |||||
use Yii; | use Yii; | ||||
use yii\base\Model; | use yii\base\Model; | ||||
use yii\helpers\Html; | |||||
/** | /** | ||||
* ContactForm is the model behind the contact form. | * ContactForm is the model behind the contact form. | ||||
public $id_distribution ; | public $id_distribution ; | ||||
public $subject; | public $subject; | ||||
public $message; | public $message; | ||||
public $integrate_product_list = false; | |||||
public $integrate_product_list; | |||||
/** | /** | ||||
* @inheritdoc | * @inheritdoc | ||||
'integrate_product_list' => 'Intégrer la liste des produits au message' | 'integrate_product_list' => 'Intégrer la liste des produits au message' | ||||
]; | ]; | ||||
} | } | ||||
public function sendEmail($contactsArray, $fromProducer = true) | |||||
{ | |||||
$productModule = ProductModule::getInstance(); | |||||
$producerModule = ProducerModule::getInstance(); | |||||
$distributionModule = DistributionModule::getInstance(); | |||||
$messageAutoText = '' ; | |||||
$messageAutoHtml = '' ; | |||||
$messageAutoHtml .= ' <style type="text/css"> | |||||
h1, h2, h3, h4, h5, h6 { | |||||
padding: 0px; | |||||
margin: 0px; | |||||
margin-bottom: 10px; | |||||
} | |||||
p { | |||||
margin: 0px; | |||||
padding: 0px; | |||||
margin-bottom: 5px; | |||||
} | |||||
</style>'; | |||||
if($this->id_distribution) { | |||||
$messageAutoText = ' | |||||
' ; | |||||
$messageAutoHtml .= '<br /><br />' ; | |||||
$distribution = Distribution::searchOne(['id' => $this->id_distribution]) ; | |||||
if($distribution) { | |||||
$linkOrder = $distributionModule->getLinkOrder($distribution); | |||||
$dateOrder = strftime('%A %d %B %Y', strtotime($distribution->date)) ; | |||||
$messageAutoHtml .= '<a href="'.$linkOrder.'">Passer ma commande du '.$dateOrder.'</a>' ; | |||||
$messageAutoText .= 'Suivez ce lien pour passer votre commande du '.$dateOrder.' : | |||||
'.$linkOrder ; | |||||
if($this->integrate_product_list) { | |||||
$productsArray = Product::find() | |||||
->where([ | |||||
'id_producer' => GlobalParam::getCurrentProducerId(), | |||||
]) | |||||
->andWhere('status >= :status') | |||||
->addParams(['status' => Product::STATUS_OFFLINE]) | |||||
->innerJoinWith(['productDistribution' => function($query) use($distribution) { | |||||
$query->andOnCondition([ | |||||
'product_distribution.id_distribution' => $distribution->id, | |||||
'product_distribution.active' => 1 | |||||
]); | |||||
}]) | |||||
->orderBy('product.name ASC') | |||||
->all(); | |||||
if(count($productsArray) > 1) { | |||||
$messageAutoHtml .= '<br /><br />Produits disponibles : <br /><ul>' ; | |||||
$messageAutoText .= ' | |||||
Produits disponibles : | |||||
' ; | |||||
foreach($productsArray as $product) { | |||||
$productDescription = $product->name ; | |||||
if(strlen($product->description)) { | |||||
$productDescription .= ' / '.$product->description ; | |||||
} | |||||
if($product->price) { | |||||
$productDescription .= ' / '.Price::format($productModule->getPriceWithTax($product)) ; | |||||
$productDescription .= ' ('. $productModule->getSolver()->strUnit($product, UnitDefinition::WORDING_UNIT).')' ; | |||||
} | |||||
$messageAutoText .= '- '.$productDescription.' | |||||
' ; | |||||
$messageAutoHtml .= '<li>'.Html::encode($productDescription).'</li>' ; | |||||
} | |||||
$messageAutoHtml .= '</ul>' ; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
if($fromProducer) { | |||||
$producer = GlobalParam::getCurrentProducer() ; | |||||
$fromEmail = $producerModule->getProducerEmailPlatform($producer) ; | |||||
$fromName = $producer->name ; | |||||
$linkProducer = 'https://'.$producer->slug.'.souke.fr'; | |||||
$linkUnsubscribe = Yii::$app->urlManagerProducer->createAbsoluteUrl(['newsletter/unsubscribe', 'slug_producer' => $producer->slug]); | |||||
// Message inscription newsletter | |||||
$messageAutoText .= " | |||||
-- | |||||
Boutique : ".$linkProducer." | |||||
Me désinscrire : ".$linkUnsubscribe; | |||||
$messageAutoHtml .= "<br /><br />--<br>"; | |||||
$messageAutoHtml .= "Boutique : <a href=\"".$linkProducer."\">".$linkProducer."</a><br>"; | |||||
$messageAutoHtml .= "Me désinscrire : <a href=\"".$linkUnsubscribe."\">".$linkUnsubscribe."</a>"; | |||||
} | |||||
else { | |||||
$fromEmail = 'contact@souke.fr' ; | |||||
$fromName = 'Souke' ; | |||||
} | |||||
$subject = $this->subject; | |||||
$htmlContent = nl2br($this->message).$messageAutoHtml; | |||||
$textContent = $this->message.$messageAutoText; | |||||
Yii::$app->bulkMailer->sendEmails($contactsArray, $fromName, $fromEmail, $subject, $htmlContent, $textContent); | |||||
} | |||||
/* | |||||
public function sendEmailMailjet($usersArray, $fromProducer = true) | |||||
{ | |||||
$productModule = ProductModule::getInstance(); | |||||
$producerModule = ProducerModule::getInstance(); | |||||
$distributionModule = DistributionModule::getInstance(); | |||||
$mj = new \Mailjet\Client( | |||||
Mailjet::getApiKey('public'), | |||||
Mailjet::getApiKey('private'), | |||||
true, | |||||
['version' => 'v3.1'] | |||||
); | |||||
$messageAutoText = '' ; | |||||
$messageAutoHtml = '' ; | |||||
$messageAutoHtml .= ' <style type="text/css"> | |||||
h1, h2, h3, h4, h5, h6 { | |||||
padding: 0px; | |||||
margin: 0px; | |||||
margin-bottom: 10px; | |||||
} | |||||
p { | |||||
margin: 0px; | |||||
padding: 0px; | |||||
margin-bottom: 5px; | |||||
} | |||||
</style>'; | |||||
if($this->id_distribution) { | |||||
$messageAutoText = ' | |||||
' ; | |||||
$messageAutoHtml .= '<br /><br />' ; | |||||
$distribution = Distribution::searchOne(['id' => $this->id_distribution]) ; | |||||
if($distribution) { | |||||
$linkOrder = $distributionModule->getLinkOrder($distribution); | |||||
$dateOrder = strftime('%A %d %B %Y', strtotime($distribution->date)) ; | |||||
$messageAutoHtml .= '<a href="'.$linkOrder.'">Passer ma commande du '.$dateOrder.'</a>' ; | |||||
$messageAutoText .= 'Suivez ce lien pour passer votre commande du '.$dateOrder.' : | |||||
'.$linkOrder ; | |||||
if($this->integrate_product_list) { | |||||
$productsArray = Product::find() | |||||
->where([ | |||||
'id_producer' => GlobalParam::getCurrentProducerId(), | |||||
]) | |||||
->andWhere('status >= :status') | |||||
->addParams(['status' => Product::STATUS_OFFLINE]) | |||||
->innerJoinWith(['productDistribution' => function($query) use($distribution) { | |||||
$query->andOnCondition([ | |||||
'product_distribution.id_distribution' => $distribution->id, | |||||
'product_distribution.active' => 1 | |||||
]); | |||||
}]) | |||||
->orderBy('product.name ASC') | |||||
->all(); | |||||
if(count($productsArray) > 1) { | |||||
$messageAutoHtml .= '<br /><br />Produits disponibles : <br /><ul>' ; | |||||
$messageAutoText .= ' | |||||
Produits disponibles : | |||||
' ; | |||||
foreach($productsArray as $product) { | |||||
$productDescription = $product->name ; | |||||
if(strlen($product->description)) { | |||||
$productDescription .= ' / '.$product->description ; | |||||
} | |||||
if($product->price) { | |||||
$productDescription .= ' / '.Price::format($productModule->getPriceWithTax($product)) ; | |||||
$productDescription .= ' ('. $productModule->getSolver()->strUnit($product, UnitDefinition::WORDING_UNIT).')' ; | |||||
} | |||||
$messageAutoText .= '- '.$productDescription.' | |||||
' ; | |||||
$messageAutoHtml .= '<li>'.Html::encode($productDescription).'</li>' ; | |||||
} | |||||
$messageAutoHtml .= '</ul>' ; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
if($fromProducer) { | |||||
$producer = GlobalParam::getCurrentProducer() ; | |||||
$fromEmail = $producerModule->getProducerEmailPlatform($producer) ; | |||||
$fromName = $producer->name ; | |||||
$linkProducer = 'https://'.$producer->slug.'.souke.fr'; | |||||
$linkUnsubscribe = Yii::$app->urlManagerProducer->createAbsoluteUrl(['newsletter/unsubscribe', 'slug_producer' => $producer->slug]); | |||||
// Message inscription newsletter | |||||
$messageAutoText .= " | |||||
-- | |||||
Boutique : ".$linkProducer." | |||||
Me désinscrire : ".$linkUnsubscribe; | |||||
$messageAutoHtml .= "<br /><br />--<br>"; | |||||
$messageAutoHtml .= "Boutique : <a href=\"".$linkProducer."\">".$linkProducer."</a><br>"; | |||||
$messageAutoHtml .= "Me désinscrire : <a href=\"".$linkUnsubscribe."\">".$linkUnsubscribe."</a>"; | |||||
} | |||||
else { | |||||
$fromEmail = 'contact@souke.fr' ; | |||||
$fromName = 'Souke' ; | |||||
} | |||||
$body = ['Messages' => []] ; | |||||
foreach($usersArray as $user) { | |||||
$body['Messages'][] = [ | |||||
'From' => [ | |||||
'Email' => $fromEmail, | |||||
'Name' => $fromName | |||||
], | |||||
'To' => [ | |||||
[ | |||||
'Email' => $user['email'], | |||||
'Name' => $user['name'].' '.$user['lastname'] | |||||
] | |||||
], | |||||
'Subject' => $this->subject, | |||||
'TextPart' => $this->message.$messageAutoText, | |||||
'HTMLPart' => nl2br($this->message).$messageAutoHtml | |||||
] ; | |||||
if(count($body['Messages']) == 50) { | |||||
$response = $mj->post(\Mailjet\Resources::$Email, ['body' => $body]); | |||||
$body['Messages'] = [] ; | |||||
} | |||||
} | |||||
if(count($body['Messages']) > 0) { | |||||
$response = $mj->post(\Mailjet\Resources::$Email, ['body' => $body]); | |||||
} | |||||
$success = (isset($response) && $response) ? $response->success() : false ; | |||||
if(!$success) { | |||||
Yii::error($response->getBody(), 'Mailjet'); | |||||
} | |||||
return $response ; | |||||
} | |||||
*/ | |||||
} | } |
<?php | |||||
/** | |||||
* Copyright Souke (2018) | |||||
* | |||||
* contact@souke.fr | |||||
* | |||||
* 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\components\Date; | |||||
use common\helpers\Dropdown; | |||||
use lo\widgets\Toggle; | |||||
use yii\widgets\ActiveForm; | |||||
?> | |||||
<div class="automatic-email-form"> | |||||
<?php $form = ActiveForm::begin(); ?> | |||||
<div class="col-md-8"> | |||||
<div class="panel panel-default"> | |||||
<div class="panel-heading"> | |||||
<h3 class="panel-title"> | |||||
<i class="fa fa-th-list"></i> | |||||
Général | |||||
</h3> | |||||
</div> | |||||
<div class="panel-body"> | |||||
<?= $form->field($automaticEmail, 'status')->widget(Toggle::class, | |||||
[ | |||||
'options' => [ | |||||
'data-id' => $automaticEmail->id, | |||||
'data-on' => 'Activé', | |||||
'data-off' => 'Désactivé' | |||||
], | |||||
]); | |||||
?> | |||||
<?= $form->field($automaticEmail, 'day')->dropDownList(Date::getDaysOfWeekArray()) ?> | |||||
<?= $form->field($automaticEmail, 'delay_before_distribution')->dropDownList(Dropdown::numberChoices(1, 7, false, ' jour(s) avant')); ?> | |||||
<?= $form->field($automaticEmail, 'subject')->textInput() ?> | |||||
<?= $form->field($automaticEmail, 'message')->widget(letyii\tinymce\Tinymce::class, [ | |||||
'configs' => [ | |||||
'plugins' => Yii::$app->parameterBag->get('tinyMcePlugins'), | |||||
] | |||||
]); ?> | |||||
<?= $form->field($automaticEmail, 'integrate_product_list')->widget(Toggle::class, | |||||
[ | |||||
'options' => [ | |||||
'data-id' => $automaticEmail->id, | |||||
'data-on' => 'Oui', | |||||
'data-off' => 'Non', | |||||
'data-offstyle' => 'default', | |||||
], | |||||
]); | |||||
?> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<?= $this->render('@backend/views/_include/form_actions.php',[ | |||||
'model' => $automaticEmail, | |||||
]); ?> | |||||
<?php ActiveForm::end(); ?> | |||||
</div> |
termes. | termes. | ||||
*/ | */ | ||||
$this->setTitle('Passer une commande') ; | |||||
$this->setTitle("Ajouter un email automatique") ; | |||||
$this->addBreadcrumb(['label' => "Emails automatiques", 'url' => ['index']]) ; | |||||
$this->addBreadcrumb('Ajouter') ; | |||||
?> | ?> | ||||
<div class="order-create"> | |||||
<div class="automatic-email-create"> | |||||
<?= $this->render('_form', [ | <?= $this->render('_form', [ | ||||
'model' => $model, | |||||
'pointsSaleArray' => $pointsSaleArray, | |||||
'distributionDaysArray' => $distributionDaysArray, | |||||
'productsArray' => $productsArray, | |||||
'selectedProducts' => $selectedProducts, | |||||
'availableProducts' => $availableProducts, | |||||
'distribution' => $distribution, | |||||
'ordersArray' => $ordersArray, | |||||
'producersArray' => $producersArray, | |||||
'idProducer' => $idProducer, | |||||
'producer' => $producer, | |||||
'credit' => $credit | |||||
'automaticEmail' => $automaticEmail, | |||||
]) ?> | ]) ?> | ||||
</div> | </div> |
<?php | |||||
/** | |||||
* Copyright Souke (2018) | |||||
* | |||||
* contact@souke.fr | |||||
* | |||||
* 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\components\View; | |||||
use domain\Communication\AutomaticEmail\AutomaticEmail; | |||||
use yii\helpers\Html; | |||||
use yii\grid\GridView; | |||||
/** | |||||
* @var View $this | |||||
*/ | |||||
$this->setTitle('Emails automatiques'); | |||||
$this->addBreadcrumb($this->getTitle()); | |||||
$this->addButton(['label' => 'Nouvel email automatique <span class="glyphicon glyphicon-plus"></span>', 'url' => 'automatic-email/create', 'class' => 'btn btn-primary']); | |||||
?> | |||||
<div class="accessory-index"> | |||||
<?= GridView::widget([ | |||||
'dataProvider' => $dataProvider, | |||||
'columns' => [ | |||||
[ | |||||
'attribute' => 'day', | |||||
'value' => function(AutomaticEmail $automaticEmail) { | |||||
return $automaticEmail->getDayAsString(); | |||||
} | |||||
], | |||||
[ | |||||
'attribute' => 'delay_before_distribution', | |||||
'value' => function(AutomaticEmail $automaticEmail) { | |||||
return $automaticEmail->getDelayBeforeDistributionAsString(); | |||||
} | |||||
], | |||||
'subject', | |||||
[ | |||||
'attribute' => 'message', | |||||
'format' => 'raw', | |||||
], | |||||
[ | |||||
'attribute' => 'status', | |||||
'format' => 'raw', | |||||
'value' => function(AutomaticEmail $automaticEmail) { | |||||
return $automaticEmail->getStatusAsHtml(); | |||||
} | |||||
], | |||||
[ | |||||
'class' => 'yii\grid\ActionColumn', | |||||
'template' => '{update} {delete}', | |||||
'headerOptions' => ['class' => 'column-actions'], | |||||
'contentOptions' => ['class' => 'column-actions'], | |||||
'buttons' => [ | |||||
'update' => function ($url, $model) { | |||||
return Html::a('<span class="glyphicon glyphicon-pencil"></span>', $url, [ | |||||
'title' => 'Modifier', 'class' => 'btn btn-default' | |||||
]); | |||||
}, | |||||
'delete' => function ($url, $model) { | |||||
return Html::a('<span class="glyphicon glyphicon-trash"></span>', $url, [ | |||||
'title' => 'Supprimer', 'class' => 'btn btn-default' | |||||
]); | |||||
} | |||||
], | |||||
], | |||||
], | |||||
]); ?> | |||||
</div> |
termes. | termes. | ||||
*/ | */ | ||||
$this->setTitle('Modifier une commande') ; | |||||
use yii\helpers\Html; | |||||
$this->setTitle("Modifier un email automatique") ; | |||||
$this->addBreadcrumb(['label' => "Emails automatiques", 'url' => ['index']]) ; | |||||
$this->addBreadcrumb(['label' => Html::encode($automaticEmail->getSubject()), 'url' => ['update', 'id' => $automaticEmail->getId()]]) ; | |||||
$this->addBreadcrumb('Modifier') ; | |||||
?> | ?> | ||||
<div class="order-update"> | |||||
<?php if($orderNotfound): ?> | |||||
<div class="alert alert-danger">Cette commande est introuvable</div><br /> | |||||
<a class="btn btn-default" href="<?php echo \Yii::$app->urlManager->createUrl(['order/index']); ?>">Retour</a> | |||||
<?php else: ?> | |||||
<?= $this->render('_form', [ | |||||
'model' => $model, | |||||
'pointsSaleArray' => $pointsSaleArray, | |||||
'distributionDaysArray' => $distributionDaysArray, | |||||
'productsArray' => $productsArray, | |||||
'selectedProducts' => $selectedProducts, | |||||
'availableProducts' => $availableProducts, | |||||
'distribution' => $distribution, | |||||
'ordersArray' => $ordersArray, | |||||
'producersArray' => $producersArray, | |||||
'idProducer' => $idProducer, | |||||
'producer' => $producer, | |||||
'credit' => $credit | |||||
]) ?> | |||||
<?php endif; ?> | |||||
<div class="automatic-email-update"> | |||||
<?= $this->render('_form', [ | |||||
'automaticEmail' => $automaticEmail, | |||||
]) ?> | |||||
</div> | </div> |
use yii\widgets\ActiveForm; | use yii\widgets\ActiveForm; | ||||
$this->setTitle('Envoyer un email') ; | $this->setTitle('Envoyer un email') ; | ||||
$this->addBreadcrumb(['label' => 'Communiquer', 'url' => ['user/index']]) ; | |||||
$this->addBreadcrumb(['label' => 'Communication', 'url' => ['user/index']]) ; | |||||
$this->addBreadcrumb($this->getTitle()) ; | $this->addBreadcrumb($this->getTitle()) ; | ||||
?> | ?> |
<br /><br /> | <br /><br /> | ||||
<?php endif; ?> | <?php endif; ?> | ||||
<?= implode(', ', $usersArray); ?> | |||||
<?= implode(', ', array_map(function($user) { | |||||
return $user['email']; | |||||
}, $usersArray)); ?> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> |
use yii\helpers\Html ; | use yii\helpers\Html ; | ||||
$this->setTitle('Communiquer par papier') ; | |||||
$this->addBreadcrumb('Communiquer') ; | |||||
$this->setTitle('Communication par papier') ; | |||||
$this->addBreadcrumb('Communication') ; | |||||
?> | ?> | ||||
) ?> | ) ?> | ||||
</div> | </div> | ||||
<div class="col-lg-6 col-xs-6"> | <div class="col-lg-6 col-xs-6"> | ||||
<?php | |||||
$colorBoxTicket = 'blue'; | |||||
if($countTicketsAdminOpen == 0) { | |||||
$colorBoxTicket = 'green'; | |||||
} | |||||
elseif($countTicketsAdminUnread == 0) { | |||||
$colorBoxTicket = 'blue'; | |||||
} | |||||
elseif($countTicketsAdminUnread > 0) { | |||||
$colorBoxTicket = 'red'; | |||||
} | |||||
?> | |||||
<?= AdminLTE::smallBox( | <?= AdminLTE::smallBox( | ||||
$countTicketsAdminOpen, | $countTicketsAdminOpen, | ||||
'Tickets', | 'Tickets', | ||||
$countTicketsAdminUnread ? 'red' : 'blue', | |||||
$colorBoxTicket, | |||||
'comments', | 'comments', | ||||
Yii::$app->urlManager->createUrl('support-admin/index') | Yii::$app->urlManager->createUrl('support-admin/index') | ||||
) ?> | ) ?> |
*/ | */ | ||||
use domain\Distribution\Distribution\DistributionModule; | use domain\Distribution\Distribution\DistributionModule; | ||||
use domain\Feature\Feature\Feature; | |||||
use domain\Feature\Feature\FeatureModule; | |||||
use domain\Order\Order\Order; | use domain\Order\Order\Order; | ||||
use domain\Order\Order\OrderModule; | use domain\Order\Order\OrderModule; | ||||
use domain\Producer\Producer\ProducerModule; | use domain\Producer\Producer\ProducerModule; | ||||
$producerModule = ProducerModule::getInstance(); | $producerModule = ProducerModule::getInstance(); | ||||
$settingModule = SettingModule::getInstance(); | $settingModule = SettingModule::getInstance(); | ||||
$adminSettingBag = $settingModule->getAdminSettingBag(); | $adminSettingBag = $settingModule->getAdminSettingBag(); | ||||
$featureChecker = FeatureModule::getInstance()->getChecker(); | |||||
$this->setTitle('Tableau de bord'); | $this->setTitle('Tableau de bord'); | ||||
?> | ?> | ||||
<div class="dashboard-index"> | <div class="dashboard-index"> | ||||
<div <?php if($adminSettingBag->get('forumFlarumUrl')): ?>class="col-md-8"<?php endif; ?>> | |||||
<div <?php if($featureChecker->isEnabled(Feature::ALIAS_FORUM)): ?>class="col-md-8"<?php endif; ?>> | |||||
<?php if(Yii::$app->request->get('error_products_points_sale')): ?> | <?php if(Yii::$app->request->get('error_products_points_sale')): ?> | ||||
<div class="alert alert-warning"> | <div class="alert alert-warning"> | ||||
Vous devez ajouter <?php if(!$productsCount): ?> des produits<?php endif; ?> | Vous devez ajouter <?php if(!$productsCount): ?> des produits<?php endif; ?> | ||||
<?php endif; ?> | <?php endif; ?> | ||||
</div> | </div> | ||||
<?php if($adminSettingBag->get('forumFlarumUrl')): ?> | |||||
<?php if($featureChecker->isEnabled(Feature::ALIAS_FORUM)): ?> | |||||
<div class="col-md-4"> | <div class="col-md-4"> | ||||
<div class="panel panel-default"> | <div class="panel panel-default"> | ||||
<div class="panel-heading"> | <div class="panel-heading"> | ||||
</h3> | </h3> | ||||
</div> | </div> | ||||
<div class="panel-body"> | <div class="panel-body"> | ||||
<?php //echo print_r($forumDiscussionsArray); ?> | |||||
<?php if($forumDiscussionsArray && count($forumDiscussionsArray['data'])): ?> | <?php if($forumDiscussionsArray && count($forumDiscussionsArray['data'])): ?> | ||||
<table class="table"> | <table class="table"> | ||||
<?php $forumDiscussionsLimitedArray = array_slice($forumDiscussionsArray['data'], 0, min(3, count($forumDiscussionsArray['data']))); ?> | <?php $forumDiscussionsLimitedArray = array_slice($forumDiscussionsArray['data'], 0, min(3, count($forumDiscussionsArray['data']))); ?> | ||||
<?php foreach($forumDiscussionsLimitedArray as $forumDiscussion): ?> | <?php foreach($forumDiscussionsLimitedArray as $forumDiscussion): ?> | ||||
<tr> | <tr> | ||||
<?php //echo print_r($forumDiscussion); ?> | |||||
<td><?= $forumDiscussion['attributes']['title']; ?></td> | <td><?= $forumDiscussion['attributes']['title']; ?></td> | ||||
<td><?= date('d/m à H:i', strtotime($forumDiscussion['attributes']['lastPostedAt'])); ?></td> | <td><?= date('d/m à H:i', strtotime($forumDiscussion['attributes']['lastPostedAt'])); ?></td> | ||||
</tr> | </tr> | ||||
<p>Aucun sujet sur le forum.</p> | <p>Aucun sujet sur le forum.</p> | ||||
<?php endif; ?> | <?php endif; ?> | ||||
<p> | <p> | ||||
<a href="<?= $settingModule->getAdminSettingBag()->get('forumFlarumUrl'); ?>" class="btn btn-default"> | |||||
<a href="<?= $settingModule->getAdminSettingBag()->get('forumFlarumUrl'); ?>" class="btn btn-default" target="_blank"> | |||||
<span class="fa fa-comments"></span> | <span class="fa fa-comments"></span> | ||||
Consulter le forum | Consulter le forum | ||||
</a> | </a> |
<td>Actif</td> | <td>Actif</td> | ||||
<td>Nom</td> | <td>Nom</td> | ||||
<td class="quantity-ordered">Commandé</td> | <td class="quantity-ordered">Commandé</td> | ||||
<td class="quantity-remaining">Reste</td> | |||||
<td class="quantity-max">Maximum</td> | <td class="quantity-max">Maximum</td> | ||||
</tr> | </tr> | ||||
</thead> | </thead> | ||||
</td> | </td> | ||||
<td>{{ product.name }}</td> | <td>{{ product.name }}</td> | ||||
<td class="quantity-ordered"> | <td class="quantity-ordered"> | ||||
<span v-if="isProductMaximumQuantityExceeded(product)" class="glyphicon glyphicon-alert"></span> | |||||
{{ product.quantity_ordered ? product.quantity_ordered + ' '+ ((product.unit == 'piece') ? ' p.' : ' '+(product.unit == 'g' || product.unit == 'kg') ? 'kg' : 'litre(s)') : '∅' }} | {{ product.quantity_ordered ? product.quantity_ordered + ' '+ ((product.unit == 'piece') ? ' p.' : ' '+(product.unit == 'g' || product.unit == 'kg') ? 'kg' : 'litre(s)') : '∅' }} | ||||
</td> | </td> | ||||
<td class="quantity-remaining"> | |||||
<span class="infinite" v-if="(getProductQuantityRemainingGlobal(product) === null)">∞</span> | |||||
<span class="negative" v-else-if="getProductQuantityRemainingGlobal(product) <= 0"> | |||||
{{ getProductQuantityRemainingGlobal(product) }} {{ product.unit == 'piece' ? ' p.' : ' '+(product.unit == 'g' || product.unit == 'kg') ? 'kg' : 'litre(s)' }} | |||||
<span class="glyphicon glyphicon-alert" v-if="getProductQuantityRemainingGlobal(product) < 0"></span> | |||||
</span> | |||||
<span class="has-quantity" v-else>{{ getProductQuantityRemainingGlobal(product) }} {{ product.unit == 'piece' ? ' p.' : ' '+(product.unit == 'g' || product.unit == 'kg') ? 'kg' : 'litre(s)' }}</span> | |||||
</td> | |||||
<td class="quantity-max"> | <td class="quantity-max"> | ||||
<div class="input-group"> | <div class="input-group"> | ||||
<input type="text" class="form-control quantity-max" placeholder="∞" :data-id-product="product.id" v-model="getProductDistribution(product).quantity_max" @keyup="productQuantityMaxChange" /> | <input type="text" class="form-control quantity-max" placeholder="∞" :data-id-product="product.id" v-model="getProductDistribution(product).quantity_max" @keyup="productQuantityMaxChange" /> | ||||
<span class="input-group-addon">{{ (product.unit == 'piece') ? 'p.' : ' '+((product.unit == 'g' || product.unit == 'kg') ? 'kg' : 'litre(s)') }}</span> | |||||
<span class="input-group-addon">{{ labelUnitReference(product.unit) }}</span> | |||||
</div> | </div> | ||||
<div v-if=" false && getProductDistribution(product).quantity_max != product.quantity_max"> | |||||
Limitation accessoires : <br /> | |||||
{{ product.quantity_max }} | |||||
<div class="limit-quantity-accessories" v-if="!showLoading && product.quantity_max && (getProductDistribution(product).quantity_max > product.quantity_max || !getProductDistribution(product).quantity_max)"> | |||||
<span class="glyphicon glyphicon-warning-sign"></span> Limitation accessoires : | |||||
<strong>{{ product.quantity_max }} {{ labelUnitReference(product.unit) }}</strong> | |||||
</div> | </div> | ||||
</td> | </td> | ||||
</tr> | </tr> | ||||
:units="units" | :units="units" | ||||
@close="closeModalOrderForm(true)" | @close="closeModalOrderForm(true)" | ||||
@ordercreatedupdated="orderCreatedUpdated" | @ordercreatedupdated="orderCreatedUpdated" | ||||
@updateproductorderprices="updateProductOrderPrices" | |||||
@updateproductorders="updateProductOrders" | |||||
></order-form> | ></order-form> | ||||
<div id="wrapper-nav-points-sale"> | <div id="wrapper-nav-points-sale"> | ||||
:units="units" | :units="units" | ||||
@close="closeModalOrderForm(false)" | @close="closeModalOrderForm(false)" | ||||
@ordercreatedupdated="orderCreatedUpdated" | @ordercreatedupdated="orderCreatedUpdated" | ||||
@updateproductorderprices="updateProductOrderPrices" | |||||
@updateproductorders="updateProductOrders" | |||||
@updateinvoiceprices="updateInvoicePrices" | @updateinvoiceprices="updateInvoicePrices" | ||||
></order-form> | ></order-form> | ||||
<tbody> | <tbody> | ||||
<tr v-for="product in products" v-if="product.status >= 0 || order.productOrder[product.id].quantity > 0" :class="(order.productOrder[product.id].quantity > 0) ? 'product-ordered' : ''"> | <tr v-for="product in products" v-if="product.status >= 0 || order.productOrder[product.id].quantity > 0" :class="(order.productOrder[product.id].quantity > 0) ? 'product-ordered' : ''"> | ||||
<td> | <td> | ||||
<span class="label label-success" v-if="loadingUpdateProductOrder || order.productOrder[product.id].active">Actif</span> | |||||
<span class="label label-success" v-if="order.productOrder[product.id].active">Actif</span> | |||||
<span class="label label-danger" v-else>Inactif</span> | <span class="label label-danger" v-else>Inactif</span> | ||||
</td> | </td> | ||||
<td> | <td> | ||||
</span> | </span> | ||||
</div> | </div> | ||||
</td> | </td> | ||||
<td class="quantity-remaining infinite" v-if="(getProductQuantityRemaining(product) === null) || order.productOrder[product.id].unit != product.unit">∞</td> | |||||
<td class="quantity-remaining negative" v-else-if="getProductQuantityRemaining(product) <= 0"> | |||||
{{ getProductQuantityRemaining(product) }} {{ order.productOrder[product.id].unit == 'piece' ? ' p.' : ' '+(order.productOrder[product.id].unit == 'g' || order.productOrder[product.id].unit == 'kg') ? 'kg' : 'litre(s)' }} | |||||
<span class="glyphicon glyphicon-alert" v-if="getProductQuantityRemaining(product) < 0"></span> | |||||
<td class="quantity-remaining"> | |||||
<span class="infinite" v-if="(getProductQuantityRemaining(order, product) === null) || order.productOrder[product.id].unit != product.unit">∞</span> | |||||
<span class="negative" v-else-if="getProductQuantityRemaining(order, product) <= 0"> | |||||
{{ getProductQuantityRemaining(order, product) }} {{ labelUnitReference(order.productOrder[product.id].unit) }} | |||||
<span class="glyphicon glyphicon-alert" v-if="getProductQuantityRemaining(order, product) < 0"></span> | |||||
</span> | |||||
<span class="has-quantity" v-else>{{ getProductQuantityRemaining(order, product) }} {{ labelUnitReference(order.productOrder[product.id].unit) }}</span> | |||||
</td> | </td> | ||||
<td class="quantity-remaining has-quantity" v-else>{{ getProductQuantityRemaining(product) }} {{ order.productOrder[product.id].unit == 'piece' ? ' p.' : ' '+(order.productOrder[product.id].unit == 'g' || order.productOrder[product.id].unit == 'kg') ? 'kg' : 'litre(s)' }}</td> | |||||
</tr> | </tr> | ||||
</tbody> | </tbody> | ||||
</table> | </table> | ||||
<button class="modal-default-button btn btn-primary" @click="submitFormCreate" v-if="!order.id">Créer</button> | <button class="modal-default-button btn btn-primary" @click="submitFormCreate" v-if="!order.id">Créer</button> | ||||
<div class="right"> | <div class="right"> | ||||
<button class="modal-default-button btn btn-info btn-update-prices" @click="updateProductOrderPrices(true)">Recharger les prix</button> | |||||
<button class="modal-default-button btn btn-info btn-update-prices" @click="updateProductOrders(true)">Recharger les prix</button> | |||||
<button v-if="order.id" class="modal-default-button btn btn-info btn-update-prices" @click="updateInvoicePrices(true)"> | <button v-if="order.id" class="modal-default-button btn btn-info btn-update-prices" @click="updateInvoicePrices(true)"> | ||||
Réinitialiser les prix facturés | Réinitialiser les prix facturés | ||||
</button> | </button> |
} | } | ||||
], | ], | ||||
[ | [ | ||||
'attribute' => 'paid', | |||||
'attribute' => 'is_paid', | |||||
'label' => 'Payée', | 'label' => 'Payée', | ||||
'filter' => [ | 'filter' => [ | ||||
0 => 'Non', | 0 => 'Non', | ||||
'headerOptions' => ['class' => 'column-hide-on-mobile'], | 'headerOptions' => ['class' => 'column-hide-on-mobile'], | ||||
'filterOptions' => ['class' => 'column-hide-on-mobile'], | 'filterOptions' => ['class' => 'column-hide-on-mobile'], | ||||
'contentOptions' => ['class' => 'column-hide-on-mobile'], | 'contentOptions' => ['class' => 'column-hide-on-mobile'], | ||||
'value' => function ($invoice) use ( $invoiceModule) { | |||||
'value' => function ($invoice) use ($invoiceModule) { | |||||
if($invoiceModule->isInvoicePaid($invoice)) { | if($invoiceModule->isInvoicePaid($invoice)) { | ||||
return '<span class="label label-success">Oui</span>'; | return '<span class="label label-success">Oui</span>'; | ||||
} | } |
$producerModule = $this->getProducerModule(); | $producerModule = $this->getProducerModule(); | ||||
$adminSettingBag = $this->getSettingModule()->getAdminSettingBag(); | $adminSettingBag = $this->getSettingModule()->getAdminSettingBag(); | ||||
$sharedPointSaleModule = $this->getSharedPointSaleModule(); | $sharedPointSaleModule = $this->getSharedPointSaleModule(); | ||||
$userModule = $this->getUserModule(); | |||||
$userCurrent = GlobalParam::getCurrentUser(); | |||||
$producer = GlobalParam::getCurrentProducer(); | $producer = GlobalParam::getCurrentProducer(); | ||||
?> | ?> | ||||
]) ?> | ]) ?> | ||||
<?php $producer = GlobalParam::getCurrentProducer(); ?> | <?php $producer = GlobalParam::getCurrentProducer(); ?> | ||||
<?php if($producer && !$producerModule->isUpToDateWithOpendistribVersion($producer) && $producer->option_display_message_new_opendistrib_version): ?> | |||||
<?php if($producer | |||||
&& !$producerModule->isUpToDateWithOpendistribVersion($producer) | |||||
&& $producer->option_display_message_new_opendistrib_version | |||||
&& !$userModule->getAuthorizationChecker()->isGrantedAsAdministrator($userCurrent)): ?> | |||||
<div class="alert alert-success"> | <div class="alert alert-success"> | ||||
<p> | <p> | ||||
<i class="icon fa fa-cogs"></i> | <i class="icon fa fa-cogs"></i> |
use common\helpers\Image; | use common\helpers\Image; | ||||
use common\helpers\Price; | use common\helpers\Price; | ||||
use domain\Distribution\Distribution\Distribution; | use domain\Distribution\Distribution\Distribution; | ||||
use domain\Feature\Feature\Feature; | |||||
use domain\Feature\Feature\FeatureModule; | |||||
use domain\Producer\Producer\Producer; | use domain\Producer\Producer\Producer; | ||||
use domain\Producer\Producer\ProducerModule; | use domain\Producer\Producer\ProducerModule; | ||||
use domain\Setting\AdminSettingBag; | |||||
use domain\User\User\UserModule; | use domain\User\User\UserModule; | ||||
use common\helpers\Environment; | use common\helpers\Environment; | ||||
use yii\helpers\Html; | use yii\helpers\Html; | ||||
$producerModule = ProducerModule::getInstance(); | $producerModule = ProducerModule::getInstance(); | ||||
$producer = GlobalParam::getCurrentProducer(); | $producer = GlobalParam::getCurrentProducer(); | ||||
$userCurrent = GlobalParam::getCurrentUser(); | $userCurrent = GlobalParam::getCurrentUser(); | ||||
$featureChecker = FeatureModule::getInstance()->getChecker(); | |||||
$adminSettingBag = AdminSettingBag::getInstance(); | |||||
?> | ?> | ||||
</a> | </a> | ||||
</li> | </li> | ||||
<?php if ($userModule->getAuthorizationChecker()->isGrantedAsProducer($userCurrent)): ?> | <?php if ($userModule->getAuthorizationChecker()->isGrantedAsProducer($userCurrent)): ?> | ||||
<li> | <li> | ||||
<a href="<?= Yii::$app->urlManagerProducer->createAbsoluteUrl(['site/index', 'slug_producer' => GlobalParam::getCurrentProducer()->slug]); ?>"> | <a href="<?= Yii::$app->urlManagerProducer->createAbsoluteUrl(['site/index', 'slug_producer' => GlobalParam::getCurrentProducer()->slug]); ?>"> | ||||
</li> | </li> | ||||
<?php endif; ?> | <?php endif; ?> | ||||
<?php if($featureChecker->isEnabled(Feature::ALIAS_FORUM)): ?> | |||||
<li> | |||||
<a href="<?= $adminSettingBag->get('forumFlarumUrl') ?>" target="_blank"> | |||||
<i class="bi bi-people"></i> | |||||
<span class="hidden-xs hidden-sm">Forum</span> | |||||
</a> | |||||
</li> | |||||
<?php endif; ?> | |||||
<li class="dropdown user user-menu"> | <li class="dropdown user user-menu"> | ||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"> | <a href="#" class="dropdown-toggle" data-toggle="dropdown"> | ||||
<i class="bi bi-person"></i> | <i class="bi bi-person"></i> |
], | ], | ||||
['label' => 'Abonnements', 'icon' => 'repeat', 'url' => ['/subscription/index'], 'visible' => $isUserCurrentGrantedAsProducer, 'active' => Yii::$app->controller->id == 'subscription'], | ['label' => 'Abonnements', 'icon' => 'repeat', 'url' => ['/subscription/index'], 'visible' => $isUserCurrentGrantedAsProducer, 'active' => Yii::$app->controller->id == 'subscription'], | ||||
[ | [ | ||||
'label' => 'Communiquer', | |||||
'label' => 'Communication', | |||||
'icon' => 'bullhorn', | 'icon' => 'bullhorn', | ||||
'url' => ['/communicate/email'], | 'url' => ['/communicate/email'], | ||||
'visible' => $isUserCurrentGrantedAsProducer, | 'visible' => $isUserCurrentGrantedAsProducer, | ||||
'items' => [ | 'items' => [ | ||||
['label' => 'Email', 'icon' => 'paper-plane', 'url' => ['/communicate/email'], 'visible' => $isUserCurrentGrantedAsProducer], | ['label' => 'Email', 'icon' => 'paper-plane', 'url' => ['/communicate/email'], 'visible' => $isUserCurrentGrantedAsProducer], | ||||
['label' => 'Email automatique', 'icon' => 'paper-plane-o', 'url' => ['/automatic-email/index'], 'visible' => $isUserCurrentGrantedAsProducer && $featureChecker->isEnabled(Feature::ALIAS_AUTOMATIC_EMAIL)], | |||||
['label' => 'Papier', 'icon' => 'print', 'url' => ['/communicate/paper'], 'visible' => $isUserCurrentGrantedAsProducer], | ['label' => 'Papier', 'icon' => 'print', 'url' => ['/communicate/paper'], 'visible' => $isUserCurrentGrantedAsProducer], | ||||
] | ] | ||||
], | ], | ||||
['label' => 'Chiffre d\'affaire', 'icon' => 'line-chart', 'url' => ['/stats/index'], 'visible' => $isUserCurrentGrantedAsProducer], | ['label' => 'Chiffre d\'affaire', 'icon' => 'line-chart', 'url' => ['/stats/index'], 'visible' => $isUserCurrentGrantedAsProducer], | ||||
['label' => 'Rapports', 'icon' => 'pencil-square-o', 'url' => ['/report/index'], 'visible' => $isUserCurrentGrantedAsProducer], | ['label' => 'Rapports', 'icon' => 'pencil-square-o', 'url' => ['/report/index'], 'visible' => $isUserCurrentGrantedAsProducer], | ||||
['label' => 'Produits', 'icon' => 'table', 'url' => ['/stats/products'], 'visible' => $isUserCurrentGrantedAsProducer], | ['label' => 'Produits', 'icon' => 'table', 'url' => ['/stats/products'], 'visible' => $isUserCurrentGrantedAsProducer], | ||||
['label' => 'Export paiements', 'icon' => 'euro', 'url' => ['/report/payments'], 'visible' => $isUserCurrentGrantedAsProducer], | |||||
], | ], | ||||
], | ], | ||||
['label' => 'Paramètres', 'icon' => 'cog', 'url' => ['/producer/update'], 'visible' => $isUserCurrentGrantedAsProducer], | ['label' => 'Paramètres', 'icon' => 'cog', 'url' => ['/producer/update'], 'visible' => $isUserCurrentGrantedAsProducer], |
if($isBilled && $producerModule->getSolver()->isFreeBillingPeriodSponsorship($producer)) { | if($isBilled && $producerModule->getSolver()->isFreeBillingPeriodSponsorship($producer)) { | ||||
$str .= "<br /><p><span class=\"glyphicon glyphicon-warning-sign\"></span> <strong>Pas de facturation, offre de parrainage jusqu'au ".$producerModule->getSolver()->getDateEndFreeBillingPeriodSponsorship($producer)->format('d/m/Y')."</strong></p>"; | $str .= "<br /><p><span class=\"glyphicon glyphicon-warning-sign\"></span> <strong>Pas de facturation, offre de parrainage jusqu'au ".$producerModule->getSolver()->getDateEndFreeBillingPeriodSponsorship($producer)->format('d/m/Y')."</strong></p>"; | ||||
if(!$producer->getSponsorshipSponsorReward()) { | |||||
$str .= '<p><i class="fa fa-gift"></i> Créer un avoir de 30€ pour le parrain <strong>'.Html::encode($producer->getSponsoredBy()->getName()).'</strong> sur Dolibarr et valider la récompense parrain.</p>'; | |||||
} | |||||
$str .= '<p><i class="fa fa-gift"></i> Créer un avoir pour le parrain <strong>'.Html::encode($producer->getSponsoredBy()->getName()).'</strong> sur Dolibarr.</p>'; | |||||
} | } | ||||
return $str; | return $str; |
<?php | |||||
/** | |||||
Copyright Souke (2018) | |||||
contact@souke.fr | |||||
Ce logiciel est un programme informatique servant à aider les producteurs | |||||
à distribuer leur production en circuits courts. | |||||
Ce logiciel est régi par la licence CeCILL soumise au droit français et | |||||
respectant les principes de diffusion des logiciels libres. Vous pouvez | |||||
utiliser, modifier et/ou redistribuer ce programme sous les conditions | |||||
de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA | |||||
sur le site "http://www.cecill.info". | |||||
En contrepartie de l'accessibilité au code source et des droits de copie, | |||||
de modification et de redistribution accordés par cette licence, il n'est | |||||
offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons, | |||||
seule une responsabilité restreinte pèse sur l'auteur du programme, le | |||||
titulaire des droits patrimoniaux et les concédants successifs. | |||||
A cet égard l'attention de l'utilisateur est attirée sur les risques | |||||
associés au chargement, à l'utilisation, à la modification et/ou au | |||||
développement et à la reproduction du logiciel par l'utilisateur étant | |||||
donné sa spécificité de logiciel libre, qui peut le rendre complexe à | |||||
manipuler et qui le réserve donc à des développeurs et des professionnels | |||||
avertis possédant des connaissances informatiques approfondies. Les | |||||
utilisateurs sont donc invités à charger et tester l'adéquation du | |||||
logiciel à leurs besoins dans des conditions permettant d'assurer la | |||||
sécurité de leurs systèmes et ou de leurs données et, plus généralement, | |||||
à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. | |||||
Le fait que vous puissiez accéder à cet en-tête signifie que vous avez | |||||
pris connaissance de la licence CeCILL, et que vous en avez accepté les | |||||
termes. | |||||
*/ | |||||
use yii\helpers\Html; | |||||
use yii\widgets\ActiveForm; | |||||
$this->setTitle('Paiements') ; | |||||
$this->addBreadcrumb('Paiements') ; | |||||
?> | |||||
<div class="row"> | |||||
<div class="col-md-8"> | |||||
<div class="panel panel-default"> | |||||
<div class="panel-heading"> | |||||
<h3 class="panel-title"> | |||||
<i class="fa fa-download"></i> | |||||
Export CSV des paiements | |||||
</h3> | |||||
</div> | |||||
<div class="panel-body"> | |||||
<?php $form = ActiveForm::begin(); ?> | |||||
<?= $form->field($reportPaymentsForm, 'date_start')->textInput([ | |||||
'class' => 'datepicker form-control' | |||||
]) ?> | |||||
<?= $form->field($reportPaymentsForm, 'date_end')->textInput([ | |||||
'class' => 'datepicker form-control' | |||||
]) ?> | |||||
<?= Html::submitButton('Exporter', ['class' => 'btn btn-primary']) ?> | |||||
<?php ActiveForm::end(); ?> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> |
Votre filleul démarre sur le logiciel avec <strong>3 mois offerts</strong>. | Votre filleul démarre sur le logiciel avec <strong>3 mois offerts</strong>. | ||||
</li> | </li> | ||||
<li> | <li> | ||||
Vous obtenez <strong>30€ de réduction</strong> sur vos prochaines factures dès lors que votre filleul | |||||
utilise le logiciel en production. | |||||
Pendant les 3 mois offerts de votre filleul, vous obtenez chaque début de mois <strong>une réduction</strong> | |||||
équivalente à <a href="<?= Yii::$app->urlManager->createUrl(['producer/billing']) ?>">la tranche dans laquelle il se situe</a>. | |||||
</li> | </li> | ||||
</ul> | </ul> | ||||
</div> | </div> |
<div class="info-box"> | <div class="info-box"> | ||||
<span class="info-box-icon bg-yellow"><i class="fa fa-users"></i></span> | <span class="info-box-icon bg-yellow"><i class="fa fa-users"></i></span> | ||||
<div class="info-box-content"> | <div class="info-box-content"> | ||||
<span class="info-box-text"><br/><?= Html::a("Ouvrir une discussion sur le forum", $adminSettingBag->get('forumFlarumUrl'), ['class' => 'btn btn-sm btn-default', 'target' => '_blank']); ?></span> | |||||
<span class="info-box-text"><br/><?= Html::a("Aller sur le forum", $adminSettingBag->get('forumFlarumUrl'), ['class' => 'btn btn-sm btn-default', 'target' => '_blank']); ?></span> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> |
return $html; | return $html; | ||||
} | } | ||||
], | ], | ||||
[ | |||||
'attribute' => 'note_emails', | |||||
'format' => 'raw', | |||||
'value' => function($user) { | |||||
if($user->note_emails) { | |||||
return nl2br($user->note_emails); | |||||
} | |||||
return ''; | |||||
} | |||||
], | |||||
[ | [ | ||||
'attribute' => 'producers', | 'attribute' => 'producers', | ||||
'label' => 'Profils', | 'label' => 'Profils', |
</h3> | </h3> | ||||
</div> | </div> | ||||
<div class="panel-body"> | <div class="panel-body"> | ||||
<?= $form->field($model, 'points_sale')->checkboxlist( | |||||
ArrayHelper::map($pointsSaleArray, 'id', function ($pointSale) use ($model) { | |||||
$commentUserPointSale = isset($pointSale->userPointSale[0]) ? $pointSale->userPointSale[0]->comment : ''; | |||||
$html = Html::encode($pointSale->name); | |||||
if ($pointSale->restricted_access) { | |||||
$html .= '<input type="text" placeholder="Commentaire" class="form-control" name="User[comment_point_sale_' . $pointSale->id . ']" value="' . (($model->id) ? Html::encode($commentUserPointSale) : '') . '" />'; | |||||
} | |||||
return $html; | |||||
}), [ | |||||
'encode' => false | |||||
]); | |||||
?> | |||||
<div class="row"> | |||||
<div class="col-md-8"> | |||||
<?= $form->field($model, 'points_sale')->checkboxlist( | |||||
ArrayHelper::map($pointsSaleArray, 'id', function ($pointSale) use ($model) { | |||||
$commentUserPointSale = isset($pointSale->userPointSale[0]) ? $pointSale->userPointSale[0]->comment : ''; | |||||
$html = Html::encode($pointSale->name); | |||||
if ($pointSale->restricted_access) { | |||||
$html .= '<input type="text" placeholder="Commentaire" class="form-control" name="User[comment_point_sale_' . $pointSale->id . ']" value="' . (($model->id) ? Html::encode($commentUserPointSale) : '') . '" />'; | |||||
} | |||||
return $html; | |||||
}), [ | |||||
'encode' => false | |||||
]); | |||||
?> | |||||
</div> | |||||
<div class="col-md-4"> | |||||
<?= $form->field($model, 'exclusive_access_selected_points_sale')->widget(Toggle::class, | |||||
[ | |||||
'options' => [ | |||||
'data-id' => $model->id, | |||||
'data-on' => 'Oui', | |||||
'data-off' => 'Non', | |||||
'data-onstyle' => 'success', | |||||
'data-offstyle' => 'default', | |||||
], | |||||
] | |||||
); ?> | |||||
</div> | |||||
</div> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
<?php endif; ?> | <?php endif; ?> |
</h3> | </h3> | ||||
</div> | </div> | ||||
<div class="panel-body"> | <div class="panel-body"> | ||||
<?php $form = ActiveForm::begin(); ?> | |||||
<?php $form = ActiveForm::begin([ | |||||
'enableClientValidation' => false | |||||
]); ?> | |||||
<div class="row"> | <div class="row"> | ||||
<div class="col-md-6"> | <div class="col-md-6"> | ||||
<?= $form->field($creditForm, 'type')->dropDownList([ | <?= $form->field($creditForm, 'type')->dropDownList([ |
.distribution-index #calendar .vc-day.is-not-in-month .vc-highlights * { | .distribution-index #calendar .vc-day.is-not-in-month .vc-highlights * { | ||||
opacity: 1 !important; | opacity: 1 !important; | ||||
} | } | ||||
/* line 97, ../sass/distribution/_index.scss */ | |||||
/* line 96, ../sass/distribution/_index.scss */ | |||||
.distribution-index table td.quantity-remaining { | |||||
text-align: right; | |||||
} | |||||
/* line 99, ../sass/distribution/_index.scss */ | |||||
.distribution-index table td.quantity-remaining .has-quantity, .distribution-index table td.quantity-remaining .infinite { | |||||
color: #00A65A; | |||||
} | |||||
/* line 103, ../sass/distribution/_index.scss */ | |||||
.distribution-index table td.quantity-remaining .negative { | |||||
color: #DD4B39; | |||||
} | |||||
/* line 107, ../sass/distribution/_index.scss */ | |||||
.distribution-index table td.quantity-remaining .infinite, .distribution-index table td.quantity-remaining .empty { | |||||
font-size: 18px; | |||||
} | |||||
/* line 113, ../sass/distribution/_index.scss */ | |||||
.distribution-index #products td.quantities { | .distribution-index #products td.quantities { | ||||
width: 100px; | width: 100px; | ||||
text-align: right; | text-align: right; | ||||
} | } | ||||
/* line 102, ../sass/distribution/_index.scss */ | |||||
/* line 118, ../sass/distribution/_index.scss */ | |||||
.distribution-index #products input.quantity-max { | .distribution-index #products input.quantity-max { | ||||
width: 50px; | width: 50px; | ||||
text-align: center; | text-align: center; | ||||
display: inline; | display: inline; | ||||
} | } | ||||
/* line 110, ../sass/distribution/_index.scss */ | |||||
/* line 126, ../sass/distribution/_index.scss */ | |||||
.distribution-index #infos-top .col-md-4 { | .distribution-index #infos-top .col-md-4 { | ||||
padding: 0px; | padding: 0px; | ||||
} | } | ||||
/* line 116, ../sass/distribution/_index.scss */ | |||||
/* line 132, ../sass/distribution/_index.scss */ | |||||
.distribution-index #infos-top .info-box { | .distribution-index #infos-top .info-box { | ||||
min-height: 96px; | min-height: 96px; | ||||
height: 96px; | height: 96px; | ||||
} | } | ||||
/* line 120, ../sass/distribution/_index.scss */ | |||||
/* line 136, ../sass/distribution/_index.scss */ | |||||
.distribution-index #infos-top .info-box .info-box-icon { | .distribution-index #infos-top .info-box .info-box-icon { | ||||
height: 96px; | height: 96px; | ||||
width: 50px; | width: 50px; | ||||
line-height: 96px; | line-height: 96px; | ||||
} | } | ||||
/* line 125, ../sass/distribution/_index.scss */ | |||||
/* line 141, ../sass/distribution/_index.scss */ | |||||
.distribution-index #infos-top .info-box .info-box-icon i.fa { | .distribution-index #infos-top .info-box .info-box-icon i.fa { | ||||
font-size: 30px; | font-size: 30px; | ||||
} | } | ||||
/* line 130, ../sass/distribution/_index.scss */ | |||||
/* line 146, ../sass/distribution/_index.scss */ | |||||
.distribution-index #infos-top .info-box .info-box-content { | .distribution-index #infos-top .info-box .info-box-content { | ||||
margin-left: 55px; | margin-left: 55px; | ||||
} | } | ||||
/* line 133, ../sass/distribution/_index.scss */ | |||||
/* line 149, ../sass/distribution/_index.scss */ | |||||
.distribution-index #infos-top .info-box .info-box-content .info-box-text { | .distribution-index #infos-top .info-box .info-box-content .info-box-text { | ||||
font-size: 12px; | font-size: 12px; | ||||
} | } | ||||
/* line 136, ../sass/distribution/_index.scss */ | |||||
/* line 152, ../sass/distribution/_index.scss */ | |||||
.distribution-index #infos-top .info-box .info-box-content .info-box-text .btn { | .distribution-index #infos-top .info-box .info-box-content .info-box-text .btn { | ||||
font-size: 12px; | font-size: 12px; | ||||
text-transform: uppercase; | text-transform: uppercase; | ||||
} | } | ||||
/* line 142, ../sass/distribution/_index.scss */ | |||||
/* line 158, ../sass/distribution/_index.scss */ | |||||
.distribution-index #infos-top .info-box .info-box-content .info-box-number { | .distribution-index #infos-top .info-box .info-box-content .info-box-number { | ||||
font-size: 14px; | font-size: 14px; | ||||
} | } | ||||
/* line 149, ../sass/distribution/_index.scss */ | |||||
/* line 165, ../sass/distribution/_index.scss */ | |||||
.distribution-index #infos-top #info-box-distribution .btn-active-week { | .distribution-index #infos-top #info-box-distribution .btn-active-week { | ||||
float: right; | float: right; | ||||
} | } | ||||
/* line 155, ../sass/distribution/_index.scss */ | |||||
/* line 171, ../sass/distribution/_index.scss */ | |||||
.distribution-index #infos-top #summary-ca-weight .normal { | .distribution-index #infos-top #summary-ca-weight .normal { | ||||
font-weight: normal; | font-weight: normal; | ||||
} | } | ||||
/* line 165, ../sass/distribution/_index.scss */ | |||||
/* line 181, ../sass/distribution/_index.scss */ | |||||
.distribution-index #modal-products table.table thead tr td { | .distribution-index #modal-products table.table thead tr td { | ||||
font-weight: bold; | font-weight: bold; | ||||
} | } | ||||
/* line 171, ../sass/distribution/_index.scss */ | |||||
/* line 187, ../sass/distribution/_index.scss */ | |||||
.distribution-index #modal-products table.table td.quantity-ordered, | .distribution-index #modal-products table.table td.quantity-ordered, | ||||
.distribution-index #modal-products table.table td.quantity-max { | .distribution-index #modal-products table.table td.quantity-max { | ||||
text-align: center; | text-align: center; | ||||
} | } | ||||
/* line 176, ../sass/distribution/_index.scss */ | |||||
/* line 192, ../sass/distribution/_index.scss */ | |||||
.distribution-index #modal-products table.table td.quantity-ordered { | .distribution-index #modal-products table.table td.quantity-ordered { | ||||
width: 50px; | width: 50px; | ||||
} | } | ||||
/* line 180, ../sass/distribution/_index.scss */ | |||||
/* line 196, ../sass/distribution/_index.scss */ | |||||
.distribution-index #modal-products table.table td.quantity-max { | .distribution-index #modal-products table.table td.quantity-max { | ||||
width: 120px; | width: 120px; | ||||
} | } | ||||
/* line 183, ../sass/distribution/_index.scss */ | |||||
/* line 199, ../sass/distribution/_index.scss */ | |||||
.distribution-index #modal-products table.table td.quantity-max input { | .distribution-index #modal-products table.table td.quantity-max input { | ||||
text-align: center; | text-align: center; | ||||
min-width: 50px; | min-width: 50px; | ||||
} | } | ||||
/* line 191, ../sass/distribution/_index.scss */ | |||||
/* line 204, ../sass/distribution/_index.scss */ | |||||
.distribution-index #modal-products table.table td.quantity-max .limit-quantity-accessories { | |||||
margin-top: 7px; | |||||
font-size: 12px; | |||||
} | |||||
/* line 208, ../sass/distribution/_index.scss */ | |||||
.distribution-index #modal-products table.table td.quantity-max .limit-quantity-accessories .quantity { | |||||
font-weight: bold; | |||||
} | |||||
/* line 216, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders { | .distribution-index #orders { | ||||
position: relative; | position: relative; | ||||
} | } | ||||
/* line 196, ../sass/distribution/_index.scss */ | |||||
/* line 221, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders .panel-heading .buttons .btn { | .distribution-index #orders .panel-heading .buttons .btn { | ||||
position: relative; | position: relative; | ||||
top: -19px; | top: -19px; | ||||
float: right; | float: right; | ||||
margin-left: 10px; | margin-left: 10px; | ||||
} | } | ||||
/* line 205, ../sass/distribution/_index.scss */ | |||||
/* line 230, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders #wrapper-nav-points-sale { | .distribution-index #orders #wrapper-nav-points-sale { | ||||
margin-bottom: 10px; | margin-bottom: 10px; | ||||
} | } | ||||
/* line 208, ../sass/distribution/_index.scss */ | |||||
/* line 233, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders #wrapper-nav-points-sale ul#nav-points-sale { | .distribution-index #orders #wrapper-nav-points-sale ul#nav-points-sale { | ||||
margin: 0px; | margin: 0px; | ||||
padding: 0px; | padding: 0px; | ||||
list-style-type: none; | list-style-type: none; | ||||
} | } | ||||
/* line 213, ../sass/distribution/_index.scss */ | |||||
/* line 238, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders #wrapper-nav-points-sale ul#nav-points-sale li { | .distribution-index #orders #wrapper-nav-points-sale ul#nav-points-sale li { | ||||
float: left; | float: left; | ||||
margin-right: 10px; | margin-right: 10px; | ||||
margin-bottom: 10px; | margin-bottom: 10px; | ||||
} | } | ||||
/* line 219, ../sass/distribution/_index.scss */ | |||||
/* line 244, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders #wrapper-nav-points-sale ul#nav-points-sale li a .label { | .distribution-index #orders #wrapper-nav-points-sale ul#nav-points-sale li a .label { | ||||
background-color: white; | background-color: white; | ||||
border: solid 1px #e0e0e0; | border: solid 1px #e0e0e0; | ||||
-webkit-border-radius: 10px; | -webkit-border-radius: 10px; | ||||
border-radius: 10px; | border-radius: 10px; | ||||
} | } | ||||
/* line 230, ../sass/distribution/_index.scss */ | |||||
/* line 255, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders #buttons-top-orders { | .distribution-index #orders #buttons-top-orders { | ||||
background-color: #F5F5F5; | background-color: #F5F5F5; | ||||
padding: 10px 20px; | padding: 10px 20px; | ||||
border-radius: 5px; | border-radius: 5px; | ||||
margin-bottom: 20px; | margin-bottom: 20px; | ||||
} | } | ||||
/* line 241, ../sass/distribution/_index.scss */ | |||||
/* line 266, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders #buttons-top-orders .right { | .distribution-index #orders #buttons-top-orders .right { | ||||
float: right; | float: right; | ||||
} | } | ||||
/* line 245, ../sass/distribution/_index.scss */ | |||||
/* line 270, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders #buttons-top-orders .dropdown { | .distribution-index #orders #buttons-top-orders .dropdown { | ||||
display: inline-block; | display: inline-block; | ||||
} | } | ||||
/* line 250, ../sass/distribution/_index.scss */ | |||||
/* line 275, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders .point-sale-totals { | .distribution-index #orders .point-sale-totals { | ||||
background-color: white; | background-color: white; | ||||
padding: 10px 20px; | padding: 10px 20px; | ||||
border-radius: 5px; | border-radius: 5px; | ||||
margin-bottom: 20px; | margin-bottom: 20px; | ||||
} | } | ||||
/* line 257, ../sass/distribution/_index.scss */ | |||||
/* line 282, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders .point-sale-totals .title { | .distribution-index #orders .point-sale-totals .title { | ||||
color: gray; | color: gray; | ||||
font-size: 13px; | font-size: 13px; | ||||
margin-right: 13px; | margin-right: 13px; | ||||
text-transform: uppercase; | text-transform: uppercase; | ||||
} | } | ||||
/* line 267, ../sass/distribution/_index.scss */ | |||||
/* line 292, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders table td.column-user { | .distribution-index #orders table td.column-user { | ||||
position: relative; | position: relative; | ||||
} | } | ||||
/* line 270, ../sass/distribution/_index.scss */ | |||||
/* line 295, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders table td.column-user:hover .shortcuts { | .distribution-index #orders table td.column-user:hover .shortcuts { | ||||
display: block; | display: block; | ||||
} | } | ||||
/* line 274, ../sass/distribution/_index.scss */ | |||||
/* line 299, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders table td.column-user a { | .distribution-index #orders table td.column-user a { | ||||
color: #333; | color: #333; | ||||
} | } | ||||
/* line 277, ../sass/distribution/_index.scss */ | |||||
/* line 302, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders table td.column-user a:hover { | .distribution-index #orders table td.column-user a:hover { | ||||
text-decoration: underline; | text-decoration: underline; | ||||
} | } | ||||
/* line 282, ../sass/distribution/_index.scss */ | |||||
/* line 307, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders table td.column-user .shortcuts { | .distribution-index #orders table td.column-user .shortcuts { | ||||
display: none; | display: none; | ||||
float: right; | float: right; | ||||
top: 1px; | top: 1px; | ||||
right: 1px; | right: 1px; | ||||
} | } | ||||
/* line 290, ../sass/distribution/_index.scss */ | |||||
/* line 315, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders table td.column-user .user-trust-alert { | .distribution-index #orders table td.column-user .user-trust-alert { | ||||
color: red; | color: red; | ||||
} | } | ||||
/* line 295, ../sass/distribution/_index.scss */ | |||||
/* line 320, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders table td.column-delivery-note { | .distribution-index #orders table td.column-delivery-note { | ||||
position: relative; | position: relative; | ||||
} | } | ||||
/* line 299, ../sass/distribution/_index.scss */ | |||||
/* line 324, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders table td.tiller { | .distribution-index #orders table td.tiller { | ||||
width: 60px; | width: 60px; | ||||
} | } | ||||
/* line 302, ../sass/distribution/_index.scss */ | |||||
/* line 327, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders table td.tiller label { | .distribution-index #orders table td.tiller label { | ||||
font-size: 12px; | font-size: 12px; | ||||
cursor: pointer; | cursor: pointer; | ||||
top: -2px; | top: -2px; | ||||
font-weight: normal; | font-weight: normal; | ||||
} | } | ||||
/* line 311, ../sass/distribution/_index.scss */ | |||||
/* line 336, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders table td.column-actions { | .distribution-index #orders table td.column-actions { | ||||
position: relative; | position: relative; | ||||
text-align: right; | text-align: right; | ||||
} | } | ||||
/* line 315, ../sass/distribution/_index.scss */ | |||||
/* line 340, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders table td.column-actions .wrapper-button-dropdown { | .distribution-index #orders table td.column-actions .wrapper-button-dropdown { | ||||
display: inline-block; | display: inline-block; | ||||
} | } | ||||
/* line 319, ../sass/distribution/_index.scss */ | |||||
/* line 344, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders table td.column-actions .dropdown-menu { | .distribution-index #orders table td.column-actions .dropdown-menu { | ||||
left: -70px; | left: -70px; | ||||
width: 227px; | width: 227px; | ||||
} | } | ||||
/* line 324, ../sass/distribution/_index.scss */ | |||||
/* line 349, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders table td.column-actions .modal-form-order, | .distribution-index #orders table td.column-actions .modal-form-order, | ||||
.distribution-index #orders table td.column-actions .modal-payment { | .distribution-index #orders table td.column-actions .modal-payment { | ||||
text-align: left; | text-align: left; | ||||
} | } | ||||
/* line 329, ../sass/distribution/_index.scss */ | |||||
/* line 354, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders table td.column-actions .add-subscription { | .distribution-index #orders table td.column-actions .add-subscription { | ||||
position: relative; | position: relative; | ||||
} | } | ||||
/* line 332, ../sass/distribution/_index.scss */ | |||||
/* line 357, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders table td.column-actions .add-subscription .glyphicon-plus { | .distribution-index #orders table td.column-actions .add-subscription .glyphicon-plus { | ||||
position: absolute; | position: absolute; | ||||
top: 4px; | top: 4px; | ||||
right: 4px; | right: 4px; | ||||
font-size: 7px; | font-size: 7px; | ||||
} | } | ||||
/* line 341, ../sass/distribution/_index.scss */ | |||||
/* line 366, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders table td.column-state-payment { | .distribution-index #orders table td.column-state-payment { | ||||
width: 133px; | width: 133px; | ||||
} | } | ||||
/* line 347, ../sass/distribution/_index.scss */ | |||||
/* line 372, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders table td.column-credit a.positive { | .distribution-index #orders table td.column-credit a.positive { | ||||
color: green; | color: green; | ||||
} | } | ||||
/* line 350, ../sass/distribution/_index.scss */ | |||||
/* line 375, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders table td.column-credit a.negative { | .distribution-index #orders table td.column-credit a.negative { | ||||
color: red; | color: red; | ||||
} | } | ||||
/* line 356, ../sass/distribution/_index.scss */ | |||||
/* line 381, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders table .state-payment-mobile { | .distribution-index #orders table .state-payment-mobile { | ||||
display: none; | display: none; | ||||
} | } | ||||
/* line 360, ../sass/distribution/_index.scss */ | |||||
/* line 385, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders table td.column-payment { | .distribution-index #orders table td.column-payment { | ||||
position: relative; | position: relative; | ||||
} | } | ||||
/* line 363, ../sass/distribution/_index.scss */ | |||||
/* line 388, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders table td.column-payment div.btn-group { | .distribution-index #orders table td.column-payment div.btn-group { | ||||
width: 125px; | width: 125px; | ||||
} | } | ||||
/* line 369, ../sass/distribution/_index.scss */ | |||||
/* line 394, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders table tr.view ul { | .distribution-index #orders table tr.view ul { | ||||
list-style-type: none; | list-style-type: none; | ||||
margin-left: 0px; | margin-left: 0px; | ||||
padding-left: 15px; | padding-left: 15px; | ||||
} | } | ||||
/* line 379, ../sass/distribution/_index.scss */ | |||||
/* line 404, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders table tr.view .comment { | .distribution-index #orders table tr.view .comment { | ||||
margin-top: 20px; | margin-top: 20px; | ||||
} | } | ||||
/* line 383, ../sass/distribution/_index.scss */ | |||||
/* line 408, ../sass/distribution/_index.scss */ | |||||
.distribution-index #orders table tr.view .delivery { | .distribution-index #orders table tr.view .delivery { | ||||
margin-top: 20px; | margin-top: 20px; | ||||
} | } | ||||
/* line 392, ../sass/distribution/_index.scss */ | |||||
/* line 417, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-form-order .modal-container { | .distribution-index .modal-form-order .modal-container { | ||||
width: 100%; | width: 100%; | ||||
padding: 0px; | padding: 0px; | ||||
} | } | ||||
/* line 396, ../sass/distribution/_index.scss */ | |||||
/* line 421, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-form-order .modal-container .modal-body { | .distribution-index .modal-form-order .modal-container .modal-body { | ||||
padding-right: 15px; | padding-right: 15px; | ||||
} | } | ||||
/* line 399, ../sass/distribution/_index.scss */ | |||||
/* line 424, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-form-order .modal-container .modal-body table { | .distribution-index .modal-form-order .modal-container .modal-body table { | ||||
margin-bottom: 150px; | margin-bottom: 150px; | ||||
} | } | ||||
/* line 404, ../sass/distribution/_index.scss */ | |||||
/* line 429, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-form-order .modal-container .modal-footer { | .distribution-index .modal-form-order .modal-container .modal-footer { | ||||
border-top-color: #f4f4f4; | border-top-color: #f4f4f4; | ||||
position: fixed; | position: fixed; | ||||
text-align: center; | text-align: center; | ||||
border-top: solid 1px #e0e0e0; | border-top: solid 1px #e0e0e0; | ||||
} | } | ||||
/* line 416, ../sass/distribution/_index.scss */ | |||||
/* line 441, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-form-order .modal-container .modal-footer .actions-form button { | .distribution-index .modal-form-order .modal-container .modal-footer .actions-form button { | ||||
float: none; | float: none; | ||||
} | } | ||||
/* line 420, ../sass/distribution/_index.scss */ | |||||
/* line 445, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-form-order .modal-container .modal-footer .actions-form div.right { | .distribution-index .modal-form-order .modal-container .modal-footer .actions-form div.right { | ||||
float: right; | float: right; | ||||
} | } | ||||
/* line 427, ../sass/distribution/_index.scss */ | |||||
/* line 452, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-form-order .btn-credit { | .distribution-index .modal-form-order .btn-credit { | ||||
float: right; | float: right; | ||||
} | } | ||||
/* line 433, ../sass/distribution/_index.scss */ | |||||
/* line 458, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-form-order table.table-products .product-ordered td { | .distribution-index .modal-form-order table.table-products .product-ordered td { | ||||
background-color: #e9e9e9; | background-color: #e9e9e9; | ||||
} | } | ||||
/* line 437, ../sass/distribution/_index.scss */ | |||||
/* line 462, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-form-order table.table-products .product-ordered input.input-quantity { | .distribution-index .modal-form-order table.table-products .product-ordered input.input-quantity { | ||||
font-size: 16px; | font-size: 16px; | ||||
font-weight: bold; | font-weight: bold; | ||||
} | } | ||||
/* line 443, ../sass/distribution/_index.scss */ | |||||
/* line 468, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-form-order table.table-products td.price { | .distribution-index .modal-form-order table.table-products td.price { | ||||
width: 150px; | width: 150px; | ||||
} | } | ||||
/* line 446, ../sass/distribution/_index.scss */ | |||||
/* line 471, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-form-order table.table-products td.price input { | .distribution-index .modal-form-order table.table-products td.price input { | ||||
text-align: center; | text-align: center; | ||||
} | } | ||||
/* line 450, ../sass/distribution/_index.scss */ | |||||
/* line 475, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-form-order table.table-products td.price .input-group-addon { | .distribution-index .modal-form-order table.table-products td.price .input-group-addon { | ||||
background-color: #eee; | background-color: #eee; | ||||
} | } | ||||
/* line 454, ../sass/distribution/_index.scss */ | |||||
/* line 479, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-form-order table.table-products td.price .invoice-price { | .distribution-index .modal-form-order table.table-products td.price .invoice-price { | ||||
margin-top: 8px; | margin-top: 8px; | ||||
} | } | ||||
/* line 456, ../sass/distribution/_index.scss */ | |||||
/* line 481, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-form-order table.table-products td.price .invoice-price .label-invoice-price { | .distribution-index .modal-form-order table.table-products td.price .invoice-price .label-invoice-price { | ||||
font-size: 11px; | font-size: 11px; | ||||
font-weight: bold; | font-weight: bold; | ||||
color: gray; | color: gray; | ||||
} | } | ||||
/* line 464, ../sass/distribution/_index.scss */ | |||||
/* line 489, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-form-order table.table-products td.quantity { | .distribution-index .modal-form-order table.table-products td.quantity { | ||||
width: 165px; | width: 165px; | ||||
} | } | ||||
/* line 467, ../sass/distribution/_index.scss */ | |||||
/* line 492, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-form-order table.table-products td.quantity input { | .distribution-index .modal-form-order table.table-products td.quantity input { | ||||
text-align: center; | text-align: center; | ||||
color: black; | color: black; | ||||
} | } | ||||
/* line 472, ../sass/distribution/_index.scss */ | |||||
/* line 497, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-form-order table.table-products td.quantity .form-control { | .distribution-index .modal-form-order table.table-products td.quantity .form-control { | ||||
border-right: 0px none; | border-right: 0px none; | ||||
padding-right: 4px; | padding-right: 4px; | ||||
} | } | ||||
/* line 477, ../sass/distribution/_index.scss */ | |||||
/* line 502, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-form-order table.table-products td.quantity .input-group-addon { | .distribution-index .modal-form-order table.table-products td.quantity .input-group-addon { | ||||
padding: 5px; | padding: 5px; | ||||
padding-left: 0px; | padding-left: 0px; | ||||
border-left: 0px none; | border-left: 0px none; | ||||
border-right: 0px none; | border-right: 0px none; | ||||
} | } | ||||
/* line 486, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-form-order table.table-products td.quantity-remaining { | |||||
text-align: right; | |||||
} | |||||
/* line 489, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-form-order table.table-products td.quantity-remaining.quantity-remaining, .distribution-index .modal-form-order table.table-products td.quantity-remaining.infinite { | |||||
color: #00A65A; | |||||
} | |||||
/* line 493, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-form-order table.table-products td.quantity-remaining.negative { | |||||
color: #DD4B39; | |||||
} | |||||
/* line 497, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-form-order table.table-products td.quantity-remaining.infinite, .distribution-index .modal-form-order table.table-products td.quantity-remaining.empty { | |||||
font-size: 18px; | |||||
} | |||||
/* line 504, ../sass/distribution/_index.scss */ | |||||
/* line 513, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-form-order .actions-form button { | .distribution-index .modal-form-order .actions-form button { | ||||
margin-left: 15px; | margin-left: 15px; | ||||
} | } | ||||
/* line 512, ../sass/distribution/_index.scss */ | |||||
/* line 521, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-payment .info-box .info-box-icon { | .distribution-index .modal-payment .info-box .info-box-icon { | ||||
width: 50px; | width: 50px; | ||||
} | } | ||||
/* line 515, ../sass/distribution/_index.scss */ | |||||
/* line 524, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-payment .info-box .info-box-icon i { | .distribution-index .modal-payment .info-box .info-box-icon i { | ||||
font-size: 30px; | font-size: 30px; | ||||
} | } | ||||
/* line 520, ../sass/distribution/_index.scss */ | |||||
/* line 529, ../sass/distribution/_index.scss */ | |||||
.distribution-index .modal-payment .info-box .info-box-content { | .distribution-index .modal-payment .info-box .info-box-content { | ||||
margin-left: 50px; | margin-left: 50px; | ||||
} | } | ||||
.user-update .panel-point-sales label.control-label { | .user-update .panel-point-sales label.control-label { | ||||
display: none; | display: none; | ||||
} | } | ||||
/* line 18, ../sass/user/_form.scss */ | |||||
/* line 16, ../sass/user/_form.scss */ | |||||
.user-create .panel-point-sales .field-user-exclusive_access_selected_points_sale label.control-label, | |||||
.user-update .panel-point-sales .field-user-exclusive_access_selected_points_sale label.control-label { | |||||
display: block; | |||||
} | |||||
/* line 22, ../sass/user/_form.scss */ | |||||
.user-create .panel-user-groups label.control-label, | .user-create .panel-user-groups label.control-label, | ||||
.user-update .panel-user-groups label.control-label { | .user-update .panel-user-groups label.control-label { | ||||
display: none; | display: none; | ||||
} | } | ||||
/* line 25, ../sass/user/_form.scss */ | |||||
/* line 29, ../sass/user/_form.scss */ | |||||
.user-create #user-points_sale label, | .user-create #user-points_sale label, | ||||
.user-create #user-user_groups label, | .user-create #user-user_groups label, | ||||
.user-update #user-points_sale label, | .user-update #user-points_sale label, | ||||
padding: 5px 10px; | padding: 5px 10px; | ||||
border: solid 1px #e0e0e0; | border: solid 1px #e0e0e0; | ||||
} | } | ||||
/* line 33, ../sass/user/_form.scss */ | |||||
/* line 37, ../sass/user/_form.scss */ | |||||
.user-create #user-points_sale label .form-control, | .user-create #user-points_sale label .form-control, | ||||
.user-create #user-user_groups label .form-control, | .user-create #user-user_groups label .form-control, | ||||
.user-update #user-points_sale label .form-control, | .user-update #user-points_sale label .form-control, | ||||
margin-top: 0px; | margin-top: 0px; | ||||
} | } | ||||
/* line 4, ../sass/automatic-email/_form.scss */ | |||||
.automatic-email-form form label { | |||||
display: block; | |||||
} | |||||
/** | /** | ||||
Copyright Souke (2018) | Copyright Souke (2018) | ||||
$(document).ready(function () { | $(document).ready(function () { | ||||
opendistrib_datepicker(); | opendistrib_datepicker(); | ||||
opendistrib_popover(); | opendistrib_popover(); | ||||
opendistrib_commandeauto(); | |||||
opendistrib_points_vente_acces(); | opendistrib_points_vente_acces(); | ||||
opendistrib_tooltip(); | opendistrib_tooltip(); | ||||
opendistrib_ordre_produits(); | opendistrib_ordre_produits(); | ||||
opendistrib_gridview_pagesize(); | opendistrib_gridview_pagesize(); | ||||
opendistrib_producers_admin(); | opendistrib_producers_admin(); | ||||
opendistrib_user_form(); | opendistrib_user_form(); | ||||
opendistrib_user_credit(); | |||||
opendistrib_features_index(); | opendistrib_features_index(); | ||||
opendistrib_point_sale_form(); | opendistrib_point_sale_form(); | ||||
opendistrib_check_all_checkboxes(); | opendistrib_check_all_checkboxes(); | ||||
opendistrib_sponsorship(); | opendistrib_sponsorship(); | ||||
}); | }); | ||||
function label_unit_reference(unit) { | |||||
if(unit == 'piece') { | |||||
return 'p.'; | |||||
} | |||||
else if(unit == 'g' || unit == 'kg') { | |||||
return 'kg'; | |||||
} | |||||
else { | |||||
return 'litre(s)'; | |||||
} | |||||
} | |||||
function opendistrib_sponsorship() { | function opendistrib_sponsorship() { | ||||
$('#sponsorship-link-copy').click(function() { | $('#sponsorship-link-copy').click(function() { | ||||
navigator.clipboard.writeText($(this).attr('href')); | navigator.clipboard.writeText($(this).attr('href')); | ||||
} | } | ||||
} | } | ||||
function opendistrib_user_credit() { | |||||
if($('body.user-credit').length) { | |||||
$('#creditform-amount').focus(); | |||||
} | |||||
} | |||||
function opendistrib_producers_admin() { | function opendistrib_producers_admin() { | ||||
$('.producer-admin-index .btn-alwaysdata, .producer-admin-index .btn-dolibarr').click(function () { | $('.producer-admin-index .btn-alwaysdata, .producer-admin-index .btn-dolibarr').click(function () { | ||||
var $button = $(this); | var $button = $(this); | ||||
} | } | ||||
} | } | ||||
function opendistrib_commandeauto() { | |||||
$('#subscriptionform-date_begin, #subscriptionform-date_end').datepicker(); | |||||
} | |||||
function opendistrib_sortable_list(element_selector, button_selector, route_ajax) { | function opendistrib_sortable_list(element_selector, button_selector, route_ajax) { | ||||
var fixHelper = function (e, ui) { | var fixHelper = function (e, ui) { | ||||
ui.children().each(function () { | ui.children().each(function () { | ||||
} | } | ||||
function opendistrib_datepicker() { | function opendistrib_datepicker() { | ||||
$('#subscriptionform-date_begin, #subscriptionform-date_end').datepicker(); | |||||
$('input.datepicker').datepicker({dateFormat: 'dd/mm/yy'}); | $('input.datepicker').datepicker({dateFormat: 'dd/mm/yy'}); | ||||
} | } | ||||
} | } | ||||
}); | }); | ||||
}, | }, | ||||
labelUnitReference: function(unit) { | |||||
return label_unit_reference(unit); | |||||
}, | |||||
getProductQuantityRemainingGlobal: function(product) { | |||||
var app = this; | |||||
var productQuantityRemaining = product.quantity_remaining; | |||||
// format | |||||
if (productQuantityRemaining && product.unit != 'piece') { | |||||
productQuantityRemaining = productQuantityRemaining.toFixed(2); | |||||
} | |||||
return productQuantityRemaining; | |||||
}, | |||||
initCountActiveProducts: function () { | initCountActiveProducts: function () { | ||||
this.countActiveProducts = 0; | this.countActiveProducts = 0; | ||||
for (var i = 0; i < this.products.length; i++) { | for (var i = 0; i < this.products.length; i++) { | ||||
this.init(); | this.init(); | ||||
}, | }, | ||||
productQuantityMaxChange: function (event) { | productQuantityMaxChange: function (event) { | ||||
var app = this; | |||||
var quantityMax = event.currentTarget.value; | var quantityMax = event.currentTarget.value; | ||||
axios.get("ajax-process-product-quantity-max", { | axios.get("ajax-process-product-quantity-max", { | ||||
params: { | params: { | ||||
} | } | ||||
}) | }) | ||||
.then(function (response) { | .then(function (response) { | ||||
app.init(app.idActivePointSale); | |||||
}); | }); | ||||
}, | }, | ||||
productActiveClick: function (event) { | productActiveClick: function (event) { | ||||
return false; | return false; | ||||
}, | }, | ||||
isProductMaximumQuantityExceeded: function (product) { | isProductMaximumQuantityExceeded: function (product) { | ||||
return | |||||
this.getProductDistribution(product) | |||||
&& this.getProductDistribution(product).quantity_max | |||||
&& product.quantity_ordered | |||||
&& product.quantity_ordered > this.getProductDistribution(product).quantity_max; | |||||
return product.quantity_remaining | |||||
&& product.quantity_remaining < 0; | |||||
}, | }, | ||||
pointSaleActiveClick: function (event) { | pointSaleActiveClick: function (event) { | ||||
var idPointSale = event.currentTarget.getAttribute('data-id-point-sale'); | var idPointSale = event.currentTarget.getAttribute('data-id-point-sale'); | ||||
}, | }, | ||||
updateOrderFromUrl: function () { | updateOrderFromUrl: function () { | ||||
this.initModalFormOrder(); | this.initModalFormOrder(); | ||||
this.updateProductOrderPrices(false); | |||||
this.updateProductOrders(false); | |||||
}, | }, | ||||
updateOrderClick: function (event) { | updateOrderClick: function (event) { | ||||
var idOrder = event.currentTarget.getAttribute('data-id-order'); | var idOrder = event.currentTarget.getAttribute('data-id-order'); | ||||
this.idOrderUpdate = idOrder; | this.idOrderUpdate = idOrder; | ||||
this.showModalFormOrderUpdate = true; | this.showModalFormOrderUpdate = true; | ||||
this.initModalFormOrder(); | this.initModalFormOrder(); | ||||
this.updateProductOrderPrices(false); | |||||
this.updateProductOrders(false); | |||||
}, | }, | ||||
openModalFormOrderCreate: function () { | openModalFormOrderCreate: function () { | ||||
this.showModalFormOrderCreate = true; | this.showModalFormOrderCreate = true; | ||||
this.initModalFormOrder(); | this.initModalFormOrder(); | ||||
this.updateProductOrderPrices(false); | |||||
this.updateProductOrders(false); | |||||
}, | }, | ||||
initModalFormOrder: function () { | initModalFormOrder: function () { | ||||
var app = this; | var app = this; | ||||
app.init(app.idActivePointSale); | app.init(app.idActivePointSale); | ||||
}); | }); | ||||
}, | }, | ||||
updateProductOrderPrices: function (updatePricesOnUpdateOrder) { | |||||
getProductOrderArrayRequest: function (order) { | |||||
var productOrderArrayRequest = {}; | |||||
for (var key in order.productOrder) { | |||||
productOrderArrayRequest[key] = { | |||||
quantity: order.productOrder[key].quantity, | |||||
unit: order.productOrder[key].unit, | |||||
price: order.productOrder[key].price, | |||||
invoice_price: order.productOrder[key].invoice_price | |||||
}; | |||||
} | |||||
return JSON.stringify(productOrderArrayRequest); | |||||
}, | |||||
updateProductOrders: function (updatePricesOnUpdateOrder) { | |||||
var app = this; | var app = this; | ||||
app.loadingUpdateProductOrder = true; | app.loadingUpdateProductOrder = true; | ||||
var order = null; | var order = null; | ||||
idDistribution: app.distribution.id, | idDistribution: app.distribution.id, | ||||
idUser: order.id_user, | idUser: order.id_user, | ||||
idPointSale: order.id_point_sale, | idPointSale: order.id_point_sale, | ||||
idOrder: order.id | |||||
idOrder: order.id, | |||||
productOrderFormArray: app.getProductOrderArrayRequest(order) | |||||
} | } | ||||
}) | }) | ||||
.then(function (response) { | .then(function (response) { | ||||
for (idProduct in response.data) { | for (idProduct in response.data) { | ||||
if (app.showModalFormOrderCreate) { | if (app.showModalFormOrderCreate) { | ||||
Vue.set(app.orderCreate.productOrder[idProduct], 'quantity_remaining', response.data[idProduct].quantity_remaining); | |||||
Vue.set(app.orderCreate.productOrder[idProduct], 'prices', response.data[idProduct].prices); | Vue.set(app.orderCreate.productOrder[idProduct], 'prices', response.data[idProduct].prices); | ||||
Vue.set(app.orderCreate.productOrder[idProduct], 'active', response.data[idProduct].active); | Vue.set(app.orderCreate.productOrder[idProduct], 'active', response.data[idProduct].active); | ||||
Vue.set(app.orderCreate.productOrder[idProduct], 'price', app.getBestProductPrice(app.orderCreate, idProduct, app.orderCreate.productOrder[idProduct].quantity, false)); | Vue.set(app.orderCreate.productOrder[idProduct], 'price', app.getBestProductPrice(app.orderCreate, idProduct, app.orderCreate.productOrder[idProduct].quantity, false)); | ||||
if (app.showModalFormOrderUpdate && app.idOrderUpdate) { | if (app.showModalFormOrderUpdate && app.idOrderUpdate) { | ||||
for (keyOrderUpdate in app.ordersUpdate) { | for (keyOrderUpdate in app.ordersUpdate) { | ||||
if (order.id == app.idOrderUpdate) { | if (order.id == app.idOrderUpdate) { | ||||
Vue.set(app.ordersUpdate[keyOrderUpdate].productOrder[idProduct], 'quantity_remaining', response.data[idProduct].quantity_remaining); | |||||
Vue.set(app.ordersUpdate[keyOrderUpdate].productOrder[idProduct], 'prices', response.data[idProduct].prices); | Vue.set(app.ordersUpdate[keyOrderUpdate].productOrder[idProduct], 'prices', response.data[idProduct].prices); | ||||
Vue.set(app.ordersUpdate[keyOrderUpdate].productOrder[idProduct], 'active', response.data[idProduct].active); | Vue.set(app.ordersUpdate[keyOrderUpdate].productOrder[idProduct], 'active', response.data[idProduct].active); | ||||
Vue.set(app.ordersUpdate[keyOrderUpdate].productOrder[idProduct], 'invoice_price', response.data[idProduct].invoice_price); | Vue.set(app.ordersUpdate[keyOrderUpdate].productOrder[idProduct], 'invoice_price', response.data[idProduct].invoice_price); | ||||
} | } | ||||
}) | }) | ||||
.then(function (response) { | .then(function (response) { | ||||
app.updateProductOrderPrices(false); | |||||
app.updateProductOrders(false); | |||||
appAlerts.alert('info', 'Prix facturés réinitialisés.'); | appAlerts.alert('info', 'Prix facturés réinitialisés.'); | ||||
}); | }); | ||||
} | } | ||||
} | } | ||||
}, | }, | ||||
methods: { | methods: { | ||||
labelUnitReference: function(unit) { | |||||
return label_unit_reference(unit); | |||||
}, | |||||
checkForm: function () { | checkForm: function () { | ||||
this.errors = []; | this.errors = []; | ||||
Vue.set(this.order.productOrder[id_product], 'price', app.getBestProductPrice(this.order, id_product, theQuantity, false)); | Vue.set(this.order.productOrder[id_product], 'price', app.getBestProductPrice(this.order, id_product, theQuantity, false)); | ||||
Vue.set(this.order.productOrder[id_product], 'price_with_tax', app.getBestProductPrice(this.order, id_product, theQuantity, true)); | Vue.set(this.order.productOrder[id_product], 'price_with_tax', app.getBestProductPrice(this.order, id_product, theQuantity, true)); | ||||
} | } | ||||
this.updateProductOrders(false); | |||||
}, | }, | ||||
getProduct: function (idProduct) { | getProduct: function (idProduct) { | ||||
for (var i = 0; i < this.products.length; i++) { | for (var i = 0; i < this.products.length; i++) { | ||||
if (app.idActivePointSale == 0) { | if (app.idActivePointSale == 0) { | ||||
app.order.id_point_sale = response.data.id_favorite_point_sale; | app.order.id_point_sale = response.data.id_favorite_point_sale; | ||||
} | } | ||||
app.updateProductOrderPrices(true); | |||||
app.updateProductOrders(true); | |||||
}); | }); | ||||
}, | }, | ||||
pointSaleChange: function (event) { | pointSaleChange: function (event) { | ||||
this.updateProductOrderPrices(true); | |||||
this.updateProductOrders(true); | |||||
}, | }, | ||||
updateProductOrderPrices: function (updateProductOrderPrices) { | |||||
this.$emit('updateproductorderprices', updateProductOrderPrices); | |||||
updateProductOrders: function (updateProductOrders) { | |||||
this.$emit('updateproductorders', updateProductOrders); | |||||
}, | }, | ||||
updateInvoicePrices: function () { | updateInvoicePrices: function () { | ||||
this.$emit('updateinvoiceprices'); | this.$emit('updateinvoiceprices'); | ||||
} | } | ||||
return productQuantityOrder; | return productQuantityOrder; | ||||
}, | }, | ||||
getProductQuantityRemaining: function (product) { | |||||
var productQuantityRemaining = null; | |||||
var productQuantityMax = this.getProductQuantityMax(product); | |||||
var productQuantityOrder = this.getProductQuantityOrder(product); | |||||
if(productQuantityMax) { | |||||
productQuantityRemaining = productQuantityMax - productQuantityOrder; | |||||
} | |||||
getProductQuantityRemaining: function (order, product) { | |||||
var productQuantityRemaining = order.productOrder[product.id].quantity_remaining; | |||||
// format | // format | ||||
if (productQuantityRemaining && product.unit != 'piece') { | if (productQuantityRemaining && product.unit != 'piece') { |
.automatic-email-form { | |||||
form { | |||||
label { | |||||
display: block; | |||||
} | |||||
} | |||||
} |
} | } | ||||
} | } | ||||
table td.quantity-remaining { | |||||
text-align: right; | |||||
.has-quantity, .infinite { | |||||
color: #00A65A; | |||||
} | |||||
.negative { | |||||
color: #DD4B39; | |||||
} | |||||
.infinite, .empty { | |||||
font-size: 18px; | |||||
} | |||||
} | |||||
#products { | #products { | ||||
td.quantities { | td.quantities { | ||||
width: 100px; | width: 100px; | ||||
text-align: center; | text-align: center; | ||||
min-width: 50px; | min-width: 50px; | ||||
} | } | ||||
.limit-quantity-accessories { | |||||
margin-top: 7px; | |||||
font-size: 12px; | |||||
.quantity { | |||||
font-weight: bold; | |||||
} | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } | ||||
border-right: 0px none; | border-right: 0px none; | ||||
} | } | ||||
} | } | ||||
td.quantity-remaining { | |||||
text-align: right; | |||||
&.quantity-remaining, &.infinite { | |||||
color: #00A65A; | |||||
} | |||||
&.negative { | |||||
color: #DD4B39; | |||||
} | |||||
&.infinite, &.empty { | |||||
font-size: 18px; | |||||
} | |||||
} | |||||
} | } | ||||
.actions-form { | .actions-form { |
@import "feature-admin/_index.scss"; | @import "feature-admin/_index.scss"; | ||||
@import "setting/_form.scss"; | @import "setting/_form.scss"; | ||||
@import "dashboard-admin/_index.scss" ; | @import "dashboard-admin/_index.scss" ; | ||||
@import "automatic-email/_form.scss" ; | |||||
@import "_responsive.scss" ; | @import "_responsive.scss" ; |
label.control-label { | label.control-label { | ||||
display: none; | display: none; | ||||
} | } | ||||
.field-user-exclusive_access_selected_points_sale label.control-label { | |||||
display: block; | |||||
} | |||||
} | } | ||||
.panel-user-groups { | .panel-user-groups { |
<?php | |||||
namespace common\components; | |||||
class ActiveDataProvider extends \yii\data\ActiveDataProvider | |||||
{ | |||||
public function filterByCallback($callback) | |||||
{ | |||||
$filtered_models = $filtered_keys = []; | |||||
// la pagination ne fonctionne pas avec ce système de filtre : solution alternative sans pagination | |||||
// @TODO : faire en sorte que la pagination fonctionne avec les filtres par callback | |||||
$this->pagination = false; | |||||
$have_been_filtered = false; | |||||
$this->prepare(true); // force read of next page | |||||
$non_filtered_models = $this->getModels(); | |||||
foreach($non_filtered_models as $model) { | |||||
$filterModel = $callback($model); | |||||
if($filterModel) { | |||||
$have_been_filtered = true; | |||||
$this->setTotalCount($this->getTotalCount() - 1); | |||||
} | |||||
else { | |||||
$filtered_models[] = $model; | |||||
$filtered_keys[] = $model->id; | |||||
} | |||||
} | |||||
if($have_been_filtered) { | |||||
$this->setModels($filtered_models); | |||||
$this->setKeys($filtered_keys); | |||||
} | |||||
} | |||||
} |
namespace common\components\BulkMailer; | namespace common\components\BulkMailer; | ||||
use domain\Communication\Email\Email; | |||||
use domain\User\User\UserSolver; | use domain\User\User\UserSolver; | ||||
use GuzzleHttp\Client; | use GuzzleHttp\Client; | ||||
use Psr\Http\Message\ResponseInterface; | use Psr\Http\Message\ResponseInterface; | ||||
class BulkMailerBrevo implements BulkMailerInterface | class BulkMailerBrevo implements BulkMailerInterface | ||||
{ | { | ||||
public function sendEmails(array $contactsArray, string $fromName, string $fromEmail, string $subject, string $htmlContent, string $textContent = null) | |||||
public function sendEmail(Email $email, array $usersArray) | |||||
{ | { | ||||
$userSolver = UserSolver::getInstance(); | $userSolver = UserSolver::getInstance(); | ||||
$client = new Client(); | $client = new Client(); | ||||
$data = [ | $data = [ | ||||
'sender' => [ | 'sender' => [ | ||||
'name' => $fromName, | |||||
'email' => $fromEmail | |||||
'name' => $email->getFromName(), | |||||
'email' => $email->getFromEmail() | |||||
], | ], | ||||
'bcc' => [], | 'bcc' => [], | ||||
'subject' => $subject, | |||||
'htmlContent' => $htmlContent | |||||
'subject' => $email->getSubject(), | |||||
'htmlContent' => $email->getHtmlContent() | |||||
] ; | ] ; | ||||
foreach($contactsArray as $user) { | |||||
foreach($usersArray as $user) { | |||||
$data['bcc'][] = [ | $data['bcc'][] = [ | ||||
'name' => $userSolver->getUsernameFromArray($user), | 'name' => $userSolver->getUsernameFromArray($user), | ||||
'email' => $user['email'] | 'email' => $user['email'] |
namespace common\components\BulkMailer; | namespace common\components\BulkMailer; | ||||
use domain\Communication\Email\Email; | |||||
interface BulkMailerInterface | interface BulkMailerInterface | ||||
{ | { | ||||
const MAILJET = 'mailjet'; | const MAILJET = 'mailjet'; | ||||
const BREVO = 'brevo'; | const BREVO = 'brevo'; | ||||
public function sendEmails(array $contactsArray, string $fromName, string $fromEmail, string $subject, string $htmlContent, string $textContent = null); | |||||
public function sendEmail(Email $email, array $usersArray); | |||||
} | } |
namespace common\components\BulkMailer; | namespace common\components\BulkMailer; | ||||
use common\helpers\Mailjet; | use common\helpers\Mailjet; | ||||
use domain\Communication\Email\Email; | |||||
use Mailjet\Client; | use Mailjet\Client; | ||||
class BulkMailerMailjet implements BulkMailerInterface | class BulkMailerMailjet implements BulkMailerInterface | ||||
{ | { | ||||
public function sendEmails(array $contactsArray, string $fromName, string $fromEmail, string $subject, string $htmlContent, string $textContent = null) | |||||
public function sendEmail(Email $email, array $usersArray) | |||||
{ | { | ||||
$client = new Client( | $client = new Client( | ||||
Mailjet::getApiKey('public'), | Mailjet::getApiKey('public'), | ||||
$data = ['Messages' => []] ; | $data = ['Messages' => []] ; | ||||
foreach($contactsArray as $user) { | |||||
foreach($usersArray as $user) { | |||||
$data['Messages'][] = [ | $data['Messages'][] = [ | ||||
'From' => [ | 'From' => [ | ||||
'Email' => $fromEmail, | |||||
'Name' => $fromName | |||||
'Email' => $email->getFromEmail(), | |||||
'Name' => $email->getFromName() | |||||
], | ], | ||||
'To' => [ | 'To' => [ | ||||
[ | [ | ||||
'Name' => $user['name'].' '.$user['lastname'] | 'Name' => $user['name'].' '.$user['lastname'] | ||||
] | ] | ||||
], | ], | ||||
'Subject' => $subject, | |||||
'HTMLPart' => $htmlContent, | |||||
'TextPart' => $textContent | |||||
'Subject' => $email->getSubject(), | |||||
'HTMLPart' => $email->getHtmlContent(), | |||||
'TextPart' => $email->getTextContent() | |||||
] ; | ] ; | ||||
if(count($data['Messages']) == 50) { | if(count($data['Messages']) == 50) { |
namespace common\components\BulkMailer; | namespace common\components\BulkMailer; | ||||
use domain\Communication\Email\Email; | |||||
use domain\Setting\AdminSettingBag; | use domain\Setting\AdminSettingBag; | ||||
use yii\base\ErrorException; | use yii\base\ErrorException; | ||||
} | } | ||||
} | } | ||||
public function sendEmails(array $contactsArray, string $fromName, string $fromEmail, string $subject, string $htmlContent, string $textContent = null) | |||||
public function sendEmail(Email $email, array $usersArray) | |||||
{ | { | ||||
$this->getBulkMailer()->sendEmails($contactsArray, $fromName, $fromEmail, $subject, $htmlContent, $textContent); | |||||
$this->getBulkMailer()->sendEmail($email, $usersArray); | |||||
} | } | ||||
} | } |
$this->getUserProducerModule(), | $this->getUserProducerModule(), | ||||
$this->getUserPointSaleModule(), | $this->getUserPointSaleModule(), | ||||
$this->getUserModule(), | $this->getUserModule(), | ||||
$this->getEmailModule(), | |||||
$this->getAutomaticEmailModule(), | |||||
$this->getUserMessageModule(), | $this->getUserMessageModule(), | ||||
$this->getPointSaleDistributionModule(), | $this->getPointSaleDistributionModule(), | ||||
$this->getProductAccessoryModule(), | $this->getProductAccessoryModule(), |
namespace common\components; | namespace common\components; | ||||
use domain\Communication\Email\EmailModule; | |||||
use domain\Config\TaxRate\TaxRateModule; | use domain\Config\TaxRate\TaxRateModule; | ||||
use domain\Config\Unit\UnitModule; | use domain\Config\Unit\UnitModule; | ||||
use domain\Distribution\Distribution\DistributionModule; | use domain\Distribution\Distribution\DistributionModule; | ||||
use domain\Document\Quotation\QuotationModule; | use domain\Document\Quotation\QuotationModule; | ||||
use domain\Feature\Feature\FeatureModule; | use domain\Feature\Feature\FeatureModule; | ||||
use domain\Feature\FeatureProducer\FeatureProducerModule; | use domain\Feature\FeatureProducer\FeatureProducerModule; | ||||
use domain\Communication\AutomaticEmail\AutomaticEmailModule; | |||||
use domain\Opinion\OpinionModule; | use domain\Opinion\OpinionModule; | ||||
use domain\Order\Order\OrderModule; | use domain\Order\Order\OrderModule; | ||||
use domain\Order\OrderStatus\OrderStatusModule; | use domain\Order\OrderStatus\OrderStatusModule; | ||||
trait BusinessLogicTrait | trait BusinessLogicTrait | ||||
{ | { | ||||
public function getEmailModule(): EmailModule | |||||
{ | |||||
return EmailModule::getInstance(); | |||||
} | |||||
public function getAutomaticEmailModule(): AutomaticEmailModule | |||||
{ | |||||
return AutomaticEmailModule::getInstance(); | |||||
} | |||||
public function getProductAccessoryModule(): ProductAccessoryModule | public function getProductAccessoryModule(): ProductAccessoryModule | ||||
{ | { | ||||
return ProductAccessoryModule::getInstance(); | return ProductAccessoryModule::getInstance(); |
<?php | |||||
namespace common\components; | |||||
class Date | |||||
{ | |||||
public static function getDaysOfWeekArray(): array | |||||
{ | |||||
return [ | |||||
1 => 'Lundi', | |||||
2 => 'Mardi', | |||||
3 => 'Mercredi', | |||||
4 => 'Jeudi', | |||||
5 => 'Vendredi', | |||||
6 => 'Samedi', | |||||
7 => 'Dimanche' | |||||
]; | |||||
} | |||||
public static function getDayOfWeekStringByNumber(int $dayOfWeekNumber): string | |||||
{ | |||||
$daysOfWeekArray = self::getDaysOfWeekArray(); | |||||
return $daysOfWeekArray[$dayOfWeekNumber]; | |||||
} | |||||
} |
{ | { | ||||
if ($this->_hostInfo === null) | if ($this->_hostInfo === null) | ||||
{ | { | ||||
$secure = Yii::$app->getRequest()->getIsSecureConnection(); | |||||
$secure = Yii::$app->getRequest()->isConsoleRequest ? false : Yii::$app->getRequest()->getIsSecureConnection(); | |||||
$http = $secure ? 'https' : 'http'; | $http = $secure ? 'https' : 'http'; | ||||
if (isset($_SERVER['HTTP_HOST'])) { | if (isset($_SERVER['HTTP_HOST'])) { |
*/ | */ | ||||
return [ | return [ | ||||
'version' => '24.6.D', | |||||
'version' => '24.7.A', | |||||
'maintenanceMode' => false, | 'maintenanceMode' => false, | ||||
'siteName' => 'Souke', | 'siteName' => 'Souke', | ||||
'tinyMcePlugins' => 'preview searchreplace autolink autosave save directionality code visualblocks visualchars fullscreen image link lists wordcount help', | 'tinyMcePlugins' => 'preview searchreplace autolink autosave save directionality code visualblocks visualchars fullscreen image link lists wordcount help', |
"[Administration] Utilisateur > Créer (en arrivant de la création d'une commande) : retour automatique à la création de la commande", | "[Administration] Utilisateur > Créer (en arrivant de la création d'une commande) : retour automatique à la création de la commande", | ||||
], | ], | ||||
[ | [ | ||||
"[Administration] Tableau de bord : corectif affichage des commandes modifiées issues des abonnements" | |||||
"[Administration] Tableau de bord : correctif affichage des commandes modifiées issues des abonnements" | |||||
] | ] | ||||
], | ], | ||||
[ | [ |
<?php | |||||
require_once dirname(__FILE__).'/_macros.php'; | |||||
version( | |||||
'01/07/2024', | |||||
[ | |||||
[ | |||||
"Gestion des accessoires produits (module payant) : possibilité de limiter les quantités de produits commandables en fonction des quantités d'accessoires disponibles (exemple : moules)", | |||||
"Système de parrainage entre producteurs (voir dans 'Parrainage')", | |||||
"[Administration] Statistiques > Export paiements : export CSV des paiements sur une période donnée", | |||||
"Utilisateurs : accès exclusif à certains points de vente (Profil utilisateur > Points de vente : champs 'Accès exclusif aux points de vente sélectionnés')", | |||||
], | |||||
[ | |||||
"[Administration] Utilisateurs > Cagnotte : curseur placé automatiquement dans le champs 'Montant'" | |||||
] | |||||
], | |||||
[ | |||||
[ | |||||
], | |||||
[ | |||||
"[Administration] Déliverabilité emails : ajout colonne 'Note emails'" | |||||
] | |||||
], | |||||
$userCurrent | |||||
); | |||||
?> |
<?php | |||||
namespace console\commands; | |||||
use domain\Communication\AutomaticEmail\AutomaticEmailModule; | |||||
use domain\Communication\Email\EmailModule; | |||||
use domain\Producer\Producer\ProducerModule; | |||||
use yii\console\Controller; | |||||
class AutomaticEmailController extends Controller | |||||
{ | |||||
// ./yii automatic-email/send | |||||
public function actionSend() | |||||
{ | |||||
$automaticEmailModule = AutomaticEmailModule::getInstance(); | |||||
$producerModule = ProducerModule::getInstance(); | |||||
$emailModule = EmailModule::getInstance(); | |||||
$producersArray = $producerModule->getRepository()->findProducers(); | |||||
foreach($producersArray as $producer) { | |||||
\Yii::$app->logic->setProducerContext($producer); | |||||
$automaticEmailsArray = $automaticEmailModule->getRepository()->findAutomaticEmails(); | |||||
foreach($automaticEmailsArray as $automaticEmail) { | |||||
$distribution = $automaticEmailModule->getResolver()->getMatchedDistribution($automaticEmail); | |||||
if($distribution) { | |||||
$email = $automaticEmailModule->getManager()->createEmailFromAutomaticEmail($automaticEmail, $distribution); | |||||
$usersArray = $emailModule->getContactListResolver()->search($producer, $distribution); | |||||
$emailModule->getBulkMailer()->sendEmail($email, $usersArray); | |||||
echo 'Email automatique "'.$automaticEmail->getSubject().'" envoyé à '.count($usersArray)." utilisateur(s)\n"; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
?> |
termes. | termes. | ||||
*/ | */ | ||||
setlocale(LC_TIME, 'fr_FR.utf8','fra'); | |||||
$params = array_merge( | $params = array_merge( | ||||
require(__DIR__ . '/../../common/config/params.php'), | require(__DIR__ . '/../../common/config/params.php'), | ||||
require(__DIR__ . '/../../common/config/params-local.php'), | require(__DIR__ . '/../../common/config/params-local.php'), |
<?php | |||||
use yii\db\Migration; | |||||
use yii\db\Schema; | |||||
/** | |||||
* Class m240626_133528_add_column_user_exclusive_access_selected_points_sale | |||||
*/ | |||||
class m240626_133528_add_column_user_exclusive_access_selected_points_sale extends Migration | |||||
{ | |||||
/** | |||||
* {@inheritdoc} | |||||
*/ | |||||
public function safeUp() | |||||
{ | |||||
$this->addColumn('user_producer', 'exclusive_access_selected_points_sale', Schema::TYPE_BOOLEAN); | |||||
} | |||||
/** | |||||
* {@inheritdoc} | |||||
*/ | |||||
public function safeDown() | |||||
{ | |||||
$this->dropColumn('user_producer', 'exclusive_access_selected_points_sale'); | |||||
} | |||||
} |
<?php | |||||
use yii\db\Migration; | |||||
use yii\db\Schema; | |||||
/** | |||||
* Class m240627_064315_create_table_automatic_email | |||||
*/ | |||||
class m240627_064315_create_table_automatic_email extends Migration | |||||
{ | |||||
/** | |||||
* {@inheritdoc} | |||||
*/ | |||||
public function safeUp() | |||||
{ | |||||
$this->createTable('automatic_email', [ | |||||
'id' => 'pk', | |||||
'id_producer' => Schema::TYPE_INTEGER.' NOT NULL', | |||||
'day' => Schema::TYPE_INTEGER.' NOT NULL', | |||||
'delay_before_distribution' => Schema::TYPE_INTEGER.' NOT NULL', | |||||
'subject' => Schema::TYPE_STRING.' NOT NULL', | |||||
'message' => Schema::TYPE_TEXT.' NOT NULL', | |||||
'integrate_product_list' => Schema::TYPE_BOOLEAN, | |||||
'status' => Schema::TYPE_INTEGER.' NOT NULL', | |||||
]); | |||||
$this->addForeignKey('fk_automatic_email_id_producer', 'automatic_email', 'id_producer', 'producer', 'id'); | |||||
} | |||||
/** | |||||
* {@inheritdoc} | |||||
*/ | |||||
public function safeDown() | |||||
{ | |||||
$this->dropTable('automatic_email'); | |||||
} | |||||
} |
<?php | |||||
namespace domain\Communication\AutomaticEmail; | |||||
use common\components\ActiveRecordCommon; | |||||
use common\components\Date; | |||||
use domain\Producer\Producer\Producer; | |||||
use yii\db\ActiveQuery; | |||||
class AutomaticEmail extends ActiveRecordCommon | |||||
{ | |||||
public static function tableName() | |||||
{ | |||||
return 'automatic_email'; | |||||
} | |||||
public function rules() | |||||
{ | |||||
return [ | |||||
[['id_producer', 'day', 'subject', 'message', 'status'], 'required'], | |||||
[['subject', 'message'], 'string'], | |||||
[['id_producer', 'day', 'delay_before_distribution', 'status'], 'integer'], | |||||
[['integrate_product_list'], 'boolean'] | |||||
]; | |||||
} | |||||
public function attributeLabels() | |||||
{ | |||||
return [ | |||||
'id_producer' => 'Producteur', | |||||
'day' => 'Jour de distribution', | |||||
'delay_before_distribution' => 'Envoi du message', | |||||
'subject' => 'Sujet', | |||||
'message' => 'Message', | |||||
'integrate_product_list' => 'Intégrer la liste des produits au message', | |||||
'status' => 'Statut' | |||||
]; | |||||
} | |||||
/* Getters / Setters */ | |||||
public function getId(): ?int | |||||
{ | |||||
return $this->id; | |||||
} | |||||
public function getProducer(): Producer | |||||
{ | |||||
return $this->producerRelation; | |||||
} | |||||
public function setProducer(Producer $producer): self | |||||
{ | |||||
$this->populateFieldObject('id_producer', 'producerRelation', $producer); | |||||
return $this; | |||||
} | |||||
public function getDay(): int | |||||
{ | |||||
return $this->day; | |||||
} | |||||
public function setDay(int $day): self | |||||
{ | |||||
$this->day = $day; | |||||
return $this; | |||||
} | |||||
public function getDelayBeforeDistribution(): int | |||||
{ | |||||
return $this->delay_before_distribution; | |||||
} | |||||
public function setDelayBeforeDistribution(int $delayBeforeDistribution): self | |||||
{ | |||||
$this->delay_before_distribution = $delayBeforeDistribution; | |||||
return $this; | |||||
} | |||||
public function getSubject(): string | |||||
{ | |||||
return $this->subject; | |||||
} | |||||
public function setSubject(string $subject): self | |||||
{ | |||||
$this->subject = $subject; | |||||
return $this; | |||||
} | |||||
public function getMessage(): string | |||||
{ | |||||
return $this->message; | |||||
} | |||||
public function setMessage(string $message): self | |||||
{ | |||||
$this->message = $message; | |||||
return $this; | |||||
} | |||||
public function getIntegrateProductList(): ?bool | |||||
{ | |||||
return $this->integrate_product_list; | |||||
} | |||||
public function setIntegrateProductList(?bool $integrateProductList): self | |||||
{ | |||||
$this->integrate_product_list = $integrateProductList; | |||||
return $this; | |||||
} | |||||
public function getStatus(): int | |||||
{ | |||||
return $this->status; | |||||
} | |||||
public function setStatus(int $status): self | |||||
{ | |||||
$this->status = $status; | |||||
return $this; | |||||
} | |||||
/* Relations */ | |||||
public function getProducerRelation(): ActiveQuery | |||||
{ | |||||
return $this->hasOne(Producer::class, ['id' => 'id_producer']); | |||||
} | |||||
/* Méthodes */ | |||||
public function getDayAsString(): string | |||||
{ | |||||
return Date::getDayOfWeekStringByNumber($this->getDay()); | |||||
} | |||||
public function getDelayBeforeDistributionAsString(): string | |||||
{ | |||||
return $this->getDelayBeforeDistribution().' jour(s) avant'; | |||||
} | |||||
public function getStatusAsHtml(): string | |||||
{ | |||||
if($this->getStatus()) { | |||||
return '<span class="label label-success">Activé</span>'; | |||||
} | |||||
else { | |||||
return '<span class="label label-danger">Désactivé</span>'; | |||||
} | |||||
} | |||||
} |
<?php | |||||
namespace domain\Communication\AutomaticEmail; | |||||
use domain\_\AbstractBuilder; | |||||
use domain\_\StatusInterface; | |||||
use domain\Producer\Producer\Producer; | |||||
class AutomaticEmailBuilder extends AbstractBuilder | |||||
{ | |||||
public function instanciateAutomaticEmail(Producer $producer): AutomaticEmail | |||||
{ | |||||
$automaticEmail = new AutomaticEmail(); | |||||
$automaticEmail->setProducer($producer); | |||||
$automaticEmail->setDelayBeforeDistribution(2); | |||||
$automaticEmail->setStatus(StatusInterface::STATUS_ONLINE); | |||||
return $automaticEmail; | |||||
} | |||||
} |
<?php | |||||
namespace domain\Communication\AutomaticEmail; | |||||
use domain\_\AbstractDefinition; | |||||
class AutomaticEmailDefinition extends AbstractDefinition | |||||
{ | |||||
public function getEntityFqcn(): string | |||||
{ | |||||
return AutomaticEmail::class; | |||||
} | |||||
} |
<?php | |||||
namespace domain\Communication\AutomaticEmail; | |||||
use domain\_\AbstractManager; | |||||
use domain\Communication\Email\Email; | |||||
use domain\Communication\Email\EmailGenerator; | |||||
use domain\Distribution\Distribution\Distribution; | |||||
use domain\Producer\Producer\Producer; | |||||
class AutomaticEmailManager extends AbstractManager | |||||
{ | |||||
protected AutomaticEmailBuilder $automaticEmailBuilder; | |||||
protected EmailGenerator $emailGenerator; | |||||
public function loadDependencies(): void | |||||
{ | |||||
$this->automaticEmailBuilder = $this->loadService(AutomaticEmailBuilder::class); | |||||
$this->emailGenerator = $this->loadService(EmailGenerator::class); | |||||
} | |||||
public function createAutomaticEmail( | |||||
Producer $producer, | |||||
int $day, | |||||
int $delayBeforeDistribution, | |||||
string $subject, | |||||
string $message, | |||||
bool $integrateProductList = null | |||||
): AutomaticEmail | |||||
{ | |||||
$automaticEmail = $this->automaticEmailBuilder->instanciateAutomaticEmail($producer); | |||||
$automaticEmail->setDay($day); | |||||
$automaticEmail->setDelayBeforeDistribution($delayBeforeDistribution); | |||||
$automaticEmail->setSubject($subject); | |||||
$automaticEmail->setMessage($message); | |||||
$automaticEmail->setIntegrateProductList($integrateProductList); | |||||
$automaticEmail->save(); | |||||
return $automaticEmail; | |||||
} | |||||
public function createEmailFromAutomaticEmail(AutomaticEmail $automaticEmail, Distribution $distribution): Email | |||||
{ | |||||
return $this->emailGenerator->createEmail( | |||||
$automaticEmail->getSubject(), | |||||
$automaticEmail->getMessage(), | |||||
$automaticEmail->getIntegrateProductList(), | |||||
$automaticEmail->getProducer(), | |||||
$distribution | |||||
); | |||||
} | |||||
} |
<?php | |||||
namespace domain\Communication\AutomaticEmail; | |||||
use domain\_\AbstractModule; | |||||
class AutomaticEmailModule extends AbstractModule | |||||
{ | |||||
public function getServices(): array | |||||
{ | |||||
return [ | |||||
AutomaticEmailDefinition::class, | |||||
AutomaticEmailBuilder::class, | |||||
AutomaticEmailRepository::class, | |||||
AutomaticEmailResolver::class, | |||||
AutomaticEmailManager::class | |||||
]; | |||||
} | |||||
public function getDefinition(): AutomaticEmailDefinition | |||||
{ | |||||
return AutomaticEmailDefinition::getInstance(); | |||||
} | |||||
public function getBuilder(): AutomaticEmailBuilder | |||||
{ | |||||
return AutomaticEmailBuilder::getInstance(); | |||||
} | |||||
public function getRepository(): AutomaticEmailRepository | |||||
{ | |||||
return AutomaticEmailRepository::getInstance(); | |||||
} | |||||
public function getResolver(): AutomaticEmailResolver | |||||
{ | |||||
return AutomaticEmailResolver::getInstance(); | |||||
} | |||||
public function getManager(): AutomaticEmailManager | |||||
{ | |||||
return AutomaticEmailManager::getInstance(); | |||||
} | |||||
} |
<?php | |||||
namespace domain\Communication\AutomaticEmail; | |||||
use domain\_\AbstractRepository; | |||||
use domain\_\RepositoryQueryInterface; | |||||
class AutomaticEmailRepository extends AbstractRepository | |||||
{ | |||||
protected AutomaticEmailRepositoryQuery $query; | |||||
public function loadDependencies(): void | |||||
{ | |||||
$this->loadQuery(AutomaticEmailRepositoryQuery::class); | |||||
} | |||||
public function getDefaultOptionsSearch(): array | |||||
{ | |||||
return [ | |||||
self::WITH => [], | |||||
self::JOIN_WITH => [], | |||||
self::ORDER_BY => 'day ASC', | |||||
self::ATTRIBUTE_ID_PRODUCER => 'automatic_email.id_producer' | |||||
]; | |||||
} | |||||
public function findOneAutomaticEmailById(int $id): ?AutomaticEmail | |||||
{ | |||||
return $this->createDefaultQuery() | |||||
->filterById($id) | |||||
->findOne(); | |||||
} | |||||
public function queryAutomaticEmails(): RepositoryQueryInterface | |||||
{ | |||||
return $this->createDefaultQuery(); | |||||
} | |||||
public function findAutomaticEmails(): array | |||||
{ | |||||
return $this->queryAutomaticEmails()->find(); | |||||
} | |||||
} |
<?php | |||||
namespace domain\Communication\AutomaticEmail; | |||||
use domain\_\AbstractRepositoryQuery; | |||||
class AutomaticEmailRepositoryQuery extends AbstractRepositoryQuery | |||||
{ | |||||
protected AutomaticEmailDefinition $definition; | |||||
public function loadDependencies(): void | |||||
{ | |||||
$this->loadDefinition(AutomaticEmailDefinition::class); | |||||
} | |||||
} |
<?php | |||||
namespace domain\Communication\AutomaticEmail; | |||||
use domain\_\AbstractResolver; | |||||
use domain\Distribution\Distribution\Distribution; | |||||
use domain\Distribution\Distribution\DistributionRepository; | |||||
use domain\Producer\Producer\ProducerSolver; | |||||
class AutomaticEmailResolver extends AbstractResolver | |||||
{ | |||||
protected DistributionRepository $distributionRepository; | |||||
protected ProducerSolver $producerSolver; | |||||
public function loadDependencies(): void | |||||
{ | |||||
$this->distributionRepository = $this->loadService(DistributionRepository::class); | |||||
$this->producerSolver = $this->loadService(ProducerSolver::class); | |||||
} | |||||
public function getMatchedDistribution(AutomaticEmail $automaticEmail): ?Distribution | |||||
{ | |||||
$date = (new \DateTime('+'.$automaticEmail->getDelayBeforeDistribution().' days')); | |||||
$dateFormat = $date->format('Y-m-d'); | |||||
$distribution = $this->distributionRepository->findOneDistribution($dateFormat); | |||||
if($distribution | |||||
&& $distribution->active | |||||
&& $date->format('N') == $automaticEmail->getDay() | |||||
&& !$this->producerSolver->isOnLeavePeriodByDistribution($distribution)) { | |||||
return $distribution; | |||||
} | |||||
return null; | |||||
} | |||||
} |
<?php | |||||
namespace domain\Communication\Email; | |||||
use common\helpers\GlobalParam; | |||||
use domain\_\AbstractResolver; | |||||
use domain\Distribution\Distribution\Distribution; | |||||
use domain\PointSale\PointSale\PointSale; | |||||
use domain\Producer\Producer\Producer; | |||||
use domain\User\User\UserRepository; | |||||
class ContactListResolver extends AbstractResolver | |||||
{ | |||||
protected UserRepository $userRepository; | |||||
public function loadDependencies(): void | |||||
{ | |||||
$this->userRepository = $this->loadService(UserRepository::class); | |||||
} | |||||
public function search( | |||||
Producer $producer, | |||||
Distribution $distribution = null, | |||||
PointSale $pointSale = null, | |||||
bool $usersPointSaleLink = false, | |||||
bool $usersPointSaleHasOrder = false, | |||||
bool $isSubscriber = false, | |||||
bool $isInactive = false | |||||
): array | |||||
{ | |||||
if ($pointSale && !$usersPointSaleLink && !$usersPointSaleHasOrder) { | |||||
$usersPointSaleLink = 1; | |||||
} | |||||
if ($distribution && !$usersPointSaleLink && !$usersPointSaleHasOrder) { | |||||
$usersPointSaleLink = 1; | |||||
} | |||||
if($distribution) { | |||||
$users = []; | |||||
foreach($distribution->pointSaleDistribution as $pointSaleDistribution) { | |||||
if($pointSaleDistribution->delivery) { | |||||
$usersPointSaleArray = $this->userRepository->queryUsersBy([ | |||||
'id_producer' => $producer->id, | |||||
'id_point_sale' => $pointSaleDistribution->id_point_sale, | |||||
'users_point_sale_link' => $usersPointSaleLink, | |||||
'users_point_sale_has_order' => $usersPointSaleHasOrder, | |||||
'newsletter' => true | |||||
])->all(); | |||||
foreach($usersPointSaleArray as $user) { | |||||
$users[$user['id']] = $user; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
else { | |||||
$users = $this->userRepository->queryUsersBy([ | |||||
'id_producer' => $producer->id, | |||||
'id_point_sale' => $pointSale ? $pointSale->id : null, | |||||
'users_point_sale_link' => $usersPointSaleLink, | |||||
'users_point_sale_has_order' => $usersPointSaleHasOrder, | |||||
'subscribers' => $isSubscriber, | |||||
'inactive' => $isInactive, | |||||
'newsletter' => true | |||||
])->all(); | |||||
} | |||||
$usersArray = []; | |||||
foreach ($users as $user) { | |||||
if (isset($user['email']) && strlen($user['email']) > 0) { | |||||
if($producer->isDemoAccount()) { | |||||
$user['email'] = \Yii::$app->faker->email(); | |||||
} | |||||
$usersArray[] = $user; | |||||
} | |||||
} | |||||
return $usersArray; | |||||
} | |||||
} |
<?php | |||||
namespace domain\Communication\Email; | |||||
class Email | |||||
{ | |||||
protected string $fromName; | |||||
protected string $fromEmail; | |||||
protected string $subject; | |||||
protected string $htmlContent; | |||||
protected string $textContent; | |||||
public function getFromName(): string | |||||
{ | |||||
return $this->fromName; | |||||
} | |||||
public function setFromName(string $fromName): self | |||||
{ | |||||
$this->fromName = $fromName; | |||||
return $this; | |||||
} | |||||
public function getFromEmail(): string | |||||
{ | |||||
return $this->fromEmail; | |||||
} | |||||
public function setFromEmail(string $fromEmail): self | |||||
{ | |||||
$this->fromEmail = $fromEmail; | |||||
return $this; | |||||
} | |||||
public function getSubject(): string | |||||
{ | |||||
return $this->subject; | |||||
} | |||||
public function setSubject(string $subject): self | |||||
{ | |||||
$this->subject = $subject; | |||||
return $this; | |||||
} | |||||
public function getHtmlContent(): string | |||||
{ | |||||
return $this->htmlContent; | |||||
} | |||||
public function setHtmlContent(string $htmlContent): self | |||||
{ | |||||
$this->htmlContent = $htmlContent; | |||||
return $this; | |||||
} | |||||
public function getTextContent(): string | |||||
{ | |||||
return $this->textContent; | |||||
} | |||||
public function setTextContent(string $textContent): self | |||||
{ | |||||
$this->textContent = $textContent; | |||||
return $this; | |||||
} | |||||
} |
<?php | |||||
namespace domain\Communication\Email; | |||||
use domain\_\AbstractBuilder; | |||||
class EmailBuilder extends AbstractBuilder | |||||
{ | |||||
public function instanciateEmail( | |||||
string $fromName, | |||||
string $fromEmail, | |||||
string $subject, | |||||
string $htmlContent, | |||||
string $textContent | |||||
{ | |||||
$email = new Email(); | |||||
$email->setFromName($fromName); | |||||
$email->setFromEmail($fromEmail); | |||||
$email->setSubject($subject); | |||||
$email->setHtmlContent($htmlContent); | |||||
$email->setTextContent($textContent); | |||||
return $email; | |||||
} | |||||
} |
<?php | |||||
namespace domain\Communication\Email; | |||||
use common\helpers\Price; | |||||
use domain\_\AbstractResolver; | |||||
use domain\Config\Unit\UnitDefinition; | |||||
use domain\Distribution\Distribution\Distribution; | |||||
use domain\Distribution\Distribution\DistributionSolver; | |||||
use domain\Producer\Producer\Producer; | |||||
use domain\Producer\Producer\ProducerSolver; | |||||
use domain\Product\Product\Product; | |||||
use domain\Product\Product\ProductSolver; | |||||
use yii\helpers\Html; | |||||
class EmailGenerator extends AbstractResolver | |||||
{ | |||||
protected EmailBuilder $emailBuilder; | |||||
protected ProductSolver $productSolver; | |||||
protected DistributionSolver $distributionSolver; | |||||
protected ProducerSolver $producerSolver; | |||||
public function loadDependencies(): void | |||||
{ | |||||
$this->emailBuilder = $this->loadService(EmailBuilder::class); | |||||
$this->productSolver = $this->loadService(ProductSolver::class); | |||||
$this->distributionSolver = $this->loadService(DistributionSolver::class); | |||||
$this->producerSolver = $this->loadService(ProducerSolver::class); | |||||
} | |||||
public function createEmail( | |||||
string $subject, | |||||
string $message, | |||||
bool $integrateProductList, | |||||
Producer $producer = null, | |||||
Distribution $distribution = null | |||||
{ | |||||
$messageAutoText = '' ; | |||||
$messageAutoHtml = '' ; | |||||
$messageAutoHtml .= ' <style type="text/css"> | |||||
h1, h2, h3, h4, h5, h6 { | |||||
padding: 0px; | |||||
margin: 0px; | |||||
margin-bottom: 10px; | |||||
} | |||||
p { | |||||
margin: 0px; | |||||
padding: 0px; | |||||
margin-bottom: 5px; | |||||
} | |||||
</style>'; | |||||
if($distribution) { | |||||
$messageAutoText = ' | |||||
' ; | |||||
$messageAutoHtml .= '<br /><br />' ; | |||||
$linkOrder = $this->distributionSolver->getLinkOrder($distribution); | |||||
$dateOrder = strftime('%A %d %B %Y', strtotime($distribution->date)) ; | |||||
$messageAutoHtml .= '<a href="'.$linkOrder.'">Passer ma commande du '.$dateOrder.'</a>' ; | |||||
$messageAutoText .= 'Suivez ce lien pour passer votre commande du '.$dateOrder.' : | |||||
'.$linkOrder ; | |||||
if($integrateProductList) { | |||||
$productsArray = Product::find() | |||||
->where([ | |||||
'id_producer' => $producer->id, | |||||
]) | |||||
->andWhere('status >= :status') | |||||
->addParams(['status' => Product::STATUS_OFFLINE]) | |||||
->innerJoinWith(['productDistribution' => function($query) use($distribution) { | |||||
$query->andOnCondition([ | |||||
'product_distribution.id_distribution' => $distribution->id, | |||||
'product_distribution.active' => 1 | |||||
]); | |||||
}]) | |||||
->orderBy('product.name ASC') | |||||
->all(); | |||||
if(count($productsArray) > 0) { | |||||
$messageAutoHtml .= '<br /><br />Produits disponibles : <br /><ul>' ; | |||||
$messageAutoText .= ' | |||||
Produits disponibles : | |||||
' ; | |||||
foreach($productsArray as $product) { | |||||
$productDescription = $product->name ; | |||||
if(strlen($product->description)) { | |||||
$productDescription .= ' / '.$product->description ; | |||||
} | |||||
if($product->price) { | |||||
$productDescription .= ' / '.Price::format($this->productSolver->getPriceWithTax($product)) ; | |||||
$productDescription .= ' ('. $this->productSolver->strUnit($product, UnitDefinition::WORDING_UNIT).')' ; | |||||
} | |||||
$messageAutoText .= '- '.$productDescription.' | |||||
' ; | |||||
$messageAutoHtml .= '<li>'.Html::encode($productDescription).'</li>' ; | |||||
} | |||||
$messageAutoHtml .= '</ul>' ; | |||||
} | |||||
} | |||||
} | |||||
if($producer) { | |||||
$fromEmail = $this->producerSolver->getProducerEmailPlatform($producer) ; | |||||
$fromName = $producer->name ; | |||||
$linkProducer = 'https://'.$producer->slug.'.souke.fr'; | |||||
$linkUnsubscribe = \Yii::$app->urlManagerProducer->createAbsoluteUrl(['newsletter/unsubscribe', 'slug_producer' => $producer->slug]); | |||||
// Message inscription newsletter | |||||
$messageAutoText .= " | |||||
-- | |||||
Boutique : ".$linkProducer." | |||||
Me désinscrire : ".$linkUnsubscribe; | |||||
$messageAutoHtml .= "<br /><br />--<br>"; | |||||
$messageAutoHtml .= "Boutique : <a href=\"".$linkProducer."\">".$linkProducer."</a><br>"; | |||||
$messageAutoHtml .= "Me désinscrire : <a href=\"".$linkUnsubscribe."\">".$linkUnsubscribe."</a>"; | |||||
} | |||||
else { | |||||
$fromEmail = 'contact@souke.fr' ; | |||||
$fromName = 'Souke' ; | |||||
} | |||||
$htmlContent = $message.$messageAutoHtml; | |||||
$textContent = strip_tags($message).$messageAutoText; | |||||
return $this->emailBuilder->instanciateEmail( | |||||
$fromName, | |||||
$fromEmail, | |||||
$subject, | |||||
$htmlContent, | |||||
$textContent | |||||
); | |||||
} | |||||
} |
<?php | |||||
namespace domain\Communication\Email; | |||||
use common\components\BulkMailer\BulkMailerInterface; | |||||
use domain\_\AbstractService; | |||||
class EmailModule extends AbstractService | |||||
{ | |||||
public function getEntityFqcn(): string | |||||
{ | |||||
return ''; | |||||
} | |||||
public function getServices(): array | |||||
{ | |||||
return [ | |||||
EmailBuilder::class, | |||||
ContactListResolver::class, | |||||
EmailGenerator::class, | |||||
]; | |||||
} | |||||
public function getBuilder(): EmailBuilder | |||||
{ | |||||
return EmailBuilder::getInstance(); | |||||
} | |||||
public function getGenerator(): EmailGenerator | |||||
{ | |||||
return EmailGenerator::getInstance(); | |||||
} | |||||
public function getContactListResolver(): ContactListResolver | |||||
{ | |||||
return ContactListResolver::getInstance(); | |||||
} | |||||
public function getBulkMailer(): BulkMailerInterface | |||||
{ | |||||
return \Yii::$app->bulkMailer; | |||||
} | |||||
} |
namespace domain\Document\DeliveryNote; | namespace domain\Document\DeliveryNote; | ||||
use common\components\ActiveDataProvider; | |||||
use common\helpers\GlobalParam; | use common\helpers\GlobalParam; | ||||
use yii\data\ActiveDataProvider; | |||||
class DeliveryNoteSearch extends DeliveryNote | class DeliveryNoteSearch extends DeliveryNote | ||||
{ | { | ||||
$query->andFilterWhere(['like', 'distribution.date', date('Y-m-d', strtotime(str_replace('/', '-', $this->date_distribution)))]); | $query->andFilterWhere(['like', 'distribution.date', date('Y-m-d', strtotime(str_replace('/', '-', $this->date_distribution)))]); | ||||
} | } | ||||
// filtre facture (oui / non) | |||||
$models = $dataProvider->getModels(); | |||||
foreach($models as $index => $deliveryNote) { | |||||
if(!is_null($this->with_invoice) && is_numeric($this->with_invoice)) { | |||||
$invoice = $deliveryNoteModule->getSolver()->getInvoice($deliveryNote); | |||||
if(($this->with_invoice && !$invoice) || (!$this->with_invoice && $invoice)) { | |||||
unset($models[$index]); | |||||
// filtre avec ou sans facture | |||||
$withInvoice = $this->with_invoice; | |||||
if(is_numeric($withInvoice)) { | |||||
$dataProvider->filterByCallback(function($model) use ($withInvoice) { | |||||
$deliveryNoteModule = DeliveryNoteModule::getInstance(); | |||||
$filterModel = false; | |||||
if(is_numeric($withInvoice)) { | |||||
$invoice = $deliveryNoteModule->getSolver()->getInvoice($model); | |||||
if(($withInvoice && !$invoice) || (!$withInvoice && $invoice)) { | |||||
$filterModel = true; | |||||
} | |||||
} | } | ||||
} | |||||
return $filterModel; | |||||
}); | |||||
} | } | ||||
$dataProvider->setModels($models); | |||||
return $dataProvider; | return $dataProvider; | ||||
} | } |
namespace domain\Document\Invoice; | namespace domain\Document\Invoice; | ||||
use common\components\ActiveDataProvider; | |||||
use common\helpers\GlobalParam; | use common\helpers\GlobalParam; | ||||
use yii\data\ActiveDataProvider; | |||||
use yii\data\Sort; | use yii\data\Sort; | ||||
class InvoiceSearch extends Invoice | class InvoiceSearch extends Invoice | ||||
{ | { | ||||
var $paid = null; | |||||
var $is_paid; | |||||
var $username; | var $username; | ||||
public function rules() | public function rules() | ||||
{ | { | ||||
return [ | return [ | ||||
[['paid'], 'safe'], | |||||
[['is_sent'], 'boolean'], | |||||
[[], 'safe'], | |||||
[['is_sent', 'is_paid'], 'boolean'], | |||||
[['comment', 'address', 'status', 'username', 'date'], 'string'], | [['comment', 'address', 'status', 'username', 'date'], 'string'], | ||||
[['name', 'reference', 'username'], 'string', 'max' => 255], | [['name', 'reference', 'username'], 'string', 'max' => 255], | ||||
]; | ]; | ||||
->with($optionsSearch['with']) | ->with($optionsSearch['with']) | ||||
->joinWith($optionsSearch['join_with']) | ->joinWith($optionsSearch['join_with']) | ||||
->where(['invoice.id_producer' => GlobalParam::getCurrentProducerId()]) | ->where(['invoice.id_producer' => GlobalParam::getCurrentProducerId()]) | ||||
//->orderBy('invoice.status ASC, invoice.reference DESC') | |||||
->orderBy($sort->orders) | ->orderBy($sort->orders) | ||||
->groupBy('invoice.id'); | ->groupBy('invoice.id'); | ||||
} | } | ||||
// filtre envoyé | // filtre envoyé | ||||
if(!is_null($this->is_sent) && is_numeric($this->is_sent)) { | |||||
if(is_numeric($this->is_sent)) { | |||||
if($this->is_sent) { | if($this->is_sent) { | ||||
$query->andWhere(['invoice.is_sent' => 1]); | $query->andWhere(['invoice.is_sent' => 1]); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// filter payé / non payé | |||||
// @TODO : comprendre pourquoi la pagination ne suit pas | |||||
$models = $dataProvider->getModels(); | |||||
foreach($models as $index => $invoice) { | |||||
if(!is_null($this->paid) && is_numeric($this->paid)) { | |||||
$isInvoicePaid = $invoiceModule->getSolver()->isInvoicePaid($invoice); | |||||
if(($this->paid && !$isInvoicePaid) || (!$this->paid && $isInvoicePaid)) { | |||||
unset($models[$index]); | |||||
// filtre payé / non payé | |||||
$isPaid = $this->is_paid; | |||||
if(is_numeric($isPaid)) { | |||||
$dataProvider->filterByCallback(function($model) use ($isPaid) { | |||||
$filterModel = false; | |||||
$invoiceModule = InvoiceModule::getInstance(); | |||||
if(is_numeric($isPaid)) { | |||||
$isInvoicePaid = $invoiceModule->getSolver()->isInvoicePaid($model); | |||||
if(($isPaid && !$isInvoicePaid) || (!$isPaid && $isInvoicePaid)) { | |||||
$filterModel = true; | |||||
} | |||||
} | } | ||||
} | |||||
return $filterModel; | |||||
}); | |||||
} | } | ||||
$dataProvider->setModels($models); | |||||
return $dataProvider; | return $dataProvider; | ||||
} | } |
const ALIAS_SPONSORSHIP = 'sponsorship'; | const ALIAS_SPONSORSHIP = 'sponsorship'; | ||||
const ALIAS_BRIDGE_EVOLIZ = 'bridge_evoliz'; | const ALIAS_BRIDGE_EVOLIZ = 'bridge_evoliz'; | ||||
const ALIAS_PRODUCT_ACCESSORY = 'product_accessory'; | const ALIAS_PRODUCT_ACCESSORY = 'product_accessory'; | ||||
const ALIAS_FORUM = 'forum'; | |||||
const ALIAS_AUTOMATIC_EMAIL = 'automatic_email'; | |||||
/** | /** | ||||
* @inheritdoc | * @inheritdoc |
Feature::ALIAS_BRIDGE_SUMUP => "Pont vers SumUp", | Feature::ALIAS_BRIDGE_SUMUP => "Pont vers SumUp", | ||||
Feature::ALIAS_BRIDGE_EVOLIZ => "Pont vers Evoliz", | Feature::ALIAS_BRIDGE_EVOLIZ => "Pont vers Evoliz", | ||||
Feature::ALIAS_PRODUCT_ACCESSORY => 'Accessoires produits', | Feature::ALIAS_PRODUCT_ACCESSORY => 'Accessoires produits', | ||||
Feature::ALIAS_FORUM => 'Forum', | |||||
Feature::ALIAS_AUTOMATIC_EMAIL => 'Emails automatiques' | |||||
]; | ]; | ||||
} | } | ||||
} | } |
use domain\Producer\Producer\Producer; | use domain\Producer\Producer\Producer; | ||||
use domain\Producer\Producer\ProducerRepository; | use domain\Producer\Producer\ProducerRepository; | ||||
use domain\Producer\Producer\ProducerSolver; | use domain\Producer\Producer\ProducerSolver; | ||||
use domain\Product\Product\Product; | |||||
use domain\Product\Product\ProductRepository; | |||||
use domain\Product\Product\ProductSolver; | use domain\Product\Product\ProductSolver; | ||||
use domain\Subscription\Subscription\Subscription; | use domain\Subscription\Subscription\Subscription; | ||||
use domain\Subscription\Subscription\SubscriptionBuilder; | use domain\Subscription\Subscription\SubscriptionBuilder; | ||||
protected DocumentSolver $documentSolver; | protected DocumentSolver $documentSolver; | ||||
protected ProducerSolver $producerSolver; | protected ProducerSolver $producerSolver; | ||||
protected OrderStatusRepository $orderStatusRepository; | protected OrderStatusRepository $orderStatusRepository; | ||||
protected ProductRepository $productRepository; | |||||
public function loadDependencies(): void | public function loadDependencies(): void | ||||
{ | { | ||||
$this->documentSolver = $this->loadService(DocumentSolver::class); | $this->documentSolver = $this->loadService(DocumentSolver::class); | ||||
$this->producerSolver = $this->loadService(ProducerSolver::class); | $this->producerSolver = $this->loadService(ProducerSolver::class); | ||||
$this->orderStatusRepository = $this->loadService(OrderStatusRepository::class); | $this->orderStatusRepository = $this->loadService(OrderStatusRepository::class); | ||||
$this->productRepository = $this->loadService(ProductRepository::class); | |||||
} | } | ||||
public function instanciateOrder(Distribution $distribution): Order | public function instanciateOrder(Distribution $distribution): Order | ||||
return $order; | return $order; | ||||
} | } | ||||
public function instanciateOrderFromProductOrdersArray(array $productOrdersArray, Order $order = null): Order | |||||
{ | |||||
if(!$order) { | |||||
$order = new Order(); | |||||
$this->initOrderStatus($order); | |||||
} | |||||
$productOrderObjectArray = []; | |||||
foreach($productOrdersArray as $idProduct => $productOrder) { | |||||
if($productOrder['quantity']) { | |||||
$product = $this->productRepository->findOneProductById($idProduct); | |||||
$productOrderObject = $this->productOrderBuilder->instanciateProductOrder( | |||||
$order, | |||||
$product, | |||||
$productOrder['quantity'], | |||||
0 | |||||
); | |||||
$productOrderObjectArray[] = $productOrderObject; | |||||
} | |||||
} | |||||
$order->populateRelation('productOrder', $productOrderObjectArray); | |||||
return $order; | |||||
} | |||||
public function addOrUpdateOrIgnoreOrderFromArray(Order $orderOverride, array $ordersArray, bool $ignoreOrderCurrent = false): array | |||||
{ | |||||
$override = false; | |||||
foreach($ordersArray as $key => $order) { | |||||
if($order->id == $orderOverride->id) { | |||||
if($ignoreOrderCurrent) { | |||||
unset($ordersArray[$key]); | |||||
} | |||||
else { | |||||
$ordersArray[$key] = $orderOverride; | |||||
$override = true; | |||||
} | |||||
} | |||||
} | |||||
if(!$override && !$ignoreOrderCurrent) { | |||||
$ordersArray[] = $orderOverride; | |||||
} | |||||
return $ordersArray; | |||||
} | |||||
public function deleteProductOrderQuantity(Order $order, Product $product, float $quantity) | |||||
{ | |||||
foreach($order->productOrder as $productOrder) { | |||||
if($productOrder->id_product == $product->id) { | |||||
$productOrder->quantity -= $quantity; | |||||
} | |||||
} | |||||
} | |||||
public function initDateUpdate(Order $order) | public function initDateUpdate(Order $order) | ||||
{ | { | ||||
$order->date_update = date('Y-m-d H:i:s');; | $order->date_update = date('Y-m-d H:i:s');; |
use domain\Feature\Feature\FeatureChecker; | use domain\Feature\Feature\FeatureChecker; | ||||
use domain\Product\Accessory\Accessory; | use domain\Product\Accessory\Accessory; | ||||
use domain\Product\Product\Product; | use domain\Product\Product\Product; | ||||
use yii\base\ErrorException; | |||||
use domain\Product\Product\ProductSolver; | |||||
class OrderResolver extends AbstractResolver | class OrderResolver extends AbstractResolver | ||||
{ | { | ||||
protected ProductSolver $productSolver; | |||||
protected OrderSolver $orderSolver; | protected OrderSolver $orderSolver; | ||||
protected OrderRepository $orderRepository; | protected OrderRepository $orderRepository; | ||||
protected ProductDistributionRepository $productDistributionRepository; | protected ProductDistributionRepository $productDistributionRepository; | ||||
protected FeatureChecker $featureChecker; | protected FeatureChecker $featureChecker; | ||||
protected OrderBuilder $orderBuilder; | |||||
protected array $ordersArrayCachedByDistribution = []; | |||||
public function loadDependencies(): void | public function loadDependencies(): void | ||||
{ | { | ||||
$this->productSolver = $this->loadService(ProductSolver::class); | |||||
$this->orderSolver = $this->loadService(OrderSolver::class); | $this->orderSolver = $this->loadService(OrderSolver::class); | ||||
$this->orderRepository = $this->loadService(OrderRepository::class); | $this->orderRepository = $this->loadService(OrderRepository::class); | ||||
$this->productDistributionRepository = $this->loadService(ProductDistributionRepository::class); | $this->productDistributionRepository = $this->loadService(ProductDistributionRepository::class); | ||||
$this->featureChecker = $this->loadService(FeatureChecker::class); | $this->featureChecker = $this->loadService(FeatureChecker::class); | ||||
$this->orderBuilder = $this->loadService(OrderBuilder::class); | |||||
} | } | ||||
public function getProductQuantityByDistribution(Product $product, Distribution $distribution): float | |||||
public function getProductQuantityByDistribution( | |||||
Product $product, | |||||
Distribution $distribution, | |||||
bool $inNumberOfPieces = false, | |||||
Order $orderCurrent = null | |||||
): float | |||||
{ | { | ||||
$ordersArray = $this->orderRepository->findOrdersByDistribution($distribution); | |||||
return $this->orderSolver->getProductQuantity($product, $ordersArray); | |||||
if(!isset($this->ordersArrayCachedByDistribution[$distribution->id])) { | |||||
$this->ordersArrayCachedByDistribution[$distribution->id] = $this->orderRepository->findOrdersByDistribution($distribution); | |||||
} | |||||
$ordersArray = $this->ordersArrayCachedByDistribution[$distribution->id]; | |||||
if($orderCurrent) { | |||||
$ordersArray = $this->orderBuilder->addOrUpdateOrIgnoreOrderFromArray($orderCurrent, $ordersArray); | |||||
} | |||||
$productQuantity = $this->orderSolver->getProductQuantity($product, $ordersArray); | |||||
if($inNumberOfPieces) { | |||||
$productQuantity = $this->productSolver->getNumberOfPieces($productQuantity, $product); | |||||
} | |||||
return $productQuantity; | |||||
} | } | ||||
public function getSmallestQuantityAccessory(Product $product): ?int | public function getSmallestQuantityAccessory(Product $product): ?int | ||||
public function getProductQuantityMax(Product $product, Distribution $distribution): ?float | public function getProductQuantityMax(Product $product, Distribution $distribution): ?float | ||||
{ | { | ||||
$productDistribution = $this->productDistributionRepository->findOneProductDistribution($distribution, $product); | $productDistribution = $this->productDistributionRepository->findOneProductDistribution($distribution, $product); | ||||
// @TODO : gérer via une exception | |||||
if(!$productDistribution) { | if(!$productDistribution) { | ||||
return null; | return null; | ||||
} | } | ||||
if($this->featureChecker->isEnabled(Feature::ALIAS_PRODUCT_ACCESSORY)) { | if($this->featureChecker->isEnabled(Feature::ALIAS_PRODUCT_ACCESSORY)) { | ||||
$smallestQuantityAccessory = $this->getSmallestQuantityAccessory($product); | $smallestQuantityAccessory = $this->getSmallestQuantityAccessory($product); | ||||
if (!is_null($smallestQuantityAccessory)) { | if (!is_null($smallestQuantityAccessory)) { | ||||
$quantityMax = is_null($quantityMax) ? $smallestQuantityAccessory : min($quantityMax, $smallestQuantityAccessory); | |||||
$smallestQuantityAccessory = $this->productSolver->getWeightOrNumberOfPieces($smallestQuantityAccessory, $product); | |||||
$quantityMax = is_null($quantityMax) ? $smallestQuantityAccessory | |||||
: min($quantityMax, $smallestQuantityAccessory); | |||||
} | } | ||||
} | } | ||||
return $quantityMax; | return $quantityMax; | ||||
} | } | ||||
public function getQuantityOfAccessoryAvailableInDistribution(Accessory $accessory, Distribution $distribution): int | |||||
public function getProductQuantityMaxOrderable(Product $product, Distribution $distribution, Order $orderCurrent = null): ?float | |||||
{ | |||||
$productQuantity = $this->orderSolver->getProductQuantity($product, $orderCurrent ? [$orderCurrent] : []); | |||||
$productQuantityRemaining = $this->getProductQuantityRemaining($product, $distribution, $orderCurrent); | |||||
if(is_null($productQuantityRemaining)) { | |||||
return null; | |||||
} | |||||
return $productQuantity + $productQuantityRemaining; | |||||
} | |||||
public function getQuantityOfAccessoryAvailableInDistribution( | |||||
Accessory $accessory, | |||||
Distribution $distribution, | |||||
Order $orderCurrent = null | |||||
): int | |||||
{ | { | ||||
$quantityOfAccessoryUsed = 0; | $quantityOfAccessoryUsed = 0; | ||||
foreach($accessory->getProductAccessories() as $productAccessory) { | foreach($accessory->getProductAccessories() as $productAccessory) { | ||||
$quantityOfAccessoryUsed += $this->getProductQuantityByDistribution($productAccessory->getProduct(), $distribution); | |||||
$quantityOfAccessoryUsed += $this->getProductQuantityByDistribution( | |||||
$productAccessory->getProduct(), | |||||
$distribution, | |||||
true, | |||||
$orderCurrent | |||||
); | |||||
} | } | ||||
return $accessory->getQuantity() - $quantityOfAccessoryUsed; | return $accessory->getQuantity() - $quantityOfAccessoryUsed; | ||||
} | } | ||||
public function getSmallestQuantityAccessoryAvailable(Product $product, Distribution $distribution): ?int | |||||
public function getSmallestQuantityAccessoryAvailable( | |||||
Product $product, | |||||
Distribution $distribution, | |||||
Order $orderCurrent = null | |||||
): ?int | |||||
{ | { | ||||
$smallestQuantity = null; | $smallestQuantity = null; | ||||
foreach ($product->getProductAccessories() as $productAccessory) { | foreach ($product->getProductAccessories() as $productAccessory) { | ||||
$quantityAccessoryAvailableInDistribution = $this->getQuantityOfAccessoryAvailableInDistribution( | $quantityAccessoryAvailableInDistribution = $this->getQuantityOfAccessoryAvailableInDistribution( | ||||
$productAccessory->getAccessory(), | $productAccessory->getAccessory(), | ||||
$distribution | |||||
$distribution, | |||||
$orderCurrent | |||||
); | ); | ||||
$smallestQuantity = is_null($smallestQuantity) ? $quantityAccessoryAvailableInDistribution | $smallestQuantity = is_null($smallestQuantity) ? $quantityAccessoryAvailableInDistribution | ||||
: min($smallestQuantity, $quantityAccessoryAvailableInDistribution); | : min($smallestQuantity, $quantityAccessoryAvailableInDistribution); | ||||
return $smallestQuantity; | return $smallestQuantity; | ||||
} | } | ||||
public function getProductQuantityRemaining(Product $product, Distribution $distribution): ?float | |||||
public function getProductQuantityRemaining( | |||||
Product $product, | |||||
Distribution $distribution, | |||||
Order $orderCurrent = null | |||||
): ?float | |||||
{ | { | ||||
$productDistribution = $this->productDistributionRepository->findOneProductDistribution($distribution, $product); | $productDistribution = $this->productDistributionRepository->findOneProductDistribution($distribution, $product); | ||||
if(!$productDistribution) { | if(!$productDistribution) { | ||||
return null; | return null; | ||||
} | } | ||||
$quantityOrder = $this->getProductQuantityByDistribution($product, $distribution); | |||||
$quantityOrder = $this->getProductQuantityByDistribution( | |||||
$product, | |||||
$distribution, | |||||
false, | |||||
$orderCurrent | |||||
); | |||||
$quantityRemaining = is_null($productDistribution->quantity_max) ? null | $quantityRemaining = is_null($productDistribution->quantity_max) ? null | ||||
: ($productDistribution->quantity_max - $quantityOrder); | : ($productDistribution->quantity_max - $quantityOrder); | ||||
// Limitation par nombre d'accessoires disponibles | // Limitation par nombre d'accessoires disponibles | ||||
if($this->featureChecker->isEnabled(Feature::ALIAS_PRODUCT_ACCESSORY)) { | if($this->featureChecker->isEnabled(Feature::ALIAS_PRODUCT_ACCESSORY)) { | ||||
$smallestQuantityAccessoryAvailable = $this->getSmallestQuantityAccessoryAvailable($product, $distribution); | |||||
$smallestQuantityAccessoryAvailable = $this->getSmallestQuantityAccessoryAvailable( | |||||
$product, | |||||
$distribution, | |||||
$orderCurrent | |||||
); | |||||
if (!is_null($smallestQuantityAccessoryAvailable)) { | if (!is_null($smallestQuantityAccessoryAvailable)) { | ||||
$smallestQuantityAccessoryAvailable = $this->productSolver->getWeightOrNumberOfPieces($smallestQuantityAccessoryAvailable, $product); | |||||
$quantityRemaining = is_null($quantityRemaining) ? $smallestQuantityAccessoryAvailable | $quantityRemaining = is_null($quantityRemaining) ? $smallestQuantityAccessoryAvailable | ||||
: min($quantityRemaining, $smallestQuantityAccessoryAvailable); | : min($quantityRemaining, $smallestQuantityAccessoryAvailable); | ||||
} | } |
namespace domain\Producer\Producer; | namespace domain\Producer\Producer; | ||||
use common\helpers\GlobalParam; | use common\helpers\GlobalParam; | ||||
use domain\Distribution\Distribution\Distribution; | |||||
use domain\User\User\User; | use domain\User\User\User; | ||||
use domain\_\AbstractService; | use domain\_\AbstractService; | ||||
use domain\_\SolverInterface; | use domain\_\SolverInterface; | ||||
return $producer->option_leave_period_start && $producer->option_leave_period_end; | return $producer->option_leave_period_start && $producer->option_leave_period_end; | ||||
} | } | ||||
public function isOnLeavePeriodByDistribution(Distribution $distribution): bool | |||||
{ | |||||
return $this->isOnLeavePeriod($distribution->producer, \DateTime::createFromFormat('Y-m-d', $distribution->date)); | |||||
} | |||||
public function isOnLeavePeriod(Producer $producer, \DateTime $date = null): bool | public function isOnLeavePeriod(Producer $producer, \DateTime $date = null): bool | ||||
{ | { | ||||
if(!$date) { | if(!$date) { |
public function rules() | public function rules() | ||||
{ | { | ||||
return [ | return [ | ||||
[['name', 'id_producer'], 'required'], | |||||
[['name', 'id_producer', 'quantity'], 'required'], | |||||
[['name'], 'string', 'max' => 255], | [['name'], 'string', 'max' => 255], | ||||
[['quantity', 'id_producer'], 'integer'], | [['quantity', 'id_producer'], 'integer'], | ||||
[['selected_products_ids'], 'safe'], | [['selected_products_ids'], 'safe'], | ||||
return $this; | return $this; | ||||
} | } | ||||
public function getQuantity(): ?int | |||||
public function getQuantity(): int | |||||
{ | { | ||||
return $this->quantity; | return $this->quantity; | ||||
} | } | ||||
public function setQuantity(?int $quantity): self | |||||
public function setQuantity(int $quantity): self | |||||
{ | { | ||||
$this->quantity = $quantity; | $this->quantity = $quantity; | ||||
return $this; | return $this; |
$this->pointSaleSolver = $this->loadService(PointSaleSolver::class); | $this->pointSaleSolver = $this->loadService(PointSaleSolver::class); | ||||
} | } | ||||
public function getWeightOrNumberOfPieces(float $quantity, Product $product): float | |||||
{ | |||||
// Poids total | |||||
if($product->unit != 'piece') { | |||||
$quantity = ($quantity * $product->weight) / 1000; | |||||
} | |||||
return $quantity; | |||||
} | |||||
public function getNumberOfPieces(float $quantity, Product $product): int | |||||
{ | |||||
if($product->unit != 'piece') { | |||||
$quantity = $quantity / ($product->weight / 1000); | |||||
} | |||||
return $quantity; | |||||
} | |||||
public function getUnitCoefficient(Product $product): int | public function getUnitCoefficient(Product $product): int | ||||
{ | { | ||||
return $this->unitSolver->getUnitCoefficient($product->unit); | return $this->unitSolver->getUnitCoefficient($product->unit); |
var $send_mail_welcome; | var $send_mail_welcome; | ||||
var $trust_alert; | var $trust_alert; | ||||
var $trust_alert_comment; | var $trust_alert_comment; | ||||
var $exclusive_access_selected_points_sale; | |||||
/** | /** | ||||
* @inheritdoc | * @inheritdoc | ||||
[['no_mail', 'mail_distribution_monday', 'mail_distribution_tuesday', 'mail_distribution_wednesday', | [['no_mail', 'mail_distribution_monday', 'mail_distribution_tuesday', 'mail_distribution_wednesday', | ||||
'mail_distribution_thursday', 'mail_distribution_friday', 'mail_distribution_saturday', | 'mail_distribution_thursday', 'mail_distribution_friday', 'mail_distribution_saturday', | ||||
'mail_distribution_sunday', 'is_main_contact', 'newsletter', 'exclude_export_shopping_cart_labels', | 'mail_distribution_sunday', 'is_main_contact', 'newsletter', 'exclude_export_shopping_cart_labels', | ||||
'send_mail_welcome', 'trust_alert', 'newsletter_souke', 'problem_receiving_emails'], 'boolean'], | |||||
'send_mail_welcome', 'trust_alert', 'newsletter_souke', 'problem_receiving_emails', 'exclusive_access_selected_points_sale'], 'boolean'], | |||||
[['lastname', 'name', 'phone', 'address', 'type', 'name_legal_person', 'evoliz_code', 'trust_alert_comment', 'note_emails'], 'string'], | [['lastname', 'name', 'phone', 'address', 'type', 'name_legal_person', 'evoliz_code', 'trust_alert_comment', 'note_emails'], 'string'], | ||||
['lastname', 'verifyOneName', 'skipOnError' => false, 'skipOnEmpty' => false], | ['lastname', 'verifyOneName', 'skipOnError' => false, 'skipOnEmpty' => false], | ||||
[['email', 'email_sending_invoicing_documents'], 'email', 'message' => 'Cette adresse email n\'est pas valide'], | [['email', 'email_sending_invoicing_documents'], 'email', 'message' => 'Cette adresse email n\'est pas valide'], | ||||
'trust_alert_comment' => 'Commentaire', | 'trust_alert_comment' => 'Commentaire', | ||||
'newsletter_souke' => "S'abonner à l'infolettre de Souke", | 'newsletter_souke' => "S'abonner à l'infolettre de Souke", | ||||
'problem_receiving_emails' => "Rencontre des problèmes pour recevoir les emails", | 'problem_receiving_emails' => "Rencontre des problèmes pour recevoir les emails", | ||||
'note_emails' => "Note emails" | |||||
'note_emails' => "Note emails", | |||||
'exclusive_access_selected_points_sale' => "Accès exclusif aux points de vente sélectionnés" | |||||
]; | ]; | ||||
} | } | ||||
. '`user`.name_legal_person, ' | . '`user`.name_legal_person, ' | ||||
. '`user`.type, ' | . '`user`.type, ' | ||||
. '`user`.problem_receiving_emails, ' | . '`user`.problem_receiving_emails, ' | ||||
. '`user`.note_emails, ' | |||||
. '(SELECT COUNT(*) FROM `order` WHERE `user`.id = `order`.id_user) AS count_orders'); | . '(SELECT COUNT(*) FROM `order` WHERE `user`.id = `order`.id_user) AS count_orders'); | ||||
if($producer) { | if($producer) { |
return [ | return [ | ||||
[['id_user', 'id_producer'], 'required'], | [['id_user', 'id_producer'], 'required'], | ||||
[['id_user', 'id_producer', 'product_price_percent'], 'integer'], | [['id_user', 'id_producer', 'product_price_percent'], 'integer'], | ||||
[['active', 'bookmark', 'credit_active', 'newsletter', 'trust_alert'], 'boolean'], | |||||
[['active', 'bookmark', 'credit_active', 'newsletter', 'trust_alert', 'exclusive_access_selected_points_sale'], 'boolean'], | |||||
[['credit', 'product_price_percent'], 'double'], | [['credit', 'product_price_percent'], 'double'], | ||||
[['trust_alert_comment'], 'string'] | [['trust_alert_comment'], 'string'] | ||||
]; | ]; | ||||
'product_price_percent' => 'Prix produits : pourcentage', | 'product_price_percent' => 'Prix produits : pourcentage', | ||||
'trust_alert' => 'Alert confiance', | 'trust_alert' => 'Alert confiance', | ||||
'trust_alert_comment' => 'Commentaire', | 'trust_alert_comment' => 'Commentaire', | ||||
'exclusive_access_selected_points_sale' => "Accès exclusif aux points de vente sélectionnés" | |||||
]; | ]; | ||||
} | } | ||||
return $this; | return $this; | ||||
} | } | ||||
public function getExclusiveAccessSelectedPointsSale(): ?bool | |||||
{ | |||||
return $this->exclusive_access_selected_points_sale; | |||||
} | |||||
public function setExclusiveAccessSelectedPointsSale(?bool $exclusiveAccessSelectedPointsSale): self | |||||
{ | |||||
$this->exclusive_access_selected_points_sale = $exclusiveAccessSelectedPointsSale; | |||||
return $this; | |||||
} | |||||
} | } |
{ | { | ||||
return $userProducer->credit < 0 || $userProducer->credit > 0; | return $userProducer->credit < 0 || $userProducer->credit > 0; | ||||
} | } | ||||
public function filterPointsSaleByExclusiveAccess(UserProducer $userProducer, array $pointsSaleArray = []): array | |||||
{ | |||||
if(!$userProducer->getExclusiveAccessSelectedPointsSale()) { | |||||
return $pointsSaleArray; | |||||
} | |||||
$filteredPointsSaleArray = []; | |||||
foreach($pointsSaleArray as $pointSale) { | |||||
$idPointSale = is_array($pointSale) ? $pointSale['id'] : $pointSale->id; | |||||
foreach($userProducer->user->userPointSale as $userPointSale) { | |||||
if($idPointSale == $userPointSale->pointSale->id) { | |||||
$filteredPointsSaleArray[] = $pointSale; | |||||
} | |||||
} | |||||
} | |||||
return $filteredPointsSaleArray; | |||||
} | |||||
} | } |
?> | ?> | ||||
<?php if($producerManager->isProducerSignupOpen()): ?> | <?php if($producerManager->isProducerSignupOpen()): ?> | ||||
<?php if(Yii::$app->user->isGuest || $userModule->getSolver()->isStatusUser($userCurrent)): ?> | |||||
<a class="btn btn-primary" | |||||
href="<?= Yii::$app->user->isGuest ? \Yii::$app->urlManagerFrontend->createUrl(['site/signup', 'type' => 'producer']) : \Yii::$app->urlManagerFrontend->createUrl(['site/signup-producer']); ?>"> | |||||
<i class="bi bi-shop"></i> Je crée mon espace producteur | |||||
</a><br /> | |||||
<?php if($producerManager->getMaximumNumberProducers()): ?> | |||||
<strong><?= ($producerSignupRemainingPlaces); ?></strong> | |||||
place<?php if($producerSignupRemainingPlaces > 1): ?>s<?php endif; ?> restante<?php if($producerSignupRemainingPlaces > 1): ?>s<?php endif; ?> | |||||
<?php endif; ?> | |||||
<br /> | |||||
<br /> | |||||
<a class="btn btn-primary" | |||||
href="<?= Yii::$app->user->isGuest ? \Yii::$app->urlManagerFrontend->createUrl(['site/signup', 'type' => 'producer']) : \Yii::$app->urlManagerFrontend->createUrl(['site/signup-producer']); ?>"> | |||||
<i class="bi bi-shop"></i> Je crée mon espace producteur | |||||
</a><br /> | |||||
<?php if($producerManager->getMaximumNumberProducers()): ?> | |||||
<strong><?= ($producerSignupRemainingPlaces); ?></strong> | |||||
place<?php if($producerSignupRemainingPlaces > 1): ?>s<?php endif; ?> restante<?php if($producerSignupRemainingPlaces > 1): ?>s<?php endif; ?> | |||||
<?php endif; ?> | <?php endif; ?> | ||||
<br /> | |||||
<br /> | |||||
<?php else: ?> | <?php else: ?> | ||||
<div class="label label-warning label-producer-signup-closed"> | <div class="label label-warning label-producer-signup-closed"> | ||||
La plateforme n'accueille pas de nouveaux producteurs pour le moment | La plateforme n'accueille pas de nouveaux producteurs pour le moment |
<div class="panel panel-default"> | <div class="panel panel-default"> | ||||
<div class="panel-heading"> | <div class="panel-heading"> | ||||
<h3 class="panel-title"> | |||||
<h3 class="panel-title" id="modules"> | |||||
<i class="bi bi-boxes"></i> | <i class="bi bi-boxes"></i> | ||||
Modules | Modules | ||||
</h3> | </h3> | ||||
</div> | </div> | ||||
<div class="panel-body"> | <div class="panel-body"> | ||||
<div class="alert alert-dark" role="alert"> | <div class="alert alert-dark" role="alert"> | ||||
Retrouvez ici les modules payants de Souke correspondant aux développements qui n'ont pas encore | |||||
été totalement financés et aux fonctionnalités nécessitant une configuration spécifique. Contactez-moi | |||||
pour demander l'activation d'un module. | |||||
Retrouvez ici les modules payants de Souke correspondant à des fonctionnalités en lien avec des | |||||
plateformes externes ou à des développements répondant à des besoins spécifiques. N'hésitez pas à | |||||
<a href="<?= Yii::$app->urlManager->createUrl(['site/contact']) ?>">me contacter</a> pour en savoir plus ou pour demander l'activation d'un module. | |||||
</div> | </div> | ||||
<table class="table table-striped table-bordered"> | <table class="table table-striped table-bordered"> | ||||
<thead> | <thead> |
?> | ?> | ||||
<div class="site-iamproducer"> | <div class="site-iamproducer"> | ||||
<div class="panel panel-primary panel-padding-large"> | <div class="panel panel-primary panel-padding-large"> | ||||
<!--<div class="panel-heading"> | |||||
<h2 class="panel-title"> | |||||
Vous avez besoin d'un outil pour vous organiser au quotidien ? | |||||
</h2> | |||||
</div>--> | |||||
<div class="panel-body"> | <div class="panel-body"> | ||||
<div class="hook"> | <div class="hook"> | ||||
Vous êtes producteur et vous souhaitez améliorer votre organisation au quotidien ?<br /> | Vous êtes producteur et vous souhaitez améliorer votre organisation au quotidien ?<br /> |
</div> | </div> | ||||
<div class="row"> | <div class="row"> | ||||
<?= block_feature("calendar3", "Planification des jours de distributions"); ?> | <?= block_feature("calendar3", "Planification des jours de distributions"); ?> | ||||
<?= block_feature("download", "Récapitulatif des commandes par jour de distribution (PDF et CSV), génération d'étiquettes (PDF)"); ?> | |||||
<?= block_feature("download", "Récapitulatif des commandes par jour de distribution (PDF et CSV)<br />Génération d'étiquettes simple (PDF)<br />Génération d'étiquettes avec format spécifique (PDF) *"); ?> | |||||
</div> | </div> | ||||
<div class="row"> | <div class="row"> | ||||
<?= block_feature("basket", "Gestion des produits, catégories et prix spécifiques"); ?> | |||||
<?= block_feature("basket", "Gestion des produits, catégories et prix spécifiques<br />Gestion des accessoires produits *"); ?> | |||||
<?php $featureSharedPointSaleDescription = ''; | <?php $featureSharedPointSaleDescription = ''; | ||||
if($featureChecker->isEnabled(Feature::ALIAS_SHARED_POINT_SALE)): | if($featureChecker->isEnabled(Feature::ALIAS_SHARED_POINT_SALE)): | ||||
$featureSharedPointSaleDescription .= "<br />Partage de points de vente entre plusieurs producteurs pour des distributions communes"; | $featureSharedPointSaleDescription .= "<br />Partage de points de vente entre plusieurs producteurs pour des distributions communes"; | ||||
</div> | </div> | ||||
<div class="row"> | <div class="row"> | ||||
<?= block_feature("piggy-bank", "Système de cagnotte permettant la comptabilisation des paiements"); ?> | <?= block_feature("piggy-bank", "Système de cagnotte permettant la comptabilisation des paiements"); ?> | ||||
<?= block_feature("credit-card", "Paiement en ligne possible via la plateforme <strong>Stripe</strong> pour que les clients puissent alimenter leur cagnotte de manière autonome"); ?> | |||||
<?= block_feature("credit-card", "Paiement en ligne via la plateforme <strong>Stripe</strong> pour le paiement des commandes ou l'alimentation des cagnottes *"); ?> | |||||
</div> | </div> | ||||
<div class="row"> | <div class="row"> | ||||
<?= block_feature("megaphone", "Communication facilitée avec les clients via l'envoi d'emails en masse"); ?> | <?= block_feature("megaphone", "Communication facilitée avec les clients via l'envoi d'emails en masse"); ?> | ||||
</div> | </div> | ||||
<div class="row"> | <div class="row"> | ||||
<?= block_feature("graph-up", "Statistiques et rapports de vente"); ?> | <?= block_feature("graph-up", "Statistiques et rapports de vente"); ?> | ||||
<?= block_feature("cloud-arrow-up", "Exports vers les logiciels <strong>Evoliz</strong> (comptabilité) et <strong>SumUp</strong> (caisse)"); ?> | |||||
<?= block_feature("cloud-arrow-up", "Exports vers les logiciels <strong>Evoliz</strong> (comptabilité) et <strong>SumUp</strong> (caisse) *"); ?> | |||||
</div> | </div> | ||||
<p> | |||||
* <a href="#modules">Modules payants</a> | |||||
</p> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
$idProducer = $producer->id; | $idProducer = $producer->id; | ||||
$order = new Order; | $order = new Order; | ||||
if ($idProducer) { | |||||
$this->_verifyProducerActive($idProducer); | |||||
} | |||||
if ($order->load($posts)) { | if ($order->load($posts)) { | ||||
$user = $this->getUserCurrent(); | $user = $this->getUserCurrent(); | ||||
) && isset($unitsArray[$product->id])) ? $unitsArray[$product->id] : $product->unit; | ) && isset($unitsArray[$product->id])) ? $unitsArray[$product->id] : $product->unit; | ||||
$coefficient = Product::$unitsArray[$unit]['coefficient']; | $coefficient = Product::$unitsArray[$unit]['coefficient']; | ||||
$quantity = ((float)$posts['products'][$product->id]) / $coefficient; | $quantity = ((float)$posts['products'][$product->id]) / $coefficient; | ||||
if ($availableProducts[$product->id]['quantity_max'] && $quantity > $availableProducts[$product->id]['quantity_remaining']) { | |||||
$quantity = $availableProducts[$product->id]['quantity_remaining']; | |||||
$quantityRemaining = $orderModule->getResolver()->getProductQuantityRemaining($product, $order->distribution); | |||||
if(!is_null($quantityRemaining) && $quantity > $quantityRemaining) { | |||||
$quantity = $quantityRemaining; | |||||
} | } | ||||
$productOrder->quantity = $quantity; | $productOrder->quantity = $quantity; | ||||
$productOrder->price = $productModule->getPrice($product, [ | $productOrder->price = $productModule->getPrice($product, [ | ||||
return 0; | return 0; | ||||
} | } | ||||
public function actionAjaxInfos(string $date = '', int $pointSaleId = 0) | |||||
public function actionAjaxInfos(string $date = '', int $pointSaleId = 0, string $productsJson = null, bool $loadingProducts = false) | |||||
{ | { | ||||
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; | \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; | ||||
$productsArray = json_decode($productsJson, true); | |||||
$user = GlobalParam::getCurrentUser(); | $user = GlobalParam::getCurrentUser(); | ||||
$producer = $this->getProducerCurrent(); | $producer = $this->getProducerCurrent(); | ||||
$pointSale = $this->getPointSaleModule()->findOnePointSaleById($pointSaleId); | $pointSale = $this->getPointSaleModule()->findOnePointSaleById($pointSaleId); | ||||
$order = $this->getOrderUser($date, $pointSale); | $order = $this->getOrderUser($date, $pointSale); | ||||
return $this->buildJsonAjaxInfos($date, $producer, $pointSale, $user, $order); | |||||
return $this->buildJsonAjaxInfos($date, $producer, $pointSale, $user, $order, $productsArray, $loadingProducts); | |||||
} | } | ||||
public function buildJsonAjaxInfos( | public function buildJsonAjaxInfos( | ||||
Producer $producer, | Producer $producer, | ||||
PointSale $pointSale = null, | PointSale $pointSale = null, | ||||
User $user = null, | User $user = null, | ||||
Order $order = null | |||||
Order $order = null, | |||||
array $productsArray = null, | |||||
bool $loadingProducts = false | |||||
) | ) | ||||
{ | { | ||||
$orderModule = $this->getOrderModule(); | $orderModule = $this->getOrderModule(); | ||||
$json['distribution'] = $distribution; | $json['distribution'] = $distribution; | ||||
$json['points_sale'] = $this->ajaxInfosPointsSale($producer, $distribution); | $json['points_sale'] = $this->ajaxInfosPointsSale($producer, $distribution); | ||||
$json['categories'] = $this->ajaxInfosProductCategories($producer); | $json['categories'] = $this->ajaxInfosProductCategories($producer); | ||||
$json['products'] = $this->ajaxInfosProducts($producer, $distribution, $pointSale, $user, $order); | |||||
$json['products'] = $this->ajaxInfosProducts($producer, $distribution, $pointSale, $user, $order, $productsArray); | |||||
if ($order) { | if ($order) { | ||||
$json['order'] = array_merge($order->getAttributes(), [ | $json['order'] = array_merge($order->getAttributes(), [ | ||||
$orderModule = $this->getOrderModule(); | $orderModule = $this->getOrderModule(); | ||||
$user = GlobalParam::getCurrentUser(); | $user = GlobalParam::getCurrentUser(); | ||||
$userProducer = $this->getUserProducerModule()->getRepository()->findOneUserProducer($user); | |||||
$pointsSaleArray = PointSale::find(); | $pointsSaleArray = PointSale::find(); | ||||
if ($distribution) { | if ($distribution) { | ||||
} | } | ||||
} | } | ||||
// Filtre par accès exclusif aux points de vente | |||||
$pointsSaleArray = $this->getUserProducerModule()->getSolver()->filterPointsSaleByExclusiveAccess( | |||||
$userProducer, | |||||
$pointsSaleArray | |||||
); | |||||
return $pointsSaleArray; | return $pointsSaleArray; | ||||
} | } | ||||
Distribution $distribution, | Distribution $distribution, | ||||
PointSale $pointSale = null, | PointSale $pointSale = null, | ||||
User $user = null, | User $user = null, | ||||
Order $order = null | |||||
Order $order = null, | |||||
array $productsFormArray = null | |||||
) | ) | ||||
{ | { | ||||
$unitModule = $this->getUnitModule(); | $unitModule = $this->getUnitModule(); | ||||
$productsArrayFilter = $productModule->filterProductsByPointSale($productsArray, $pointSale); | $productsArrayFilter = $productModule->filterProductsByPointSale($productsArray, $pointSale); | ||||
$orderCurrent = $order; | |||||
if(count($productsFormArray)) { | |||||
$productOrdersArray = []; | |||||
foreach($productsFormArray as $idProduct => $quantityProduct) { | |||||
if($idProduct) { | |||||
$productObject1 = $productModule->getRepository()->findOneProductById($idProduct); | |||||
$productOrdersArray[$idProduct] = [ | |||||
'quantity' => $quantityProduct / $productModule->getSolver()->getUnitCoefficient($productObject1) | |||||
]; | |||||
} | |||||
} | |||||
$orderCurrent = $orderModule->getBuilder()->instanciateOrderFromProductOrdersArray($productOrdersArray, $orderCurrent); | |||||
} | |||||
$indexProduct = 0; | $indexProduct = 0; | ||||
foreach ($productsArrayFilter as $key => &$product) { | foreach ($productsArrayFilter as $key => &$product) { | ||||
$productObject = $product; | $productObject = $product; | ||||
] | ] | ||||
); | ); | ||||
$coefficient_unit = Product::$unitsArray[$product['unit']]['coefficient']; | |||||
if (is_null($product['photo']) || strlen($product['photo']) == 0) { | if (is_null($product['photo']) || strlen($product['photo']) == 0) { | ||||
$product['photo'] = ''; | $product['photo'] = ''; | ||||
} | } | ||||
$product['photo'] = Image::getThumbnailSmall($product['photo']); | $product['photo'] = Image::getThumbnailSmall($product['photo']); | ||||
} | } | ||||
$product['quantity_max'] = (isset($product['productDistribution']) && isset($product['productDistribution'][0])) ? $product['productDistribution'][0]['quantity_max'] : null; | |||||
$quantityOrder = $orderModule->getProductQuantity($productObject, $ordersArray); | |||||
$product['quantity_ordered'] = $quantityOrder; | |||||
$product['quantity_remaining'] = $product['quantity_max'] - $quantityOrder; | |||||
$coefficientUnit = Product::$unitsArray[$product['unit']]['coefficient']; | |||||
$product['coefficient_unit'] = $coefficientUnit; | |||||
$product['quantity_max'] = $orderModule->getResolver()->getProductQuantityMaxOrderable($productObject, $distribution, $orderCurrent); | |||||
$product['quantity_remaining'] = $orderModule->getResolver()->getProductQuantityRemaining($productObject, $distribution, $orderCurrent); | |||||
$product['wording_unit'] = $unitModule->getSolver()->strUnit($product['unit'], UnitDefinition::WORDING_UNIT, true); | $product['wording_unit'] = $unitModule->getSolver()->strUnit($product['unit'], UnitDefinition::WORDING_UNIT, true); | ||||
$product['wording_unit_ref'] = $unitModule->getSolver()->strUnit($product['unit'], UnitDefinition::WORDING_SHORT, true); | $product['wording_unit_ref'] = $unitModule->getSolver()->strUnit($product['unit'], UnitDefinition::WORDING_SHORT, true); | ||||
$quantityOrderUser = $orderModule->getSolver()->getProductQuantity($productObject, $orderCurrent ? [$orderCurrent] : [], true); | |||||
$product['quantity_form'] = $quantityOrderUser * $coefficientUnit; | |||||
if($product['quantity_remaining'] < 0 && $product['quantity_form']) { | |||||
$product['quantity_form'] = $product['quantity_form'] + ($product['quantity_remaining'] * $coefficientUnit); | |||||
$orderModule->getBuilder()->deleteProductOrderQuantity($orderCurrent, $productObject, abs($product['quantity_remaining'])); | |||||
$product['quantity_remaining'] = $orderModule->getResolver()->getProductQuantityRemaining($productObject, $distribution, $orderCurrent); | |||||
} | |||||
$product['wording_unit'] = $unitModule->getSolver()->strUnit($product['unit'], 'wording_unit', true); | |||||
if ($order) { | if ($order) { | ||||
$quantityOrderUser = $orderModule->getProductQuantity($productObject, [$order], true); | |||||
$product['quantity_ordered'] = $quantityOrder; | |||||
$product['quantity_remaining'] = $product['quantity_max'] - $quantityOrder + $quantityOrderUser; | |||||
$product['quantity_form'] = $quantityOrderUser * $coefficient_unit; | |||||
foreach ($order->productOrder as $productOrder) { | foreach ($order->productOrder as $productOrder) { | ||||
if ($productOrder->id_product == $product['id']) { | if ($productOrder->id_product == $product['id']) { | ||||
$product['wording_unit'] = $productModule->getSolver()->strUnit($productOrder->product, 'wording_unit', true); | $product['wording_unit'] = $productModule->getSolver()->strUnit($productOrder->product, 'wording_unit', true); | ||||
$product['step'] = $productOrder->step; | $product['step'] = $productOrder->step; | ||||
} | } | ||||
} | } | ||||
} else { | |||||
$product['quantity_form'] = 0; | |||||
$product['wording_unit'] = $unitModule->getSolver()->strUnit($product['unit'], 'wording_unit', true); | |||||
} | } | ||||
$product['coefficient_unit'] = $coefficient_unit; | |||||
if ($product['quantity_remaining'] < 0) { | |||||
$product['quantity_remaining'] = 0; | |||||
} | |||||
$product['index'] = $indexProduct++; | $product['index'] = $indexProduct++; | ||||
} | } | ||||
<?php | |||||
/** | |||||
Copyright Souke (2018) | |||||
contact@souke.fr | |||||
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\GlobalParam; | |||||
use common\helpers\Price; | |||||
use domain\Order\Order\OrderModule; | |||||
use domain\Producer\Producer\Producer; | |||||
use domain\Producer\Producer\ProducerModule; | |||||
use yii\helpers\Html; | |||||
use yii\widgets\ActiveForm; | |||||
$producerModule = ProducerModule::getInstance(); | |||||
$orderModule = OrderModule::getInstance(); | |||||
?> | |||||
<div class="order-form"> | |||||
<?php | |||||
$form = ActiveForm::begin([ | |||||
'enableClientScript' => false | |||||
]); | |||||
?> | |||||
<?php | |||||
if(count($distributionDaysArray) <= 1) : | |||||
?> | |||||
<div class="alert alert-warning">Aucun jour de production n'a été programmé par le producteur.</div> | |||||
<?php endif; ?> | |||||
<?php if($idProducer && count($distributionDaysArray) > 1): ?> | |||||
<div id="step-date" class="col-md-6"> | |||||
<?= $form->field($model, 'id_distribution')->label('')->hiddenInput(); ?> | |||||
<?php if (isset($model->id)): ?> | |||||
<div class="date-order"><span><?php echo date('d/m/Y', strtotime($distribution->date)); ?></span></div> | |||||
<?= Html::hiddenInput('id_order', $model->id,['id'=>'id-order']); ?> | |||||
<?= Html::hiddenInput('paid_amount', $orderModule->getOrderAmount($model, Order::AMOUNT_PAID),['id'=>'paid-amount']); ?> | |||||
<?php endif; ?> | |||||
<div id="datepicker-distribution" <?php if (isset($model->id)): ?>style="display:none"<?php endif; ?>> | |||||
</div> | |||||
<?php if (!isset($model->id)): ?> | |||||
<br /> | |||||
<?php endif; ?> | |||||
<div id="dates" style="display:none;"> | |||||
<?php | |||||
foreach ($distributionDaysArray as $idDistribution => $day) { | |||||
if ($day != '--') { | |||||
echo '<div><span class="date">' . $day . '</span><span class="id_distribution">' . $idDistribution. '</span></div>'; | |||||
} | |||||
} | |||||
?> | |||||
</div> | |||||
<div class="clr"></div> | |||||
<div id="orders-in-progress" style="display:none;"> | |||||
<?php foreach ($ordersArray as $order): ?> | |||||
<?php echo '<div class="order" data-iddistribution="' . $order->id_distribution. '" data-id="' . $order->id . '" data-href="' . \Yii::$app->urlManager->createUrl(['order/update', 'id' => $order->id, 'id_producer' => $order->distribution->id_producer]) . '"></div>'; ?> | |||||
<?php endforeach; ?> | |||||
</div> | |||||
<div id="has-order-in-progress" style="display:none;" class="alert alert-danger">Vous avez déjà une commande en cours pour cette date. <a href="#">Cliquez ici</a> pour la modifier.</div> | |||||
</div> | |||||
<div class="col-md-6"> | |||||
<?php if(strlen($producer->order_infos)): ?> | |||||
<div id="order-infos"> | |||||
<?= nl2br(Html::encode($producer->order_infos)) ?> | |||||
</div> | |||||
<?php endif; ?> | |||||
</div> | |||||
<div class="clr"></div> | |||||
<div id="block-points-sale"> | |||||
<h3 id="step-point-sale"><span><?= $producerModule->getPointSaleWording($producer); ?></span></h3> | |||||
<?= | |||||
$form->field($model, 'id_point_sale') | |||||
->label('') | |||||
->hiddenInput(); | |||||
?> | |||||
<input type="hidden" id="livraison" value="<?php if (!is_null($distribution) && $distribution->delivery): ?>1<?php else: ?>0<?php endif; ?>" /> | |||||
<ul id="points-sale" class="blocks"> | |||||
<?php | |||||
foreach ($pointsSaleArray as $pointSale) { | |||||
$comment = '' ; | |||||
if(isset($pointSale->userPointSale) && is_array($pointSale->userPointSale) && count($pointSale->userPointSale)) | |||||
{ | |||||
foreach($pointSale->userPointSale as $userPointSale) | |||||
{ | |||||
if($userPointSale->id_user == GlobalParam::getCurrentUserId() && strlen($userPointSale->comment)) | |||||
{ | |||||
$comment = '<div class="comment"><span>'.Html::encode($userPointSale->comment).'</span></div>' ; | |||||
} | |||||
} | |||||
} | |||||
$htmlCode = '' ; | |||||
$dataCode = '0' ; | |||||
$code = '' ; | |||||
if(strlen($pointSale->code)) | |||||
{ | |||||
if(!isset($model->id_point_sale) || $model->id_point_sale != $pointSale->id) | |||||
{ | |||||
$htmlCode .= '<span class="glyphicon glyphicon-lock"></span> ' ; | |||||
$dataCode = '1' ; | |||||
} | |||||
else { | |||||
$code = $pointSale->code ; | |||||
} | |||||
} | |||||
echo '<li class="block point-sale point-sale-' . $pointSale->id . '" data-code="'.$dataCode.'" data-credit="'.(int) $pointSale->payment_method_credit.'"><div class="contenu">' . | |||||
'<span style="display:none;" class="id">' . $pointSale->id . '</span>' . | |||||
'<div class="name">' .$htmlCode. Html::encode($pointSale->name) . '</div>' . | |||||
'<div class="address">à ' . Html::encode($pointSale->locality) . '</div>' . | |||||
$comment . | |||||
'<input type="hidden" name="code_point_sale_'.$pointSale->id.'" value="'.$code.'" />'. | |||||
'</div></li>'; | |||||
} | |||||
?> | |||||
</ul> | |||||
<div class="clr"></div> | |||||
<div id="step-infos-point-sale"> | |||||
<?php | |||||
foreach ($pointsSaleArray as $pointSale) { | |||||
echo '<div class="alert alert-warning infos-point-sale infos-point-sale-'.$pointSale->id.'"><h4>Infos : <span>'.Html::encode($pointSale->name).'</span></h4>' . | |||||
'<div class="jour jour-1">' . $pointSale->getStrInfos('monday') . '</div>' . | |||||
'<div class="jour jour-2">' . $pointSale->getStrInfos('tuesday') . '</div>' . | |||||
'<div class="jour jour-3">' . $pointSale->getStrInfos('wednesday') . '</div>' . | |||||
'<div class="jour jour-4">' . $pointSale->getStrInfos('thursday') . '</div>' . | |||||
'<div class="jour jour-5">' . $pointSale->getStrInfos('friday') . '</div>' . | |||||
'<div class="jour jour-6">' . $pointSale->getStrInfos('saturday') . '</div>' . | |||||
'<div class="jour jour-0">' . $pointSale->getStrInfos('sunday') . '</div>' . | |||||
'</div>' ; | |||||
} | |||||
?> | |||||
</div> | |||||
<div class="clr"></div> | |||||
</div> | |||||
<div id="products"> | |||||
<h3 id="step-products"><span>Produits</span></h3> | |||||
<?php // erreur ?> | |||||
<?php if (Yii::$app->session->getFlash('error')): ?> | |||||
<div class="alert alert-danger"><div class="icon"></div><?= \Yii::$app->session->getFlash('error'); ?></div> | |||||
<?php endif; ?> | |||||
<div id=""> | |||||
<div class="alert alert-warning unavailable">Produit indisponible pour ce point de vente</div> | |||||
<table class="table table-bordered" id="table-products"> | |||||
<thead> | |||||
<tr> | |||||
<th class="th-photo">Photo</th> | |||||
<th class="product">Produit</th> | |||||
<th class="price-unit">Prix unitaire</th> | |||||
<th class="column-quantity">Quantité</th> | |||||
<th class="total">Total</th> | |||||
</tr> | |||||
</thead> | |||||
<tbody> | |||||
<?php foreach ($productsArray as $product): ?> | |||||
<?php | |||||
$quantity = 0; | |||||
if (isset($selectedProducts[$product->id])) { | |||||
$quantity = $selectedProducts[$product->id]; | |||||
} | |||||
?> | |||||
<tr class="product-<?php echo $product->id; ?>" data-no-limit="<?php if(!$product->quantity_max): ?>1<?php else: ?>0<?php endif; ?>" data-quantity-max="<?= $quantity ?>" <?php if (count($availableProducts) && !$availableProducts[$product->id]['active']): ?>style="display:none;"<?php endif; ?>> | |||||
<td class="td-photo"> | |||||
<?php if (strlen($product->photo) && file_exists(dirname(__FILE__).'/../../web/uploads/' . $product->photo)): ?><a href="<?= \Yii::$app->urlManager->getBaseUrl() . '/uploads/' . $product->photo ?>" data-lightbox="product-<?php echo $product->id; ?>"><img class="photo img-rounded" src="<?= \Yii::$app->urlManager->getBaseUrl() . '/uploads/' . $product->photo ?>" alt="Photo <?= Html::encode($product->name); ?>" /></a><?php endif; ?> | |||||
</td> | |||||
<td class="produit"> | |||||
<span class="name"><?= Html::encode($product->name); ?></span> - <span class="description"><?= Html::encode($product->getDescription()); ?></span><br /> | |||||
<span class="recipe"><?= Html::encode($product->recipe); ?></span> | |||||
</td> | |||||
<td class="price-unit"> | |||||
<span class="price"><?= Price::format($product->price); ?></span> € | |||||
</td> | |||||
<td class="column-quantity"> | |||||
<div class="input-group" <?php if (isset($availableProducts[$product->id]) && $availableProducts[$product->id]['quantity_remaining'] == 0 && $quantity == 0): ?>style="display:none;"<?php endif; ?>> | |||||
<span class="input-group-btn"> | |||||
<button type="button" class="btn btn-default move-quantity minus">-</button> | |||||
</span> | |||||
<input type="text" value="<?php if (isset($selectedProducts[$product->id])): echo $selectedProducts[$product->id]; | |||||
else: ?>0<?php endif; ?>" readonly name="Product[product_<?php echo $product->id; ?>]" class="quantity form-control"> | |||||
<span class="input-group-btn"> | |||||
<button type="button" class="btn btn-default move-quantity plus">+</button> | |||||
</span> | |||||
</div> | |||||
<div class="quantity-remaining">Reste <span class="nb"><?php if (isset($availableProducts[$product->id])): echo $availableProducts[$product->id]['quantity_remaining'] + $quantity; | |||||
endif; ?></span> <?php echo Html::encode(strtolower($product->name)); ?>(s) | |||||
</div> | |||||
<div class="unavailable">Épuisé</div> | |||||
</td> | |||||
<td class="total"><strong></strong></td> | |||||
</tr> | |||||
<?php endforeach; ?> | |||||
</tbody> | |||||
<tfoot> | |||||
<tr> | |||||
<td></td> | |||||
<td></td> | |||||
<td></td> | |||||
<td id="total-order"><strong></strong></td> | |||||
</tr> | |||||
</tfoot> | |||||
</table> | |||||
</div> | |||||
</div> | |||||
<?php if($idProducer): ?> | |||||
<?php | |||||
$producer = Producer::findOne($idProducer); | |||||
?> | |||||
<div id="bar-fixed" class="<?php if($producer->credit): ?>credit<?php else: ?>no-credit<?php endif; ?>"> | |||||
<div class="container"> | |||||
<?php if (isset($model->id) && $orderModule->getSolver()->isOrderStatusValid($model)): ?> | |||||
<a href="<?php echo \Yii::$app->urlManager->createUrl(['order/cancel', 'id' => $model->id]); ?>" class="btn btn-danger cancel-order">Annuler ma commande</a> | |||||
<?php endif; ?> | |||||
<span id="total-order-bottom"><span></span> €</span> | |||||
<?= Html::submitButton('<span class="glyphicon glyphicon-comment"></span> Commentaire', ['class' => 'btn btn-default btn-comment', 'data-placement' => 'top', 'data-toggle' => 'tooltip', 'data-original-title' => 'Ajouter un commentaire']) ?> | |||||
<?php | |||||
if($producer->credit): | |||||
$linkCredit = '<a class="info-credit" href="'.Yii::$app->urlManager->createUrl(['site/credit']) .'" data-toggle="tooltip" data-placement="bottom" title="En savoir plus sur le Crédit"><span class="glyphicon glyphicon-info-sign"></span></a>' ; ; | |||||
?> | |||||
<div id="checkbox-credit" > | |||||
<?php if($credit || $orderModule->getAmount($order, Order::AMOUNT_PAID)): ?> | |||||
<?= Html::checkbox('credit', true, ['label' => 'Utiliser mon Crédit <span class="the-credit" data-toggle="tooltip" data-placement="top" data-original-title="Vous avez actuellement '.number_format($credit,2).' € sur votre compte Crédit">'.number_format($credit,2).' €</span><br /><span class="info"></span>']) ?> | |||||
<?= Html::hiddenInput('amount_credit', $credit, ['id' => 'amount-credit']) ?> | |||||
<?= Html::hiddenInput('str_amount_credit', number_format($credit,2).' €', ['id' => 'str-amount-credit']) ?> | |||||
<?php else: ?> | |||||
<div id="info-credit-empty"> | |||||
Votre compte Crédit est vide <?= $linkCredit ?> | |||||
</div> | |||||
<?php endif; ?> | |||||
<div id="credit-disabled">Le Crédit est désactivé<br /> pour ce point de vente <?= $linkCredit ?></div> | |||||
</div> | |||||
<div class="clr"></div> | |||||
<?php endif; ?> | |||||
<?= $form->field($model, 'comment')->textarea(['rows' => 3, 'placeholder' => 'Un commentaire ?'])->label(''); ?> | |||||
<div id="block-confirm-order"> | |||||
<?php if($model->date_delete): $strButtonConfirmOrder = 'Réactiver ma commande' ; else: $strButtonConfirmOrder = 'Valider ma commande' ; endif; ?> | |||||
<?= Html::submitButton('<span class="glyphicon glyphicon-ok"></span> '.$strButtonConfirmOrder, ['class' => 'btn btn-primary confirm-order']) ?> | |||||
</div> | |||||
<?php endif; ?> | |||||
</div> | |||||
</div> | |||||
<?php | |||||
// id_etablissement | |||||
endif; ?> | |||||
<?php ActiveForm::end(); ?> | |||||
<!-- modal code point de vente --> | |||||
<div class="modal fade" id="modal-code" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> | |||||
<div class="modal-dialog modal-lg" role="document"> | |||||
<div class="modal-content"> | |||||
<div class="modal-header"> | |||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> | |||||
<h4 class="modal-title" id="myModalLabel">Code d'accès</h4> | |||||
</div> | |||||
<div class="modal-body"> | |||||
<div class="alert alert-warning"> | |||||
Ce point de vente nécessite un code d'accès. | |||||
</div> | |||||
<form action="index.php?r=order/validate-code-point-sale" method="post"> | |||||
<input type="hidden" value="" name="idPointSale" id="id-point-sale" /> | |||||
<div class="form-group field-code required"> | |||||
<label class="control-label" for="code">Code d'accès :</label> | |||||
<input type="password" class="form-control" id="code" name="code" /> | |||||
<p class="help-block help-block-error" style="display:none;">Code incorrect</p> | |||||
</div> | |||||
<div class="form-group"> | |||||
<button type="submit" class="btn btn-primary">Valider</button> | |||||
</div> | |||||
</form> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div><!-- commande-form --> |
<span v-if="product.weight">({{ product.weight }} g)</span> | <span v-if="product.weight">({{ product.weight }} g)</span> | ||||
</span> | </span> | ||||
<div> | <div> | ||||
<span v-if="product.quantity_max > 0 && ((product.quantity_form / product.coefficient_unit == product.quantity_remaining) || ((product.quantity_remaining * product.coefficient_unit) - product.quantity_form) < product.step)" | |||||
<span v-if="product.quantity_max != null && (product.quantity_remaining <= 0 || product.quantity_remaining * product.coefficient_unit < product.step)" | |||||
class="badge bg-danger">Épuisé</span> | class="badge bg-danger">Épuisé</span> | ||||
</div> | </div> | ||||
<div class="description" v-if="product.description.length"> | <div class="description" v-if="product.description.length"> | ||||
<button class="btn btn-secondary btn-moins" | <button class="btn btn-secondary btn-moins" | ||||
type="button" | type="button" | ||||
@click="productQuantityClick(product, product.unit == 'piece' ? -1 : -parseFloat(product.step))" | @click="productQuantityClick(product, product.unit == 'piece' ? -1 : -parseFloat(product.step))" | ||||
:disabled="product.quantity_form == 0"> | |||||
:disabled="product.quantity_form == 0 || loadingProducts"> | |||||
<i class="bi bi-dash-lg"></i></button> | <i class="bi bi-dash-lg"></i></button> | ||||
</span> | </span> | ||||
<input type="text" v-model="product.quantity_form" | <input type="text" v-model="product.quantity_form" | ||||
<button class="btn btn-secondary btn-plus" | <button class="btn btn-secondary btn-plus" | ||||
type="button" | type="button" | ||||
@click="productQuantityClick(product, product.unit == 'piece' ? 1 : parseFloat(product.step))" | @click="productQuantityClick(product, product.unit == 'piece' ? 1 : parseFloat(product.step))" | ||||
:disabled="product.quantity_form == product.quantity_remaining && product.quantity_max > 0"> | |||||
:disabled="loadingProducts || (product.quantity_remaining != null && product.quantity_remaining <= 0) || (product.quantity_max != null && product.quantity_form >= product.quantity_max * product.coefficient_unit)"> | |||||
<i class="bi bi-plus-lg"></i></button> | <i class="bi bi-plus-lg"></i></button> | ||||
</span> | </span> | ||||
</div> | </div> |
data() { | data() { | ||||
return Object.assign({ | return Object.assign({ | ||||
order: null, | order: null, | ||||
timerAjaxInfosProducts: false, | |||||
xhr: false, | |||||
loading: false, | loading: false, | ||||
loadingProducts: false, | |||||
loadingInit: true, | loadingInit: true, | ||||
cancelTokenSource: null, | |||||
step: null, | step: null, | ||||
producer: null, | producer: null, | ||||
user: null, | user: null, | ||||
}, | }, | ||||
mounted: function() { | mounted: function() { | ||||
this.initDate(); | this.initDate(); | ||||
this.init('first'); | |||||
this.init('first', false); | |||||
}, | }, | ||||
methods: { | methods: { | ||||
initDate: function() { | initDate: function() { | ||||
} | } | ||||
} | } | ||||
}, | }, | ||||
init: function(type, oldStep, step) { | |||||
init: function(type, loadingProducts) { | |||||
var app = this ; | var app = this ; | ||||
this.loading = true ; | |||||
if(loadingProducts) { | |||||
if (app.timerAjaxInfosProducts) { | |||||
clearTimeout(app.timerAjaxInfosProducts); | |||||
} | |||||
app.timerAjaxInfosProducts = setTimeout(function(app) { | |||||
app.loadingProducts = true ; | |||||
if(app.xhr) { | |||||
app.xhr.abort(); | |||||
} | |||||
app.xhr = $.get('ajax-infos', { | |||||
date : app.getDate(), | |||||
pointSaleId: app.pointSaleActiveId ? app.pointSaleActiveId : (app.pointSaleActive ? app.pointSaleActive.id : 0), | |||||
productsJson: JSON.stringify(app.getProductsArray()), | |||||
loadingProducts: loadingProducts | |||||
}, function(response) { | |||||
app.products = response.products; | |||||
app.loadingProducts = false; | |||||
}, 'json'); | |||||
}.bind(this, app), 300); | |||||
return; | |||||
} | |||||
else { | |||||
this.loading = true ; | |||||
} | |||||
if(app.isChangeState('date', 'date', 'point-sale')) { | if(app.isChangeState('date', 'date', 'point-sale')) { | ||||
app.pointSaleActive = null ; | app.pointSaleActive = null ; | ||||
app.products = [] ; | app.products = [] ; | ||||
} | } | ||||
axios.get("ajax-infos",{params: { | |||||
date : this.getDate(), | |||||
pointSaleId: this.pointSaleActiveId ? this.pointSaleActiveId : (this.pointSaleActive ? this.pointSaleActive.id : 0) | |||||
//app.cancelTokenSource = axios.CancelToken.source(); | |||||
axios.get("ajax-infos",{ | |||||
//cancelToken: app.cancelTokenSource.token, | |||||
params: { | |||||
date : this.getDate(), | |||||
pointSaleId: this.pointSaleActiveId ? this.pointSaleActiveId : (this.pointSaleActive ? this.pointSaleActive.id : 0), | |||||
productsJson: this.getProductsArray(), | |||||
loadingProducts: loadingProducts | |||||
}}) | }}) | ||||
.catch(function (thrown) { | |||||
if (axios.isCancel(thrown)) { | |||||
} | |||||
}) | |||||
.then(function(response) { | .then(function(response) { | ||||
app.calendar.attrs = []; | |||||
app.calendar.availableDates = []; | |||||
var distributions = response.data.distributions; | |||||
app.distributions = distributions; | |||||
if (distributions.length) { | |||||
var arrayDate; | |||||
var highlightStyle = { | |||||
style: { | |||||
background: 'white', | |||||
border: 'solid 2px #198754' | |||||
}, | |||||
contentStyle: { | |||||
color: '#198754' | |||||
} | |||||
}; | |||||
for (var i = 0; i < distributions.length; i++) { | |||||
app.calendar.attrs.push({ | |||||
highlight: highlightStyle, | |||||
dates: distributions[i].date | |||||
}); | |||||
if(response) { | |||||
app.calendar.attrs = []; | |||||
app.calendar.availableDates = []; | |||||
var distributions = response.data.distributions; | |||||
app.distributions = distributions; | |||||
if (distributions.length) { | |||||
var arrayDate; | |||||
var highlightStyle = { | |||||
style: { | |||||
background: 'white', | |||||
border: 'solid 2px #198754' | |||||
}, | |||||
contentStyle: { | |||||
color: '#198754' | |||||
} | |||||
}; | |||||
for (var i = 0; i < distributions.length; i++) { | |||||
app.calendar.attrs.push({ | |||||
highlight: highlightStyle, | |||||
dates: distributions[i].date | |||||
}); | |||||
arrayDate = distributions[i].date.split('-'); | |||||
app.calendar.availableDates.push({ | |||||
highlight: highlightStyle, | |||||
start: new Date(arrayDate[0], arrayDate[1] - 1, arrayDate[2]), | |||||
end: new Date(arrayDate[0], arrayDate[1] - 1, arrayDate[2]) | |||||
}); | |||||
arrayDate = distributions[i].date.split('-'); | |||||
app.calendar.availableDates.push({ | |||||
highlight: highlightStyle, | |||||
start: new Date(arrayDate[0], arrayDate[1] - 1, arrayDate[2]), | |||||
end: new Date(arrayDate[0], arrayDate[1] - 1, arrayDate[2]) | |||||
}); | |||||
} | |||||
} | } | ||||
} | |||||
if(response.data.leave_period) { | |||||
leavePeriodStartDateArray = response.data.leave_period.start.split('-'); | |||||
leavePeriodEndDateArray = response.data.leave_period.end.split('-'); | |||||
if (response.data.leave_period) { | |||||
leavePeriodStartDateArray = response.data.leave_period.start.split('-'); | |||||
leavePeriodEndDateArray = response.data.leave_period.end.split('-'); | |||||
app.calendar.attrs.push({ | |||||
highlight: { | |||||
style: { | |||||
//background: '#E09F3E' | |||||
background: 'gray' | |||||
app.calendar.attrs.push({ | |||||
highlight: { | |||||
style: { | |||||
//background: '#E09F3E' | |||||
background: 'gray' | |||||
}, | |||||
contentStyle: { | |||||
color: 'white' | |||||
} | |||||
}, | }, | ||||
contentStyle: { | |||||
color: 'white' | |||||
} | |||||
}, | |||||
dates: { | |||||
start: new Date(leavePeriodStartDateArray[0], leavePeriodStartDateArray[1] - 1, leavePeriodStartDateArray[2]), | |||||
end: new Date(leavePeriodEndDateArray[0], leavePeriodEndDateArray[1] - 1, leavePeriodEndDateArray[2]) | |||||
}, | |||||
popover: { | |||||
label: 'En congé', | |||||
hideIndicator: true, | |||||
isInteractive: true | |||||
}, | |||||
}); | |||||
} | |||||
dates: { | |||||
start: new Date(leavePeriodStartDateArray[0], leavePeriodStartDateArray[1] - 1, leavePeriodStartDateArray[2]), | |||||
end: new Date(leavePeriodEndDateArray[0], leavePeriodEndDateArray[1] - 1, leavePeriodEndDateArray[2]) | |||||
}, | |||||
popover: { | |||||
label: 'En congé', | |||||
hideIndicator: true, | |||||
isInteractive: true | |||||
}, | |||||
}); | |||||
} | |||||
if (response.data.distribution) { | |||||
app.distribution = response.data.distribution; | |||||
} | |||||
if (response.data.distribution) { | |||||
app.distribution = response.data.distribution; | |||||
} | |||||
var orders = []; | |||||
if (response.data.orders) { | |||||
orders = response.data.orders; | |||||
} | |||||
var orders = []; | |||||
if (response.data.orders) { | |||||
orders = response.data.orders; | |||||
} | |||||
if (orders.length) { | |||||
for (var i = 0; i < orders.length; i++) { | |||||
arrayDate = orders[i].date_distribution.split('-'); | |||||
var dateOrder = new Date(arrayDate[0], arrayDate[1] - 1, arrayDate[2]); | |||||
if (app.isAvailableDate(dateOrder)) { | |||||
app.calendar.attrs.push({ | |||||
highlight: { | |||||
style: { | |||||
background: '#198754' | |||||
if (orders.length) { | |||||
for (var i = 0; i < orders.length; i++) { | |||||
arrayDate = orders[i].date_distribution.split('-'); | |||||
var dateOrder = new Date(arrayDate[0], arrayDate[1] - 1, arrayDate[2]); | |||||
if (app.isAvailableDate(dateOrder)) { | |||||
app.calendar.attrs.push({ | |||||
highlight: { | |||||
style: { | |||||
background: '#198754' | |||||
}, | |||||
contentStyle: { | |||||
color: 'white' | |||||
} | |||||
}, | }, | ||||
contentStyle: { | |||||
color: 'white' | |||||
} | |||||
}, | |||||
popover: { | |||||
label: orders[i].pointSale.name + ' (' + app.formatPrice(orders[i].amount_total)+')', | |||||
hideIndicator: true, | |||||
isInteractive: true | |||||
}, | |||||
dates: orders[i].date_distribution | |||||
}); | |||||
popover: { | |||||
label: orders[i].pointSale.name + ' (' + app.formatPrice(orders[i].amount_total) + ')', | |||||
hideIndicator: true, | |||||
isInteractive: true | |||||
}, | |||||
dates: orders[i].date_distribution | |||||
}); | |||||
} | |||||
} | } | ||||
} | } | ||||
} | |||||
app.producer = response.data.producer; | |||||
app.user = response.data.user; | |||||
app.useCredit = response.data.producer.use_credit_checked_default; | |||||
app.producer = response.data.producer; | |||||
app.user = response.data.user; | |||||
app.useCredit = response.data.producer.use_credit_checked_default; | |||||
if (response.data.points_sale) { | |||||
app.pointsSale = []; | |||||
var orderPointSale = 0; | |||||
for (var key in response.data.points_sale) { | |||||
response.data.points_sale[key].order = orderPointSale++; | |||||
app.pointsSale[response.data.points_sale[key].id] = response.data.points_sale[key]; | |||||
if (response.data.points_sale) { | |||||
app.pointsSale = []; | |||||
var orderPointSale = 0; | |||||
for (var key in response.data.points_sale) { | |||||
response.data.points_sale[key].order = orderPointSale++; | |||||
app.pointsSale[response.data.points_sale[key].id] = response.data.points_sale[key]; | |||||
if(!app.pointsSaleCodes[response.data.points_sale[key].id]) { | |||||
app.pointsSaleCodes[response.data.points_sale[key].id] = ''; | |||||
Vue.set(app.pointsSaleCodes, response.data.points_sale[key].id, ''); | |||||
if (!app.pointsSaleCodes[response.data.points_sale[key].id]) { | |||||
app.pointsSaleCodes[response.data.points_sale[key].id] = ''; | |||||
Vue.set(app.pointsSaleCodes, response.data.points_sale[key].id, ''); | |||||
} | |||||
} | } | ||||
} | } | ||||
} | |||||
if(app.pointSaleActiveId) { | |||||
app.pointSaleActive = app.getPointSale(app.pointSaleActiveId); | |||||
} | |||||
if(app.pointSaleActive) { | |||||
if(app.producer.credit | |||||
&& app.pointSaleActive.payment_method_credit | |||||
&& (app.pointSaleActive.credit_functioning == 'mandatory' | |||||
|| (app.pointSaleActive.credit_functioning == 'user' && app.user.credit_active) | |||||
|| (app.pointSaleActive.credit_functioning == 'optional' && response.data.producer.use_credit_checked_default))) { | |||||
app.paymentMethod = 'credit'; | |||||
if (app.pointSaleActiveId) { | |||||
app.pointSaleActive = app.getPointSale(app.pointSaleActiveId); | |||||
} | } | ||||
else if(app.pointSaleActive.payment_method_onsite) { | |||||
app.paymentMethod = 'onsite'; | |||||
if (app.pointSaleActive) { | |||||
if (app.producer.credit | |||||
&& app.pointSaleActive.payment_method_credit | |||||
&& (app.pointSaleActive.credit_functioning == 'mandatory' | |||||
|| (app.pointSaleActive.credit_functioning == 'user' && app.user.credit_active) | |||||
|| (app.pointSaleActive.credit_functioning == 'optional' && response.data.producer.use_credit_checked_default))) { | |||||
app.paymentMethod = 'credit'; | |||||
} else if (app.pointSaleActive.payment_method_onsite) { | |||||
app.paymentMethod = 'onsite'; | |||||
} else if (app.pointSaleActive.payment_method_online) { | |||||
app.paymentMethod = 'online'; | |||||
} | |||||
} | } | ||||
else if(app.pointSaleActive.payment_method_online) { | |||||
app.paymentMethod = 'online'; | |||||
if (app.isChangeState('point-sale', 'point-sale', 'date')) { | |||||
app.date = null; | |||||
app.dateFormat = null; | |||||
} | } | ||||
} | |||||
if(app.isChangeState('point-sale', 'point-sale', 'date')) { | |||||
app.date = null ; | |||||
app.dateFormat = null ; | |||||
} | |||||
// update order | |||||
var updateOrder = false; | |||||
if (app.isChangeState('date', 'point-sale', 'products') | |||||
|| app.isChangeState('date', 'date', 'point-sale') | |||||
|| app.isChangeState('point-sale', 'date', 'products') | |||||
|| app.isChangeState('point-sale', 'point-sale', 'date')) { | |||||
// update order | |||||
var updateOrder = false ; | |||||
if(app.isChangeState('date', 'point-sale', 'products') | |||||
|| app.isChangeState('date', 'date', 'point-sale') | |||||
|| app.isChangeState('point-sale', 'date', 'products') | |||||
|| app.isChangeState('point-sale', 'point-sale', 'date')) { | |||||
updateOrder = true; | |||||
} | |||||
updateOrder = true ; | |||||
} | |||||
if (updateOrder) { | |||||
app.updateOrder(response); | |||||
} | |||||
if(updateOrder) { | |||||
app.updateOrder(response); | |||||
} | |||||
if (type == 'first') { | |||||
if (app.getDate() && app.pointSaleActive) { | |||||
app.step = 'products'; | |||||
if (response.data.products) { | |||||
app.products = response.data.products; | |||||
} | |||||
if(type == 'first') { | |||||
if(app.getDate() && app.pointSaleActive) { | |||||
app.step = 'products' ; | |||||
if(response.data.products) { | |||||
app.products = response.data.products; | |||||
app.updateOrder(response); | |||||
} else if (app.producer.option_order_entry_point == 'point-sale') { | |||||
app.step = 'point-sale'; | |||||
} else if (app.getDate() && app.producer && app.producer.option_order_entry_point == 'date') { | |||||
app.step = 'point-sale'; | |||||
} else { | |||||
app.step = 'date'; | |||||
} | } | ||||
app.updateOrder(response); | |||||
} | |||||
else if(app.producer.option_order_entry_point == 'point-sale') { | |||||
app.step = 'point-sale' ; | |||||
} | |||||
else if(app.getDate() && app.producer && app.producer.option_order_entry_point == 'date') { | |||||
app.step = 'point-sale' ; | |||||
} | } | ||||
else { | |||||
app.step = 'date' ; | |||||
} | |||||
} | |||||
if(response.data.categories) { | |||||
app.categories = response.data.categories ; | |||||
for(keyCategory in response.data.categories) { | |||||
var category = response.data.categories[keyCategory]; | |||||
if(category.id && app.countProductsByCategory(category)) { | |||||
app.setCategoryCurrent(category, true) ; | |||||
break; | |||||
if (response.data.categories) { | |||||
app.categories = response.data.categories; | |||||
for (keyCategory in response.data.categories) { | |||||
var category = response.data.categories[keyCategory]; | |||||
if (category.id && app.countProductsByCategory(category)) { | |||||
app.setCategoryCurrent(category, true); | |||||
break; | |||||
} | |||||
} | } | ||||
} | } | ||||
} | |||||
setTimeout(function() { | |||||
app.responsive(); | |||||
opendistrib_products(); | |||||
}, 500); | |||||
setTimeout(function () { | |||||
app.responsive(); | |||||
opendistrib_products(); | |||||
}, 500); | |||||
app.loading = false ; | |||||
app.loadingInit = false ; | |||||
app.loading = false; | |||||
app.loadingProducts = false; | |||||
app.loadingInit = false; | |||||
} | |||||
}); | }); | ||||
}, | }, | ||||
updateOrder: function(response) { | updateOrder: function(response) { | ||||
} | } | ||||
}, | }, | ||||
changeStep: function(step) { | changeStep: function(step) { | ||||
this.errors = [] ; | this.errors = [] ; | ||||
var oldStep = this.step ; | var oldStep = this.step ; | ||||
} | } | ||||
if(!this.errors.length) { | if(!this.errors.length) { | ||||
this.step = step ; | this.step = step ; | ||||
this.init('basic', oldStep, step) ; | |||||
this.init('basic', false) ; | |||||
} | } | ||||
}, | }, | ||||
dayClickList: function(event) { | dayClickList: function(event) { | ||||
this.nextStep() ; | this.nextStep() ; | ||||
}, | }, | ||||
productQuantityClick: function(product, quantity) { | productQuantityClick: function(product, quantity) { | ||||
if( this.products[product.index].quantity_form + quantity >= 0 && | |||||
(this.products[product.index].quantity_form + quantity <= (this.products[product.index].quantity_remaining * this.products[product.index].coefficient_unit) || | |||||
!this.products[product.index].quantity_max) | |||||
if(this.products[product.index].quantity_form + quantity >= 0 | |||||
&& (this.products[product.index].quantity_max == null | |||||
|| this.products[product.index].quantity_form + quantity <= this.products[product.index].quantity_max * this.products[product.index].coefficient_unit) | |||||
&& (this.products[product.index].quantity_remaining == null | |||||
|| (quantity <= (this.products[product.index].quantity_remaining * this.products[product.index].coefficient_unit))) | |||||
) { | ) { | ||||
var theQuantity = parseFloat(this.products[product.index].quantity_form) + parseFloat(quantity); | var theQuantity = parseFloat(this.products[product.index].quantity_form) + parseFloat(quantity); | ||||
this.products[product.index].quantity_form = parseFloat(theQuantity.toFixed(2)) ; | this.products[product.index].quantity_form = parseFloat(theQuantity.toFixed(2)) ; | ||||
this.init('first', true); | |||||
} | } | ||||
}, | }, | ||||
oneProductOrdered: function() { | oneProductOrdered: function() { | ||||
} | } | ||||
// products | // products | ||||
var productsArray = {} ; | |||||
for(var key in this.products) { | |||||
if( this.products[key].quantity_form != null && | |||||
this.products[key].quantity_form > 0) { | |||||
productsArray[this.products[key].id] = this.products[key].quantity_form ; | |||||
} | |||||
} | |||||
var productsArray = this.getProductsArray(); | |||||
app.disableConfirmButton = true ; | app.disableConfirmButton = true ; | ||||
axios.post('ajax-process', { | axios.post('ajax-process', { | ||||
} | } | ||||
}); | }); | ||||
}, | }, | ||||
getProductsArray: function() { | |||||
var productsArray = {} ; | |||||
for(var key in this.products) { | |||||
if( this.products[key].quantity_form != null && | |||||
this.products[key].quantity_form > 0) { | |||||
productsArray[this.products[key].id] = this.products[key].quantity_form ; | |||||
} | |||||
} | |||||
return productsArray; | |||||
}, | |||||
checkProducts: function() { | checkProducts: function() { | ||||
if(!this.oneProductOrdered()) { | if(!this.oneProductOrdered()) { | ||||
this.errors.push('Veuillez sélectionner au moins un produit.') ; | this.errors.push('Veuillez sélectionner au moins un produit.') ; |