@@ -0,0 +1,58 @@ | |||
<?php | |||
/** | |||
Copyright distrib (2018) | |||
contact@opendistrib.net | |||
Ce logiciel est un programme informatique servant à aider les producteurs | |||
à distribuer leur production en circuits courts. | |||
Ce logiciel est régi par la licence CeCILL soumise au droit français et | |||
respectant les principes de diffusion des logiciels libres. Vous pouvez | |||
utiliser, modifier et/ou redistribuer ce programme sous les conditions | |||
de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA | |||
sur le site "http://www.cecill.info". | |||
En contrepartie de l'accessibilité au code source et des droits de copie, | |||
de modification et de redistribution accordés par cette licence, il n'est | |||
offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons, | |||
seule une responsabilité restreinte pèse sur l'auteur du programme, le | |||
titulaire des droits patrimoniaux et les concédants successifs. | |||
A cet égard l'attention de l'utilisateur est attirée sur les risques | |||
associés au chargement, à l'utilisation, à la modification et/ou au | |||
développement et à la reproduction du logiciel par l'utilisateur étant | |||
donné sa spécificité de logiciel libre, qui peut le rendre complexe à | |||
manipuler et qui le réserve donc à des développeurs et des professionnels | |||
avertis possédant des connaissances informatiques approfondies. Les | |||
utilisateurs sont donc invités à charger et tester l'adéquation du | |||
logiciel à leurs besoins dans des conditions permettant d'assurer la | |||
sécurité de leurs systèmes et ou de leurs données et, plus généralement, | |||
à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. | |||
Le fait que vous puissiez accéder à cet en-tête signifie que vous avez | |||
pris connaissance de la licence CeCILL, et que vous en avez accepté les | |||
termes. | |||
*/ | |||
namespace backend\assets; | |||
use yii\web\AssetBundle; | |||
use yii ; | |||
class VuejsSettingFormAsset extends \common\components\MyAssetBundle | |||
{ | |||
public $basePath = '@webroot'; | |||
public $baseUrl = '@web'; | |||
public $css = []; | |||
public $js = []; | |||
public $depends = [ | |||
'common\assets\CommonAsset' | |||
]; | |||
public function __construct() | |||
{ | |||
parent::__construct() ; | |||
$this->addAsset('js','js/vuejs/setting-form.js') ; | |||
} | |||
} |
@@ -577,7 +577,8 @@ class DistributionController extends BackendController | |||
return $distributionModule->getExportManager()->getGenerator($name)->generate($distribution); | |||
} | |||
catch(ErrorException $exception) { | |||
$this->setFlash('error', "Une erreur est survenue lors de la génération de l'export."); | |||
//$this->setFlash('error', "Une erreur est survenue lors de la génération de l'export."); | |||
$this->setFlash('error', $exception->getMessage()); | |||
return $this->redirectReferer(); | |||
} | |||
} |
@@ -71,7 +71,7 @@ class FeatureAdminController extends BackendController | |||
public function actionIndex() | |||
{ | |||
$featureModule = $this->getFeatureModule(); | |||
$dataProviderFeatures = $featureModule->getRepository()->queryAll()->getDataProvider(100); | |||
$dataProviderFeatures = $featureModule->getRepository()->queryDefaultAll()->getDataProvider(100); | |||
return $this->render('index', [ | |||
'producerCurrent' => $this->getProducerCurrent(), | |||
@@ -85,30 +85,30 @@ class FeatureAdminController extends BackendController | |||
$feature = $this->findModel($id); | |||
if($status) { | |||
$featureManager->enable($feature); | |||
$featureManager->enableFeature($feature); | |||
$messageResponse = 'La fonctionnalité "'.Html::encode($feature->name).'" a bien été activée'; | |||
} | |||
else { | |||
$featureManager->disable($feature); | |||
$featureManager->disableFeature($feature); | |||
$messageResponse = 'La fonctionnalité "'.Html::encode($feature->name).'" a bien été désactivée'; | |||
} | |||
return Ajax::responseSuccess($messageResponse); | |||
} | |||
public function actionToggleStatusFeatureProducer(int $id, bool $status = null) | |||
public function actionToggleStatusFeatureProducer(int $id, int $status = null) | |||
{ | |||
$featureManager = $this->getFeatureModule()->getManager(); | |||
$feature = $this->findModel($id); | |||
if(is_null($status)) { | |||
$featureManager->defaultForProducer($feature); | |||
$featureManager->defaultFeatureForProducer($feature); | |||
} | |||
elseif($status == 0) { | |||
$featureManager->disableForProducer($feature); | |||
$featureManager->disableFeatureForProducer($feature); | |||
} | |||
elseif($status == 1) { | |||
$featureManager->enableForProducer($feature); | |||
$featureManager->enableFeatureForProducer($feature); | |||
} | |||
return $this->redirectReferer(); | |||
@@ -128,6 +128,18 @@ class FeatureAdminController extends BackendController | |||
} | |||
} | |||
public function actionPosition() | |||
{ | |||
$array = \Yii::$app->request->post('array'); | |||
$positionArray = json_decode(stripslashes($array)); | |||
foreach ($positionArray as $id => $position) { | |||
$feature = $this->findModel($id); | |||
$feature->position = $position; | |||
$feature->save(); | |||
} | |||
} | |||
protected function findModel($id) | |||
{ | |||
$featureModule = $this->getFeatureModule(); |
@@ -94,17 +94,20 @@ class ProducerController extends BackendController | |||
$logoFilenameOld = $model->logo; | |||
$photoFilenameOld = $model->photo; | |||
$documentImageBottomFilenameOld = $model->document_image_bottom; | |||
$producerBuilder->initOptionDashboardDatesDisplay($model); | |||
if ($model->load(\Yii::$app->request->post())) { | |||
$model->logoFile = UploadedFile::getInstance($model, 'logoFile'); | |||
$model->photoFile = UploadedFile::getInstance($model, 'photoFile'); | |||
$model->document_image_bottomFile = UploadedFile::getInstance($model, 'document_image_bottomFile'); | |||
if($model->validate()) { | |||
$producerBuilder->processUploadImage($model, 'logo', $logoFilenameOld, $request->post('delete_logo', 0)); | |||
$producerBuilder->processUploadImage($model, 'photo', $photoFilenameOld, $request->post('delete_photo', 0)); | |||
$producerBuilder->processUploadImage($model, 'document_image_bottom', $documentImageBottomFilenameOld, $request->post('delete_document_image_bottom', 0)); | |||
$producerBuilder->initOptionDashboardDatesBeforeSave($model); | |||
$producerBuilder->savePrivateKeysStripe($model); | |||
$model->save(); |
@@ -0,0 +1,86 @@ | |||
<?php | |||
/** | |||
* Copyright distrib (2018) | |||
* | |||
* contact@opendistrib.net | |||
* | |||
* Ce logiciel est un programme informatique servant à aider les producteurs | |||
* à distribuer leur production en circuits courts. | |||
* | |||
* Ce logiciel est régi par la licence CeCILL soumise au droit français et | |||
* respectant les principes de diffusion des logiciels libres. Vous pouvez | |||
* utiliser, modifier et/ou redistribuer ce programme sous les conditions | |||
* de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA | |||
* sur le site "http://www.cecill.info". | |||
* | |||
* En contrepartie de l'accessibilité au code source et des droits de copie, | |||
* de modification et de redistribution accordés par cette licence, il n'est | |||
* offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons, | |||
* seule une responsabilité restreinte pèse sur l'auteur du programme, le | |||
* titulaire des droits patrimoniaux et les concédants successifs. | |||
* | |||
* A cet égard l'attention de l'utilisateur est attirée sur les risques | |||
* associés au chargement, à l'utilisation, à la modification et/ou au | |||
* développement et à la reproduction du logiciel par l'utilisateur étant | |||
* donné sa spécificité de logiciel libre, qui peut le rendre complexe à | |||
* manipuler et qui le réserve donc à des développeurs et des professionnels | |||
* avertis possédant des connaissances informatiques approfondies. Les | |||
* utilisateurs sont donc invités à charger et tester l'adéquation du | |||
* logiciel à leurs besoins dans des conditions permettant d'assurer la | |||
* sécurité de leurs systèmes et ou de leurs données et, plus généralement, | |||
* à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. | |||
* | |||
* Le fait que vous puissiez accéder à cet en-tête signifie que vous avez | |||
* pris connaissance de la licence CeCILL, et que vous en avez accepté les | |||
* termes. | |||
*/ | |||
namespace backend\controllers; | |||
use backend\forms\AdminSettingsForm; | |||
use common\helpers\Ajax; | |||
use yii\filters\AccessControl; | |||
use yii\helpers\Html; | |||
use yii\web\NotFoundHttpException; | |||
/** | |||
* UserController implements the CRUD actions for User model. | |||
*/ | |||
class SettingAdminController extends BackendController | |||
{ | |||
public function behaviors() | |||
{ | |||
return [ | |||
'access' => [ | |||
'class' => AccessControl::class, | |||
'rules' => [ | |||
[ | |||
'allow' => true, | |||
'roles' => ['@'], | |||
'matchCallback' => function ($rule, $action) { | |||
return $this->getUserModule() | |||
->getAuthorizationChecker() | |||
->isGrantedAsAdministrator($this->getUserCurrent()); | |||
} | |||
] | |||
], | |||
], | |||
]; | |||
} | |||
public function actionIndex() | |||
{ | |||
$settingModule = $this->getSettingModule(); | |||
$model = new AdminSettingsForm(); | |||
if($model->load(\Yii::$app->request->post()) && $model->validate()) { | |||
foreach($settingModule->getAdminSettingDefinition()->getSettingDetailsFlat() as $settingDetail) { | |||
$settingModule->getAdminSettingBag()->set($settingDetail->getName(), $model->{$settingDetail->getName()}); | |||
} | |||
} | |||
return $this->render('index', [ | |||
'model' => $model | |||
]); | |||
} | |||
} |
@@ -532,7 +532,7 @@ class UserController extends BackendController | |||
} | |||
} | |||
$pointsSaleArray = PointSale::find()->where(['id_producer' => GlobalParam::getCurrentProducerId()])->all(); | |||
$pointsSaleArray = PointSale::find()->where(['id_producer' => GlobalParam::getCurrentProducerId(), 'status' => 1])->all(); | |||
$pointSale = null; | |||
if ($idPointSale) { |
@@ -0,0 +1,57 @@ | |||
<?php | |||
namespace backend\forms; | |||
use common\logic\Setting\SettingModule; | |||
use yii\base\Model; | |||
class AdminSettingsForm extends Model | |||
{ | |||
public function __get($name) | |||
{ | |||
return SettingModule::getInstance()->getAdminSettingBag()->get($name); | |||
} | |||
public function __set($name, $value) | |||
{ | |||
$this->$name = $value; | |||
} | |||
public function rules() | |||
{ | |||
$rulesArray = []; | |||
$typesArray = [ | |||
'string' => ['string', 'text'], | |||
'date' => ['date'], | |||
'boolean' => ['boolean'], | |||
'integer' => ['integer'], | |||
'double' => ['double', 'float'], | |||
]; | |||
foreach($typesArray as $rule => $typesSettingArray) { | |||
$rulesArray[] = [$this->getSettingNamesByTypeArray($typesSettingArray), $rule]; | |||
} | |||
return $rulesArray; | |||
} | |||
public function attributeLabels() | |||
{ | |||
$attributeLabelsArray = []; | |||
foreach(SettingModule::getInstance()->getAdminSettingDefinition()->getSettingDetailsFlat() as $settingDetail) { | |||
$attributeLabelsArray[$settingDetail->getName()] = $settingDetail->getLabel(); | |||
} | |||
return $attributeLabelsArray; | |||
} | |||
public function getSettingNamesByTypeArray(array $typesSettingArray): array | |||
{ | |||
$settingNamesTypeArray = []; | |||
foreach(SettingModule::getInstance()->getAdminSettingDefinition()->getSettingDetailsFlat() as $settingDetail) { | |||
if(in_array($settingDetail->getType(), $typesSettingArray)) { | |||
$settingNamesTypeArray[] = $settingDetail->getName(); | |||
} | |||
} | |||
return $settingNamesTypeArray; | |||
} | |||
} | |||
?> |
@@ -1,35 +1,20 @@ | |||
<?php | |||
use common\logic\Order\Order\Module\OrderModule; | |||
use yii\helpers\Html; | |||
use common\logic\Distribution\Distribution\Export\DistributionShoppingCartLabelsPdfGenerator; | |||
$orderModule = OrderModule::getInstance(); | |||
$distributionShoppingCartLabelsPdfGenerator = DistributionShoppingCartLabelsPdfGenerator::getInstance(); | |||
$index = 0; | |||
?> | |||
<?php | |||
$i = 0; | |||
foreach($ordersArray as $key => $order): | |||
foreach($ordersArray as $key => $order) { | |||
$index ++; | |||
?> | |||
<div class="shopping-cart-label"> | |||
<div class="inner"> | |||
<div class="username"> | |||
<?= $orderModule->getOrderUsername($order); ?> | |||
</div> | |||
<div class="point-sale"> | |||
<?= date('d/m', strtotime($distribution->date)); ?> • | |||
<?= Html::encode($order->pointSale->name); ?> | |||
</div> | |||
<div class="products"> | |||
<?= $orderModule->getCartSummary($order); ?> | |||
</div> | |||
</div> | |||
</div> | |||
<?php if($index == $shoppingCartLabelsPerColumn) { | |||
echo $distributionShoppingCartLabelsPdfGenerator->getShoppingCartLabelAsHtml($order); | |||
if($index == $shoppingCartLabelsPerColumn) { | |||
$index = 0; | |||
} ?> | |||
<?php if($index == 0 && $key !== array_key_last($ordersArray)): ?> | |||
<columnbreak /> | |||
<?php endif; ?> | |||
<?php endforeach; ?> | |||
} | |||
if(!$isSpecificFormat && $index == 0 && $key !== array_key_last($ordersArray)) { | |||
echo '<columnbreak />'; | |||
} | |||
} | |||
?> |
@@ -50,6 +50,15 @@ $this->addBreadcrumb($this->getTitle()); | |||
<?= GridView::widget([ | |||
'dataProvider' => $dataProviderFeatures, | |||
'columns' => [ | |||
[ | |||
'attribute' => 'position', | |||
'headerOptions' => ['class' => 'position'], | |||
'format' => 'raw', | |||
'filter' => '', | |||
'value' => function ($model) { | |||
return '<a class="btn-position btn btn-default" href="javascript:void(0);"><span class="glyphicon glyphicon-resize-vertical"></span></a>'; | |||
} | |||
], | |||
'name', | |||
[ | |||
'attribute' => 'status', | |||
@@ -121,7 +130,7 @@ $this->addBreadcrumb($this->getTitle()); | |||
'format' => 'raw', | |||
'value' => function ($model) { | |||
if($model->is_paid_feature && $model->price) { | |||
return Price::format($model->price); | |||
return Price::format($model->price, 0); | |||
} | |||
return ''; |
@@ -49,7 +49,14 @@ $this->addBreadcrumb('Modifier') ; | |||
<?php $form = ActiveForm::begin(); ?> | |||
<?= $form->field($model, 'status')->radioList([1 => 'Oui', 0 => 'Non']) ?> | |||
<?= $form->field($model, 'name') ?> | |||
<?= $form->field($model, 'description')->textarea(['rows' => '4']) ; ?> | |||
<?= $form->field($model, 'description')->widget(letyii\tinymce\Tinymce::class, [ | |||
'options' => [ | |||
'id' => 'testid', | |||
], | |||
'configs' => [ // Read more: https://www.tiny.cloud/docs/tinymce/6/full-featured-open-source-demo/ | |||
'plugins' => 'preview importcss searchreplace autolink autosave save directionality code visualblocks visualchars fullscreen image link media template codesample table charmap pagebreak nonbreaking anchor insertdatetime advlist lists wordcount help charmap quickbars emoticons accordion' , | |||
] | |||
]) ; ?> | |||
<?= $form->field($model, 'only_for_selected_producers')->radioList([1 => 'Oui', 0 => 'Non']) ?> | |||
<?= $form->field($model, 'is_paid_feature')->radioList([1 => 'Oui', 0 => 'Non']) ?> | |||
<?= $form->field($model, 'price') ?> |
@@ -37,14 +37,14 @@ | |||
*/ | |||
use common\helpers\GlobalParam; | |||
use common\logic\Feature\Feature\Model\Feature; | |||
use common\logic\Feature\Feature\Feature; | |||
use common\logic\User\User\Module\UserModule; | |||
$producerModule = $this->getProducerModule(); | |||
$userModule = UserModule::getInstance(); | |||
$userProducerModule = $this->getUserProducerModule(); | |||
$ticketModule = $this->getTicketModule(); | |||
$featureManager = $this->getFeatureModule()->getManager(); | |||
$featureChecker = $this->getFeatureModule()->getChecker(); | |||
$producer = GlobalParam::getCurrentProducer(); | |||
$userCurrent = GlobalParam::getCurrentUser(); | |||
@@ -106,7 +106,7 @@ $isUserCurrentGrantedAsProducer = $userModule->getAuthorizationChecker()->isGran | |||
'items' => [ | |||
['label' => 'Liste', 'icon' => 'th-list', 'url' => ['/product/index'], 'visible' => $isUserCurrentGrantedAsProducer], | |||
['label' => 'Catégories', 'icon' => 'book', 'url' => ['/product-category/index'], 'visible' => $isUserCurrentGrantedAsProducer], | |||
['label' => 'Import prix', 'icon' => 'upload', 'url' => ['/product/price-import'], 'visible' => $isUserCurrentGrantedAsProducer && $featureManager->isEnabled(Feature::ALIAS_PRODUCT_PRICE_IMPORT)], | |||
['label' => 'Import prix', 'icon' => 'upload', 'url' => ['/product/price-import'], 'visible' => $isUserCurrentGrantedAsProducer && $featureChecker->isEnabled(Feature::ALIAS_PRODUCT_PRICE_IMPORT)], | |||
] | |||
], | |||
['label' => 'Points de vente', 'icon' => 'map-marker', 'url' => ['/point-sale/index'], 'visible' => $isUserCurrentGrantedAsProducer, 'active' => Yii::$app->controller->id == 'point-sale'], | |||
@@ -182,6 +182,7 @@ $isUserCurrentGrantedAsProducer = $userModule->getAuthorizationChecker()->isGran | |||
['label' => 'Commandes clients', 'icon' => 'calendar', 'url' => ['/stats-admin/customer-orders'], 'visible' => $isUserCurrentGrantedAsAdministrator], | |||
], | |||
], | |||
['label' => 'Paramètres', 'icon' => 'cog', 'url' => ['/setting-admin/index'], 'visible' => $isUserCurrentGrantedAsAdministrator && $featureChecker->isEnabled(Feature::ALIAS_SETTINGS)], | |||
['label' => 'Fonctionnalités', 'icon' => 'flag', 'url' => ['/feature-admin/index'], 'visible' => $isUserCurrentGrantedAsAdministrator], | |||
['label' => 'Tranches de prix', 'icon' => 'eur', 'url' => ['/producer-price-range-admin/index'], 'visible' => $isUserCurrentGrantedAsAdministrator], | |||
['label' => 'Taxes', 'icon' => 'eur', 'url' => ['/tax-rate-admin/index'], 'visible' => $isUserCurrentGrantedAsAdministrator], |
@@ -88,6 +88,8 @@ $distributionModule = DistributionModule::getInstance(); | |||
->dropDownList( ProductPrice::percentValues(), [])->hint('Pourcentage appliqué aux prix de chaque produit dans ce point de vente.');*/ ?> | |||
<?= $form->field($model, 'maximum_number_orders')->textInput() ?> | |||
<?= $form->field($model, 'minimum_order_amount')->textInput() ?> | |||
<div id="delivery-days"> | |||
<h2>Jours de livraison</h2> |
@@ -39,6 +39,9 @@ | |||
use common\helpers\Dropdown; | |||
use common\helpers\GlobalParam; | |||
use common\logic\Distribution\Distribution\Module\DistributionModule; | |||
use common\logic\Distribution\Distribution\Service\ExportManager; | |||
use common\logic\Feature\Feature\Feature; | |||
use common\logic\Feature\Feature\FeatureModule; | |||
use common\logic\User\User\Module\UserModule; | |||
use common\logic\User\UserGroup\Module\UserGroupModule; | |||
use yii\helpers\Html; | |||
@@ -53,6 +56,7 @@ use yii\helpers\ArrayHelper; | |||
$userModule = UserModule::getInstance(); | |||
$userGroupModule = UserGroupModule::getInstance(); | |||
$distributionExportManager = DistributionModule::getInstance()->getExportManager(); | |||
$featureChecker = FeatureModule::getInstance()->getChecker(); | |||
$userCurrent = GlobalParam::getCurrentUser(); | |||
@@ -304,8 +308,13 @@ $this->addBreadcrumb($this->getTitle()); | |||
->dropDownList(Dropdown::noYesChoices()); ?> | |||
<?= $form->field($model, 'option_csv_export_by_piece') | |||
->dropDownList(Dropdown::noYesChoices()); ?> | |||
<?= $form->field($model, 'export_shopping_cart_labels_number_per_column') | |||
->dropDownList(Dropdown::numberChoices(1, 20)); ?> | |||
<?php if($featureChecker->isEnabled(Feature::ALIAS_EXPORT_SHOPPING_CART_LABELS_ADVANCED)): ?> | |||
<?= $form->field($model, 'export_shopping_cart_labels_format') | |||
->dropDownList($distributionExportManager->getGenerator(ExportManager::SHOPPING_CART_LABELS_PDF)->populateDropdownSpecificFormats()); ?> | |||
<?php else: ?> | |||
<?= $form->field($model, 'export_shopping_cart_labels_number_per_column') | |||
->dropDownList(Dropdown::numberChoices(1, 20)); ?> | |||
<?php endif; ?> | |||
</div> | |||
</div> | |||
@@ -350,21 +359,27 @@ $this->addBreadcrumb($this->getTitle()); | |||
<?= $form->field($model, 'option_check_by_default_prevent_user_credit') | |||
->dropDownList(Dropdown::noYesChoices()); ?> | |||
<h4>Paiement en ligne</h4> | |||
<?= $form->field($model, 'online_payment') | |||
->dropDownList(Dropdown::noYesChoices()); ?> | |||
<?= $form->field($model, 'option_online_payment_minimum_amount') | |||
->hint('Valeur par défaut si non défini : ' . Producer::ONLINE_PAYMENT_MINIMUM_AMOUNT_DEFAULT . ' €') | |||
->textInput(); ?> | |||
<?= $form->field($model, 'option_stripe_mode_test')->dropDownList(Dropdown::noYesChoices()); ?> | |||
<?= $form->field($model, 'option_online_payment_type') | |||
->dropDownList([ | |||
'credit' => 'Alimentation du crédit', | |||
'order' => 'Paiement à la commande', | |||
], []); ?> | |||
<?= $form->field($model, 'option_stripe_public_key')->textInput(); ?> | |||
<?= $form->field($model, 'option_stripe_private_key')->textInput(); ?> | |||
<?= $form->field($model, 'option_stripe_endpoint_secret')->textInput(); ?> | |||
<?php if($featureChecker->isEnabled(Feature::ALIAS_ONLINE_PAYMENT)): ?> | |||
<h4>Paiement en ligne</h4> | |||
<?php if($userModule->getAuthorizationChecker()->isGrantedAsAdministrator($userCurrent)): ?> | |||
<?= $form->field($model, 'online_payment') | |||
->dropDownList(Dropdown::noYesChoices()); ?> | |||
<?= $form->field($model, 'option_stripe_mode_test')->dropDownList(Dropdown::noYesChoices()); ?> | |||
<?= $form->field($model, 'option_online_payment_type') | |||
->dropDownList([ | |||
'credit' => 'Alimentation du crédit', | |||
'order' => 'Paiement à la commande', | |||
], []); ?> | |||
<?= $form->field($model, 'option_stripe_public_key')->textInput(); ?> | |||
<?= $form->field($model, 'option_stripe_private_key')->textInput(); ?> | |||
<?= $form->field($model, 'option_stripe_endpoint_secret')->textInput(); ?> | |||
<?php endif; ?> | |||
<?= $form->field($model, 'option_online_payment_minimum_amount') | |||
->hint('Valeur par défaut si non défini : ' . Producer::ONLINE_PAYMENT_MINIMUM_AMOUNT_DEFAULT . ' €') | |||
->textInput(); ?> | |||
<?php endif; ?> | |||
</div> | |||
</div> | |||
@@ -431,6 +446,15 @@ $this->addBreadcrumb($this->getTitle()); | |||
->hint("Affichées juste en dessous de l'adresse"); ?> | |||
<?= $form->field($model, 'document_infos_bottom') | |||
->textarea(['rows' => 8]) ?> | |||
<?= $form->field($model, 'document_image_bottomFile')->fileInput()->hint('') ?> | |||
<?php | |||
if (strlen($model->document_image_bottom)) { | |||
echo '<img src="' . Yii::$app->urlManagerProducer->getHostInfo() . '/' . Yii::$app->urlManagerProducer->baseUrl . '/uploads/' . $model->document_image_bottom . '" width="400px" /><br />'; | |||
echo '<input type="checkbox" name="delete_document_image_bottom" id="delete_document_image_bottom" /> <label for="delete_document_image_bottom">Supprimer l\'image</label><br /><br />'; | |||
} | |||
?> | |||
<?= $form->field($model, 'document_infos_quotation') | |||
->textarea(['rows' => 8]) ?> | |||
<?= $form->field($model, 'document_infos_invoice') |
@@ -0,0 +1,112 @@ | |||
<?php | |||
/** | |||
* Copyright distrib (2018) | |||
* | |||
* contact@opendistrib.net | |||
* | |||
* Ce logiciel est un programme informatique servant à aider les producteurs | |||
* à distribuer leur production en circuits courts. | |||
* | |||
* Ce logiciel est régi par la licence CeCILL soumise au droit français et | |||
* respectant les principes de diffusion des logiciels libres. Vous pouvez | |||
* utiliser, modifier et/ou redistribuer ce programme sous les conditions | |||
* de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA | |||
* sur le site "http://www.cecill.info". | |||
* | |||
* En contrepartie de l'accessibilité au code source et des droits de copie, | |||
* de modification et de redistribution accordés par cette licence, il n'est | |||
* offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons, | |||
* seule une responsabilité restreinte pèse sur l'auteur du programme, le | |||
* titulaire des droits patrimoniaux et les concédants successifs. | |||
* | |||
* A cet égard l'attention de l'utilisateur est attirée sur les risques | |||
* associés au chargement, à l'utilisation, à la modification et/ou au | |||
* développement et à la reproduction du logiciel par l'utilisateur étant | |||
* donné sa spécificité de logiciel libre, qui peut le rendre complexe à | |||
* manipuler et qui le réserve donc à des développeurs et des professionnels | |||
* avertis possédant des connaissances informatiques approfondies. Les | |||
* utilisateurs sont donc invités à charger et tester l'adéquation du | |||
* logiciel à leurs besoins dans des conditions permettant d'assurer la | |||
* sécurité de leurs systèmes et ou de leurs données et, plus généralement, | |||
* à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. | |||
* | |||
* Le fait que vous puissiez accéder à cet en-tête signifie que vous avez | |||
* pris connaissance de la licence CeCILL, et que vous en avez accepté les | |||
* termes. | |||
*/ | |||
use common\logic\Setting\SettingModule; | |||
use lo\widgets\Toggle; | |||
use yii\bootstrap\ActiveForm; | |||
use yii\helpers\Html; | |||
\backend\assets\VuejsSettingFormAsset::register($this); | |||
$settingModule = SettingModule::getInstance(); | |||
$adminSettingDefinition = $settingModule->getAdminSettingDefinition(); | |||
$this->setTitle('Paramètres'); | |||
$this->addBreadcrumb($this->getTitle()); | |||
?> | |||
<script> | |||
var appInitValues = { | |||
sectionsArray: <?php echo json_encode($adminSettingDefinition->getSectionsArray()); ?>, | |||
}; | |||
</script> | |||
<div class="setting-admin-index setting-form" id="app-setting-admin"> | |||
<div id="nav-params"> | |||
<a v-for="section in sectionsArray" :class="'btn '+((currentSection == section.name) ? 'btn-primary' : 'btn-default')" | |||
@click="changeSection(section)" :href="'#'+section.name"> | |||
{{ section.nameDisplay }} | |||
</a> | |||
</div> | |||
<?php $form = ActiveForm::begin(); ?> | |||
<?php foreach($adminSettingDefinition->getSettingDetails() as $sectionName => $sectionsArray): ?> | |||
<div v-show="currentSection == '<?= $sectionName ?>'" class="panel panel-default"> | |||
<div class="panel-body"> | |||
<?php foreach($sectionsArray as $subSectionName => $subSectionsArray): ?> | |||
<h4><?php echo $adminSettingDefinition->getSectionLabelBySectionName($subSectionName); ?></h4> | |||
<?php foreach($subSectionsArray as $settingDetail): ?> | |||
<?php echo field($form, $model, $settingDetail); ?> | |||
<?php endforeach; ?> | |||
<?php endforeach; ?> | |||
</div> | |||
</div> | |||
<?php endforeach; ?> | |||
<div class="form-group"> | |||
<?= Html::submitButton('Sauvegarder', ['class' => 'btn btn-primary']) ?> | |||
</div> | |||
<?php ActiveForm::end(); ?> | |||
</div> | |||
<?php | |||
function field($form, $model, $settingDetail) { | |||
$field = $form->field($model, $settingDetail->getName()); | |||
if($settingDetail->getFormType() == 'checkbox') { | |||
return $field->checkbox(); | |||
} | |||
elseif($settingDetail->getFormType() == 'toggle') { | |||
return $form->field($model, $settingDetail->getName(), ['options' => ['class' => 'form-group form-toggle']])->widget(Toggle::class, ['options' => ['data-on' => 'Oui', 'data-off' => 'Non', 'data-offstyle' => 'default']]); | |||
} | |||
elseif($settingDetail->getFormType() == 'select') { | |||
return $field->dropDownList($settingDetail->getOptions()); | |||
} | |||
elseif($settingDetail->getFormType() == 'textarea') { | |||
return $field->textarea(['rows' => 4]); | |||
} | |||
elseif($settingDetail->getFormType() == 'input') { | |||
return $field->textInput(); | |||
} | |||
else { | |||
return '<div class="form-group"><span class="glyphicon glyphicon-alert"></span> Type de champ non défini pour le paramètre "'.$settingDetail->getName().'"</div>'; | |||
} | |||
} | |||
?> |
@@ -41,7 +41,12 @@ use common\logic\Ticket\Ticket\Module\TicketModule; | |||
use yii\helpers\Html; | |||
use yii\grid\GridView; | |||
/** | |||
* @var $this common\components\ViewBackend | |||
*/ | |||
$ticketModule = TicketModule::getInstance(); | |||
$adminSettingBag = $this->getSettingModule()->getAdminSettingBag(); | |||
$userCurrent = $this->getUserCurrent(); | |||
$this->setTitle('Support & contact'); | |||
$this->addBreadcrumb($this->getTitle()); | |||
@@ -62,7 +67,7 @@ $this->addBreadcrumb($this->getTitle()); | |||
<span class="info-box-text">Me contacter directement</span> | |||
<span class="info-box-text"> | |||
<br/> | |||
<strong><?= Yii::$app->parameterBag->get('adminPhoneNumber'); ?></strong> | |||
<strong><?= $adminSettingBag->get('administratorPhoneNumber'); ?></strong> | |||
</span> | |||
</div> | |||
</div> | |||
@@ -89,7 +94,7 @@ $this->addBreadcrumb($this->getTitle()); | |||
<div class="info-box"> | |||
<span class="info-box-icon bg-yellow"><i class="fa fa-envelope"></i></span> | |||
<div class="info-box-content"> | |||
<span class="info-box-text"><br/><?= Html::a("M'envoyer un email", 'mailto:'.Yii::$app->parameterBag->get('adminEmail'), ['class' => 'btn btn-sm btn-default']); ?></span> | |||
<span class="info-box-text"><br/><?= Html::a("M'envoyer un email", 'mailto:'.$adminSettingBag->get('administratorEmail'), ['class' => 'btn btn-sm btn-default']); ?></span> | |||
</div> | |||
</div> | |||
</div> |
@@ -428,7 +428,7 @@ a.btn.btn-primary .glyphicon-triangle-bottom, button.btn.btn-primary .glyphicon- | |||
/* line 344, ../sass/screen.scss */ | |||
#nav-params { | |||
margin-bottom: 30px; | |||
margin-bottom: 20px; | |||
} | |||
/* line 347, ../sass/screen.scss */ | |||
#nav-params a { | |||
@@ -2802,6 +2802,49 @@ termes. | |||
width: 100px; | |||
} | |||
/* line 4, ../sass/setting/_form.scss */ | |||
.setting-form .panel h4 { | |||
font-size: 23px; | |||
margin-bottom: 20px; | |||
text-transform: uppercase; | |||
border-bottom: solid 1px gray; | |||
} | |||
/* line 10, ../sass/setting/_form.scss */ | |||
.setting-form .panel h4:not(:first-child) { | |||
margin-top: 45px; | |||
} | |||
/* line 16, ../sass/setting/_form.scss */ | |||
.setting-form .form-group.has-success, .setting-form .form-group.has-success label { | |||
color: #333; | |||
} | |||
/* line 21, ../sass/setting/_form.scss */ | |||
.setting-form .form-group .checkbox input { | |||
position: relative; | |||
top: -1px; | |||
margin-right: 3px; | |||
} | |||
/* line 30, ../sass/setting/_form.scss */ | |||
.setting-form .form-group.form-toggle .control-label { | |||
position: relative; | |||
top: 7px; | |||
left: 10px; | |||
} | |||
/* line 36, ../sass/setting/_form.scss */ | |||
.setting-form .form-group.form-toggle .toggle { | |||
-moz-border-radius: 20px; | |||
-webkit-border-radius: 20px; | |||
border-radius: 20px; | |||
float: left; | |||
} | |||
/* line 41, ../sass/setting/_form.scss */ | |||
.setting-form .form-group.form-toggle .toggle .toggle-group .btn.toggle-on { | |||
color: white; | |||
} | |||
/* line 45, ../sass/setting/_form.scss */ | |||
.setting-form .form-group.form-toggle .toggle .toggle-group .btn.toggle-off { | |||
border-color: white; | |||
} | |||
/** | |||
Copyright distrib (2018) | |||
@@ -464,7 +464,13 @@ function opendistrib_features_index() { | |||
.then(function (response) { | |||
appAlerts.alertResponse(response); | |||
}); | |||
}) | |||
}); | |||
opendistrib_sortable_list( | |||
'.feature-admin-index', | |||
'.btn-position', | |||
'feature-admin/position' | |||
); | |||
} | |||
function opendistrib_datepicker() { |
@@ -0,0 +1,63 @@ | |||
/** | |||
Copyright distrib (2018) | |||
contact@opendistrib.net | |||
Ce logiciel est un programme informatique servant à aider les producteurs | |||
à distribuer leur production en circuits courts. | |||
Ce logiciel est régi par la licence CeCILL soumise au droit français et | |||
respectant les principes de diffusion des logiciels libres. Vous pouvez | |||
utiliser, modifier et/ou redistribuer ce programme sous les conditions | |||
de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA | |||
sur le site "http://www.cecill.info". | |||
En contrepartie de l'accessibilité au code source et des droits de copie, | |||
de modification et de redistribution accordés par cette licence, il n'est | |||
offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons, | |||
seule une responsabilité restreinte pèse sur l'auteur du programme, le | |||
titulaire des droits patrimoniaux et les concédants successifs. | |||
A cet égard l'attention de l'utilisateur est attirée sur les risques | |||
associés au chargement, à l'utilisation, à la modification et/ou au | |||
développement et à la reproduction du logiciel par l'utilisateur étant | |||
donné sa spécificité de logiciel libre, qui peut le rendre complexe à | |||
manipuler et qui le réserve donc à des développeurs et des professionnels | |||
avertis possédant des connaissances informatiques approfondies. Les | |||
utilisateurs sont donc invités à charger et tester l'adéquation du | |||
logiciel à leurs besoins dans des conditions permettant d'assurer la | |||
sécurité de leurs systèmes et ou de leurs données et, plus généralement, | |||
à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. | |||
Le fait que vous puissiez accéder à cet en-tête signifie que vous avez | |||
pris connaissance de la licence CeCILL, et que vous en avez accepté les | |||
termes. | |||
*/ | |||
var app = new Vue({ | |||
el: '#app-setting-admin', | |||
data() { | |||
return Object.assign({ | |||
currentSection: null, | |||
sectionsArray: [] | |||
}, window.appInitValues); | |||
}, | |||
methods: { | |||
changeSection: function(section) { | |||
this.currentSection = section.name ; | |||
}, | |||
getInitialSection: function() { | |||
var hash = window.location.hash.substring(1); | |||
if(hash && hash.length) { | |||
return hash; | |||
} | |||
return this.sectionsArray[0].name; | |||
} | |||
}, | |||
mounted: function() { | |||
this.currentSection = this.getInitialSection(); | |||
} | |||
}); | |||
@@ -342,7 +342,7 @@ a.btn, button.btn { | |||
} | |||
#nav-params { | |||
margin-bottom: 30px ; | |||
margin-bottom: 20px ; | |||
a { | |||
margin-right: 10px ; | |||
@@ -1535,4 +1535,5 @@ a.btn, button.btn { | |||
@import "support/_view.scss"; | |||
@import "producer-admin/_index.scss"; | |||
@import "feature-admin/_index.scss"; | |||
@import "setting/_form.scss"; | |||
@import "_responsive.scss" ; |
@@ -0,0 +1,52 @@ | |||
.setting-form { | |||
.panel { | |||
h4 { | |||
font-size: 23px; | |||
margin-bottom: 20px; | |||
text-transform: uppercase; | |||
border-bottom: solid 1px gray; | |||
} | |||
h4:not(:first-child) { | |||
margin-top: 45px; | |||
} | |||
} | |||
.form-group { | |||
&.has-success, &.has-success label { | |||
color: #333; | |||
} | |||
.checkbox { | |||
input { | |||
position: relative; | |||
top: -1px; | |||
margin-right: 3px; | |||
} | |||
} | |||
&.form-toggle { | |||
.control-label { | |||
position: relative; | |||
top: 7px; | |||
left: 10px; | |||
} | |||
.toggle { | |||
@include border-radius(20px); | |||
float: left; | |||
.toggle-group { | |||
.btn.toggle-on { | |||
//border-color: white; | |||
color: white; | |||
} | |||
.btn.toggle-off { | |||
border-color: white; | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -62,6 +62,7 @@ class CommonAsset extends \common\components\MyAssetBundle | |||
$this->addAsset('css','js/jquery-ui-1.11.4.custom/jquery-ui.min.css'); | |||
$this->addAsset('css','js/jquery-ui-1.11.4.custom/jquery-ui.theme.css'); | |||
$this->addAsset('css','js/vuejs/vcalendar/vcalendar.min.css') ; | |||
$this->addAsset('css','js/simple-lightbox/simpleLightbox.min.css') ; | |||
$this->addAsset('css','css/screen.css') ; | |||
// js | |||
@@ -69,6 +70,7 @@ class CommonAsset extends \common\components\MyAssetBundle | |||
$this->addAsset('js','js/jquery-ui-1.11.4.custom/jquery-ui.min.js'); | |||
$this->addAsset('js','js/promise-polyfill/promise.min.js'); | |||
$this->addAsset('js','js/axios/axios.min.js'); | |||
$this->addAsset('js','js/simple-lightbox/simpleLightbox.min.js') ; | |||
$this->addAsset('js','js/vuejs/vue.js'); | |||
// Documentation : https://vcalendar.io/ |
@@ -15,6 +15,7 @@ class BusinessLogic | |||
public function getModules() | |||
{ | |||
return [ | |||
$this->getSettingModule(), | |||
$this->getFeatureModule(), | |||
$this->getFeatureProducerModule(), | |||
$this->getUnitModule(), | |||
@@ -54,7 +55,7 @@ class BusinessLogic | |||
return $this->producerContext; | |||
} | |||
public function setProducerContext(Producer $producer) | |||
public function setProducerContext(Producer $producer = null) | |||
{ | |||
$this->producerContext = $producer; | |||
@@ -11,8 +11,8 @@ use common\logic\Document\DeliveryNote\Module\DeliveryNoteModule; | |||
use common\logic\Document\Document\Module\DocumentModule; | |||
use common\logic\Document\Invoice\Module\InvoiceModule; | |||
use common\logic\Document\Quotation\Module\QuotationModule; | |||
use common\logic\Feature\Feature\Module\FeatureModule; | |||
use common\logic\Feature\FeatureProducer\Module\FeatureProducerModule; | |||
use common\logic\Feature\Feature\FeatureModule; | |||
use common\logic\Feature\FeatureProducer\FeatureProducerModule; | |||
use common\logic\Opinion\Module\OpinionModule; | |||
use common\logic\Order\Order\Module\OrderModule; | |||
use common\logic\Order\ProductOrder\Module\ProductOrderModule; | |||
@@ -25,6 +25,7 @@ use common\logic\Product\Product\Module\ProductModule; | |||
use common\logic\Product\ProductCategory\Module\ProductCategoryModule; | |||
use common\logic\Product\ProductPointSale\Module\ProductPointSaleModule; | |||
use common\logic\Product\ProductPrice\Module\ProductPriceModule; | |||
use common\logic\Setting\SettingModule; | |||
use common\logic\Subscription\ProductSubscription\Module\ProductSubscriptionModule; | |||
use common\logic\Subscription\Subscription\Module\SubscriptionModule; | |||
use common\logic\Ticket\Ticket\Module\TicketModule; | |||
@@ -196,4 +197,9 @@ trait BusinessLogicTrait | |||
{ | |||
return FeatureProducerModule::getInstance(); | |||
} | |||
public function getSettingModule(): SettingModule | |||
{ | |||
return SettingModule::getInstance(); | |||
} | |||
} |
@@ -13,7 +13,8 @@ class DolibarrApi extends AbstractApi | |||
public function createInvoice(int $idUser) | |||
{ | |||
return $this->post(self::RESOURCE_INVOICES, [ | |||
'socid' => $idUser | |||
'socid' => $idUser, | |||
'cond_reglement_id' => 2 | |||
]); | |||
} | |||
@@ -37,7 +37,7 @@ | |||
*/ | |||
return [ | |||
'version' => '23.10.E', | |||
'version' => '23.11.B', | |||
'maintenanceMode' => false, | |||
'siteName' => 'Opendistrib', | |||
'adminEmail' => 'contact@opendistrib.net', |
@@ -0,0 +1,8 @@ | |||
<?php | |||
namespace common\logic; | |||
abstract class AbstractChecker extends AbstractService implements CheckerInterface | |||
{ | |||
} |
@@ -67,7 +67,9 @@ abstract class AbstractRepository extends AbstractService implements RepositoryI | |||
public function defaultFilterProducerContext(): void | |||
{ | |||
$defaultOptions = $this->getDefaultOptionsSearch(); | |||
if(isset($defaultOptions['attribute_id_producer']) && $defaultOptions['attribute_id_producer']) { | |||
if(isset($defaultOptions['attribute_id_producer']) | |||
&& $defaultOptions['attribute_id_producer'] | |||
&& $this->getProducerContext()) { | |||
$this->query->andWhere([$defaultOptions['attribute_id_producer'] => $this->getProducerContextId()]); | |||
} | |||
} | |||
@@ -89,4 +91,9 @@ abstract class AbstractRepository extends AbstractService implements RepositoryI | |||
{ | |||
return $this->createQuery(); | |||
} | |||
public function queryDefaultAll() | |||
{ | |||
return $this->createDefaultQuery(); | |||
} | |||
} |
@@ -0,0 +1,8 @@ | |||
<?php | |||
namespace common\logic; | |||
abstract class AbstractResolver extends AbstractService implements ResolverInterface | |||
{ | |||
} |
@@ -15,6 +15,7 @@ abstract class AbstractService extends AbstractSingleton implements ServiceInter | |||
SolverInterface::class, | |||
RepositoryQueryInterface::class, | |||
RepositoryInterface::class, | |||
CheckerInterface::class, | |||
NotifierInterface::class, | |||
BuilderInterface::class, | |||
ResolverInterface::class, |
@@ -0,0 +1,8 @@ | |||
<?php | |||
namespace common\logic; | |||
interface CheckerInterface | |||
{ | |||
} |
@@ -4,34 +4,81 @@ namespace common\logic\Distribution\Distribution\Export; | |||
use common\logic\AbstractGenerator; | |||
use common\logic\Distribution\Distribution\Model\Distribution; | |||
use common\logic\Feature\Feature\Feature; | |||
use common\logic\Feature\Feature\FeatureChecker; | |||
use common\logic\Feature\Feature\FeatureManager; | |||
use common\logic\Order\Order\Model\Order; | |||
use common\logic\Order\Order\Repository\OrderRepository; | |||
use common\logic\Order\Order\Service\OrderSolver; | |||
use common\logic\Producer\Producer\Service\ProducerSolver; | |||
use kartik\mpdf\Pdf; | |||
use yii\base\ErrorException; | |||
use yii\helpers\BaseStringHelper; | |||
use yii\helpers\Html; | |||
class DistributionShoppingCartLabelsPdfGenerator extends AbstractGenerator implements DistributionExportGeneratorInterface | |||
{ | |||
const FORMAT_70_42 = '70x42'; | |||
protected ProducerSolver $producerSolver; | |||
protected OrderRepository $orderRepository; | |||
protected OrderSolver $orderSolver; | |||
protected FeatureChecker $featureChecker; | |||
public function loadDependencies(): void | |||
{ | |||
$this->producerSolver = $this->loadService(ProducerSolver::class); | |||
$this->orderRepository = $this->loadService(OrderRepository::class); | |||
$this->orderSolver = $this->loadService(OrderSolver::class); | |||
$this->featureChecker = $this->loadService(FeatureChecker::class); | |||
} | |||
public function getSpecificFormatDetailsArray(): array | |||
{ | |||
return [ | |||
self::FORMAT_70_42 => [70, 42] | |||
]; | |||
} | |||
public function generate(Distribution $distribution, bool $save = false) | |||
{ | |||
$isSpecificFormat = false; | |||
$exportShoppingCartLabelsFormat = $this->producerSolver->getConfig('export_shopping_cart_labels_format'); | |||
if($this->featureChecker->isEnabled(Feature::ALIAS_EXPORT_SHOPPING_CART_LABELS_ADVANCED)) { | |||
if($exportShoppingCartLabelsFormat) { | |||
$isSpecificFormat = true; | |||
[$specificFormatWidth, $specificFormatHeight] = $this->getSpecificFormatDetails($exportShoppingCartLabelsFormat); | |||
} | |||
else { | |||
throw new ErrorException("Aucun format d'étiquette n'est défini dans les paramètres."); | |||
} | |||
} | |||
$ordersArray = $this->orderRepository->findOrdersByDistribution($distribution); | |||
$ordersArray = $this->filterOrdersExcludedUsersAndPointSales($ordersArray); | |||
$content = \Yii::$app->getView()->render('@backend/views/distribution/shopping-cart-labels.php', [ | |||
'distribution' => $distribution, | |||
'ordersArray' => $ordersArray, | |||
'isSpecificFormat' => $isSpecificFormat, | |||
'shoppingCartLabelsPerColumn' => $this->producerSolver->getConfig('export_shopping_cart_labels_number_per_column') ?: 8 | |||
]); | |||
$pdf = new Pdf([ | |||
if($isSpecificFormat) { | |||
$pdf = $this->getPdf($distribution, $content, true, $specificFormatWidth, $specificFormatHeight); | |||
} | |||
else { | |||
$pdf = $this->getPdf($distribution, $content, false); | |||
$pdf->getApi()->SetColumns(4); | |||
$pdf->getApi()->keepColumns = true; | |||
} | |||
return $pdf->render(); | |||
} | |||
public function getPdf(Distribution $distribution, string $content, bool $isSpecificFormat, float $specificFormatWidth = 0, float $specificFormatHeight = 0) | |||
{ | |||
return new Pdf([ | |||
'mode' => Pdf::MODE_UTF8, | |||
'format' => Pdf::FORMAT_A4, | |||
'orientation' => Pdf::ORIENT_PORTRAIT, | |||
@@ -40,17 +87,8 @@ class DistributionShoppingCartLabelsPdfGenerator extends AbstractGenerator imple | |||
'@app/web/pdf/Etiquettes-' . $distribution->date . '-' . $this->getProducerContextId() . '.pdf' | |||
), | |||
'content' => $content, | |||
'cssInline' => $this->getCss(), | |||
'methods' => [ | |||
'SetHeader' => ['Étiquettes du ' . date('d/m/Y', strtotime($distribution->date))], | |||
'SetFooter' => ['{PAGENO}'], | |||
], | |||
'cssInline' => $this->getCss($isSpecificFormat, $specificFormatWidth, $specificFormatHeight), | |||
]); | |||
$pdf->getApi()->SetColumns(4); | |||
$pdf->getApi()->keepColumns = true; | |||
return $pdf->render(); | |||
} | |||
public function filterOrdersExcludedUsersAndPointSales(array $ordersArray) | |||
@@ -77,9 +115,9 @@ class DistributionShoppingCartLabelsPdfGenerator extends AbstractGenerator imple | |||
return $order->pointSale && $order->pointSale->exclude_export_shopping_cart_labels; | |||
} | |||
public function getCss(): string | |||
public function getCss(bool $isSpecificFormat = false, float $specificFormatWith = 0, float $specificFormatHeight = 0): string | |||
{ | |||
return ' | |||
$css = ' | |||
@page { | |||
margin: 0px 0px 0px 0px !important; | |||
padding: 0px 0px 0px 0px !important; | |||
@@ -90,21 +128,6 @@ class DistributionShoppingCartLabelsPdfGenerator extends AbstractGenerator imple | |||
font-size: 13px; | |||
} | |||
.clr { | |||
clear: both; | |||
} | |||
.shopping-cart-label { | |||
-webkit-column-break-inside:avoid; | |||
column-break-inside: avoid; | |||
-webkit-page-break-inside:avoid; | |||
page-break-inside: avoid; | |||
} | |||
.shopping-cart-label .inner { | |||
padding: 8px; | |||
} | |||
.shopping-cart-label .username { | |||
font-weight: bold; | |||
font-size: 13px; | |||
@@ -119,7 +142,75 @@ class DistributionShoppingCartLabelsPdfGenerator extends AbstractGenerator imple | |||
.shopping-cart-label .products { | |||
font-size: 10px; | |||
}'; | |||
if($isSpecificFormat) { | |||
$paddingShoppingCartLabel = 3; | |||
$specificFormatWith = $specificFormatWith - 2 * $paddingShoppingCartLabel; | |||
$specificFormatHeight = $specificFormatHeight - 2 * $paddingShoppingCartLabel; | |||
$css .= ' | |||
.shopping-cart-label { | |||
box-sizing: border-box; | |||
padding: '.$paddingShoppingCartLabel.'mm; | |||
width: '.$specificFormatWith.'mm; | |||
height: '.$specificFormatHeight.'mm; | |||
display: block; | |||
float: left; | |||
}'; | |||
} | |||
else { | |||
$css .= ' | |||
.shopping-cart-label { | |||
-webkit-column-break-inside:avoid; | |||
column-break-inside: avoid; | |||
-webkit-page-break-inside:avoid; | |||
page-break-inside: avoid; | |||
} | |||
'; | |||
.shopping-cart-label .inner { | |||
padding: 8px; | |||
} | |||
'; | |||
} | |||
return $css; | |||
} | |||
public function getShoppingCartLabelAsHtml(Order $order): string | |||
{ | |||
return '<div class="shopping-cart-label"> | |||
<div class="inner"> | |||
<div class="username"> | |||
'.$this->orderSolver->getOrderUsername($order).' | |||
</div> | |||
<div class="point-sale"> | |||
'.date('d/m', strtotime($order->distribution->date)).' • | |||
'.$order->pointSale->name.' | |||
</div> | |||
<div class="products"> | |||
'.$this->orderRepository->getCartSummary($order).' | |||
</div> | |||
</div> | |||
</div>'; | |||
} | |||
public function getSpecificFormatDetails(string $name): array | |||
{ | |||
$specificFormatDetailsArray = $this->getSpecificFormatDetailsArray(); | |||
if(!isset($specificFormatDetailsArray[$name])) { | |||
throw new ErrorException("Format d'étiquette inconnu"); | |||
} | |||
return $specificFormatDetailsArray[$name]; | |||
} | |||
public function populateDropdownSpecificFormats(): array | |||
{ | |||
$specificFormatsArray = [null => '--']; | |||
foreach($this->getSpecificFormatDetailsArray() as $key => $specificFormat) { | |||
$specificFormatsArray[$key] = $specificFormat[0].'x'.$specificFormat[1].' mm'; | |||
} | |||
return $specificFormatsArray; | |||
} | |||
} |
@@ -52,7 +52,13 @@ class DocumentManager extends AbstractManager | |||
]); | |||
$contentFooter = '<div id="footer">'; | |||
$contentFooter .= '<div class="infos-bottom">' . Html::encode($producer->document_infos_bottom) . '</div>'; | |||
if ($this->producerSolver->getConfig('document_image_bottom')) { | |||
$urlDocumentImageBottom = \Yii::$app->urlManagerProducer->getHostInfo() . '/' . \Yii::$app->urlManagerProducer->baseUrl . '/uploads/' . $producer->document_image_bottom; | |||
$contentFooter .= '<div class="image"><img src="'.$urlDocumentImageBottom.'" style="max-height:80px;" /></div>'; | |||
} | |||
if ($this->producerSolver->getConfig('document_infos_bottom')) { | |||
$contentFooter .= '<div class="infos-bottom">'.nl2br($producer->document_infos_bottom).'</div>'; | |||
} | |||
$contentFooter .= '</div>'; | |||
$marginBottom = 10; |
@@ -36,17 +36,19 @@ | |||
* termes. | |||
*/ | |||
namespace common\logic\Feature\Feature\Model; | |||
namespace common\logic\Feature\Feature; | |||
use common\components\ActiveRecordCommon; | |||
use common\logic\Feature\FeatureProducer\Model\FeatureProducer; | |||
use common\logic\Feature\FeatureProducer\FeatureProducer; | |||
use yii\db\ActiveQuery; | |||
use yii\db\Schema; | |||
class Feature extends ActiveRecordCommon | |||
{ | |||
const ALIAS_CONTACT = 'contact'; | |||
const ALIAS_PRODUCT_PRICE_IMPORT = 'product_price_import'; | |||
const ALIAS_ONLINE_PAYMENT = 'online_payment'; | |||
const ALIAS_EXPORT_SHOPPING_CART_LABELS_ADVANCED = 'export_shopping_cart_labels_advanced'; | |||
const ALIAS_SETTINGS = 'settings'; | |||
/** | |||
* @inheritdoc | |||
@@ -64,6 +66,7 @@ class Feature extends ActiveRecordCommon | |||
return [ | |||
[['alias', 'name'], 'required'], | |||
[['status', 'is_paid_feature', 'only_for_selected_producers'], 'boolean'], | |||
[['position'], 'integer'], | |||
[['price'], 'double'], | |||
[['alias', 'name', 'description'], 'string'], | |||
]; | |||
@@ -82,7 +85,8 @@ class Feature extends ActiveRecordCommon | |||
'status' => 'Statut', | |||
'is_paid_feature' => "Fonctionnalité payante", | |||
'price' => 'Prix', | |||
'only_for_selected_producers' => 'Uniquement pour les producteurs sélectionnés' | |||
'only_for_selected_producers' => 'Uniquement pour les producteurs sélectionnés', | |||
'position' => 'Position' | |||
]; | |||
} | |||
@@ -1,10 +1,8 @@ | |||
<?php | |||
namespace common\logic\Feature\Feature\Service; | |||
namespace common\logic\Feature\Feature; | |||
use common\logic\AbstractBuilder; | |||
use common\logic\Feature\Feature\Model\Feature; | |||
use common\logic\Feature\Feature\Repository\FeatureRepository; | |||
class FeatureBuilder extends AbstractBuilder | |||
{ | |||
@@ -38,7 +36,7 @@ class FeatureBuilder extends AbstractBuilder | |||
public function createFeature( | |||
string $alias, | |||
string $name, | |||
string $description, | |||
string $description = '', | |||
bool $status = true, | |||
bool $isPaidFeature = false, | |||
float $price = null |
@@ -0,0 +1,48 @@ | |||
<?php | |||
namespace common\logic\Feature\Feature; | |||
use common\logic\AbstractChecker; | |||
use common\logic\Feature\FeatureProducer\FeatureProducerRepository; | |||
use yii\base\ErrorException; | |||
class FeatureChecker extends AbstractChecker | |||
{ | |||
protected FeatureRepository $featureRepository; | |||
protected FeatureProducerRepository $featureProducerRepository; | |||
public function loadDependencies(): void | |||
{ | |||
$this->featureRepository = $this->loadService(FeatureRepository::class); | |||
$this->featureProducerRepository = $this->loadService(FeatureProducerRepository::class); | |||
} | |||
public function isEnabled(string $aliasFeature): bool | |||
{ | |||
$feature = $this->featureRepository->findOneFeatureByAlias($aliasFeature); | |||
if(!$feature) { | |||
throw new ErrorException("Fonctionnalité avec l'alias '".$aliasFeature."' non trouvée"); | |||
} | |||
if(!$feature->status) { | |||
return false; | |||
} | |||
$featureProducer = $this->featureProducerRepository->findOneFeatureProducer($feature); | |||
if(!$featureProducer || is_null($featureProducer->status)) { | |||
if($feature->is_paid_feature || $feature->only_for_selected_producers) { | |||
return false; | |||
} | |||
return $feature->status; | |||
} | |||
else { | |||
return $featureProducer->status; | |||
} | |||
} | |||
public function isDisabled(string $aliasFeature): bool | |||
{ | |||
return !$this->isEnabled($aliasFeature); | |||
} | |||
} |
@@ -0,0 +1,24 @@ | |||
<?php | |||
namespace common\logic\Feature\Feature; | |||
use common\logic\AbstractDefinition; | |||
class FeatureDefinition extends AbstractDefinition | |||
{ | |||
public function getEntityFqcn(): string | |||
{ | |||
return Feature::class; | |||
} | |||
public function getFeaturesBase(): array | |||
{ | |||
return [ | |||
Feature::ALIAS_CONTACT => 'Formulaire de contact', | |||
Feature::ALIAS_PRODUCT_PRICE_IMPORT => 'Produits : import prix', | |||
Feature::ALIAS_ONLINE_PAYMENT => 'Paiement en ligne', | |||
Feature::ALIAS_EXPORT_SHOPPING_CART_LABELS_ADVANCED => "Génération d'étiquettes avec un format spécifique", | |||
Feature::ALIAS_SETTINGS => 'Système de paramètres' | |||
]; | |||
} | |||
} |
@@ -1,6 +1,6 @@ | |||
<?php | |||
namespace common\logic\Feature\Feature\Service; | |||
namespace common\logic\Feature\Feature; | |||
use common\logic\AbstractManager; | |||
@@ -19,13 +19,10 @@ class FeatureImporter extends AbstractManager | |||
{ | |||
$featuresBaseArray = $this->featureDefinition->getFeaturesBase(); | |||
foreach($featuresBaseArray as $alias => $featureBase) { | |||
foreach($featuresBaseArray as $alias => $featureBaseName) { | |||
$this->featureBuilder->createFeature( | |||
$alias, | |||
$featureBase['name'], | |||
'', | |||
$featureBase['status'], | |||
$featureBase['is_paid_feature'] | |||
$featureBaseName | |||
); | |||
} | |||
} |
@@ -0,0 +1,43 @@ | |||
<?php | |||
namespace common\logic\Feature\Feature; | |||
use common\logic\AbstractManager; | |||
use common\logic\Feature\FeatureProducer\FeatureProducerBuilder; | |||
class FeatureManager extends AbstractManager | |||
{ | |||
protected FeatureBuilder $featureBuilder; | |||
protected FeatureProducerBuilder $featureProducerBuilder; | |||
public function loadDependencies(): void | |||
{ | |||
$this->featureBuilder = $this->loadService(FeatureBuilder::class); | |||
$this->featureProducerBuilder = $this->loadService(FeatureProducerBuilder::class); | |||
} | |||
public function enableFeature(Feature $feature): void | |||
{ | |||
$this->featureBuilder->updateStatus($feature, true); | |||
} | |||
public function disableFeature(Feature $feature): void | |||
{ | |||
$this->featureBuilder->updateStatus($feature, false); | |||
} | |||
public function enableFeatureForProducer(Feature $feature) | |||
{ | |||
$this->featureProducerBuilder->updateStatusByFeature($feature, true); | |||
} | |||
public function disableFeatureForProducer(Feature $feature) | |||
{ | |||
$this->featureProducerBuilder->updateStatusByFeature($feature, false); | |||
} | |||
public function defaultFeatureForProducer(Feature $feature) | |||
{ | |||
$this->featureProducerBuilder->updateStatusByFeature($feature, null); | |||
} | |||
} |
@@ -1,13 +1,8 @@ | |||
<?php | |||
namespace common\logic\Feature\Feature\Module; | |||
namespace common\logic\Feature\Feature; | |||
use common\logic\AbstractModule; | |||
use common\logic\Feature\Feature\Repository\FeatureRepository; | |||
use common\logic\Feature\Feature\Service\FeatureBuilder; | |||
use common\logic\Feature\Feature\Service\FeatureDefinition; | |||
use common\logic\Feature\Feature\Service\FeatureImporter; | |||
use common\logic\Feature\Feature\Service\FeatureManager; | |||
class FeatureModule extends AbstractModule | |||
{ | |||
@@ -16,6 +11,7 @@ class FeatureModule extends AbstractModule | |||
return [ | |||
FeatureDefinition::class, | |||
FeatureRepository::class, | |||
FeatureChecker::class, | |||
FeatureBuilder::class, | |||
FeatureImporter::class, | |||
FeatureManager::class | |||
@@ -32,6 +28,11 @@ class FeatureModule extends AbstractModule | |||
return FeatureRepository::getInstance(); | |||
} | |||
public function getChecker(): FeatureChecker | |||
{ | |||
return FeatureChecker::getInstance(); | |||
} | |||
public function getBuilder(): FeatureBuilder | |||
{ | |||
return FeatureBuilder::getInstance(); |
@@ -1,9 +1,8 @@ | |||
<?php | |||
namespace common\logic\Feature\Feature\Repository; | |||
namespace common\logic\Feature\Feature; | |||
use common\logic\AbstractRepository; | |||
use common\logic\Feature\Feature\Model\Feature; | |||
class FeatureRepository extends AbstractRepository | |||
{ | |||
@@ -19,7 +18,7 @@ class FeatureRepository extends AbstractRepository | |||
return [ | |||
self::WITH => ['featureProducers'], | |||
self::JOIN_WITH => [], | |||
self::ORDER_BY => '', | |||
self::ORDER_BY => 'position ASC', | |||
self::ATTRIBUTE_ID_PRODUCER => '' | |||
]; | |||
} | |||
@@ -37,4 +36,11 @@ class FeatureRepository extends AbstractRepository | |||
->filterByAlias($alias) | |||
->findOne(); | |||
} | |||
public function findPaidFeatures(): array | |||
{ | |||
return $this->createQuery() | |||
->filterIsPaidFeature() | |||
->find(); | |||
} | |||
} |
@@ -1,9 +1,8 @@ | |||
<?php | |||
namespace common\logic\Feature\Feature\Repository; | |||
namespace common\logic\Feature\Feature; | |||
use common\logic\AbstractRepositoryQuery; | |||
use common\logic\Feature\Feature\Service\FeatureDefinition; | |||
class FeatureRepositoryQuery extends AbstractRepositoryQuery | |||
{ | |||
@@ -19,4 +18,12 @@ class FeatureRepositoryQuery extends AbstractRepositoryQuery | |||
$this->andWhere(['alias' => $alias]); | |||
return $this; | |||
} | |||
public function filterIsPaidFeature(): self | |||
{ | |||
$this->andWhere(['is_paid_feature' => true]); | |||
return $this; | |||
} | |||
} |
@@ -1,31 +0,0 @@ | |||
<?php | |||
namespace common\logic\Feature\Feature\Service; | |||
use common\logic\AbstractDefinition; | |||
use common\logic\Feature\Feature\Model\Feature; | |||
class FeatureDefinition extends AbstractDefinition | |||
{ | |||
public function getEntityFqcn(): string | |||
{ | |||
return Feature::class; | |||
} | |||
public function getFeaturesBase(): array | |||
{ | |||
return [ | |||
Feature::ALIAS_CONTACT => $this->buildFeatureArray('Formulaire de contact', true, false), | |||
Feature::ALIAS_PRODUCT_PRICE_IMPORT => $this->buildFeatureArray('Produits : import prix', true, false), | |||
]; | |||
} | |||
public function buildFeatureArray(string $name, bool $status, bool $isPaidFeature): array | |||
{ | |||
return [ | |||
'name' => $name, | |||
'status' => $status, | |||
'is_paid_feature' => $isPaidFeature | |||
]; | |||
} | |||
} |
@@ -1,80 +0,0 @@ | |||
<?php | |||
namespace common\logic\Feature\Feature\Service; | |||
use common\logic\AbstractManager; | |||
use common\logic\Feature\Feature\Model\Feature; | |||
use common\logic\Feature\Feature\Repository\FeatureRepository; | |||
use common\logic\Feature\FeatureProducer\Repository\FeatureProducerRepository; | |||
use common\logic\Feature\FeatureProducer\Service\FeatureProducerBuilder; | |||
use yii\base\ErrorException; | |||
class FeatureManager extends AbstractManager | |||
{ | |||
protected FeatureRepository $featureRepository; | |||
protected FeatureProducerRepository $featureProducerRepository; | |||
protected FeatureBuilder $featureBuilder; | |||
protected FeatureProducerBuilder $featureProducerBuilder; | |||
public function loadDependencies(): void | |||
{ | |||
$this->featureRepository = $this->loadService(FeatureRepository::class); | |||
$this->featureProducerRepository = $this->loadService(FeatureProducerRepository::class); | |||
$this->featureBuilder = $this->loadService(FeatureBuilder::class); | |||
$this->featureProducerBuilder = $this->loadService(FeatureProducerBuilder::class); | |||
} | |||
public function isEnabled(string $aliasFeature): bool | |||
{ | |||
$feature = $this->featureRepository->findOneFeatureByAlias($aliasFeature); | |||
if(!$feature) { | |||
throw new ErrorException("Fonctionnalité avec l'alias '".$aliasFeature."' non trouvée"); | |||
} | |||
if(!$feature->status) { | |||
return false; | |||
} | |||
$featureProducer = $this->featureProducerRepository->findOneFeatureProducer($feature); | |||
if(!$featureProducer || is_null($featureProducer->status)) { | |||
if($feature->is_paid_feature || $feature->only_for_selected_producers) { | |||
return false; | |||
} | |||
return $feature->status; | |||
} | |||
else { | |||
return $featureProducer->status; | |||
} | |||
} | |||
public function isDisabled(string $aliasFeature): bool | |||
{ | |||
return !$this->isEnabled($aliasFeature); | |||
} | |||
public function enable(Feature $feature): void | |||
{ | |||
$this->featureBuilder->updateStatus($feature, true); | |||
} | |||
public function disable(Feature $feature): void | |||
{ | |||
$this->featureBuilder->updateStatus($feature, false); | |||
} | |||
public function enableForProducer(Feature $feature) | |||
{ | |||
$this->featureProducerBuilder->updateStatusByFeature($feature, true); | |||
} | |||
public function disableForProducer(Feature $feature) | |||
{ | |||
$this->featureProducerBuilder->updateStatusByFeature($feature, false); | |||
} | |||
public function defaultForProducer(Feature $feature) | |||
{ | |||
$this->featureProducerBuilder->updateStatusByFeature($feature, null); | |||
} | |||
} |
@@ -36,10 +36,10 @@ | |||
* termes. | |||
*/ | |||
namespace common\logic\Feature\FeatureProducer\Model; | |||
namespace common\logic\Feature\FeatureProducer; | |||
use common\components\ActiveRecordCommon; | |||
use common\logic\Feature\Feature\Model\Feature; | |||
use common\logic\Feature\Feature\Feature; | |||
use common\logic\Producer\Producer\Model\Producer; | |||
use yii\db\ActiveQuery; | |||
@@ -1,12 +1,9 @@ | |||
<?php | |||
namespace common\logic\Feature\FeatureProducer\Service; | |||
namespace common\logic\Feature\FeatureProducer; | |||
use common\logic\AbstractBuilder; | |||
use common\logic\Feature\Feature\Model\Feature; | |||
use common\logic\Feature\FeatureProducer\Model\FeatureProducer; | |||
use common\logic\Feature\FeatureProducer\Repository\FeatureProducerRepository; | |||
use common\logic\Producer\Producer\Model\Producer; | |||
use common\logic\Feature\Feature\Feature; | |||
class FeatureProducerBuilder extends AbstractBuilder | |||
{ |
@@ -0,0 +1,13 @@ | |||
<?php | |||
namespace common\logic\Feature\FeatureProducer; | |||
use common\logic\AbstractDefinition; | |||
class FeatureProducerDefinition extends AbstractDefinition | |||
{ | |||
public function getEntityFqcn(): string | |||
{ | |||
return FeatureProducer::class; | |||
} | |||
} |
@@ -1,11 +1,8 @@ | |||
<?php | |||
namespace common\logic\Feature\FeatureProducer\Module; | |||
namespace common\logic\Feature\FeatureProducer; | |||
use common\logic\AbstractModule; | |||
use common\logic\Feature\FeatureProducer\Repository\FeatureProducerRepository; | |||
use common\logic\Feature\FeatureProducer\Service\FeatureProducerBuilder; | |||
use common\logic\Feature\FeatureProducer\Service\FeatureProducerDefinition; | |||
class FeatureProducerModule extends AbstractModule | |||
{ | |||
@@ -14,7 +11,7 @@ class FeatureProducerModule extends AbstractModule | |||
return [ | |||
FeatureProducerDefinition::class, | |||
FeatureProducerRepository::class, | |||
FeatureProducerBuilder::class | |||
FeatureProducerBuilder::class, | |||
]; | |||
} | |||
@@ -1,10 +1,9 @@ | |||
<?php | |||
namespace common\logic\Feature\FeatureProducer\Repository; | |||
namespace common\logic\Feature\FeatureProducer; | |||
use common\logic\AbstractRepository; | |||
use common\logic\Feature\Feature\Model\Feature; | |||
use common\logic\Producer\Producer\Model\Producer; | |||
use common\logic\Feature\Feature\Feature; | |||
class FeatureProducerRepository extends AbstractRepository | |||
{ |
@@ -1,10 +1,9 @@ | |||
<?php | |||
namespace common\logic\Feature\FeatureProducer\Repository; | |||
namespace common\logic\Feature\FeatureProducer; | |||
use common\logic\AbstractRepositoryQuery; | |||
use common\logic\Feature\Feature\Model\Feature; | |||
use common\logic\Feature\FeatureProducer\Service\FeatureProducerDefinition; | |||
use common\logic\Feature\Feature\Feature; | |||
class FeatureProducerRepositoryQuery extends AbstractRepositoryQuery | |||
{ | |||
@@ -17,7 +16,7 @@ class FeatureProducerRepositoryQuery extends AbstractRepositoryQuery | |||
public function filterByFeature(Feature $feature): self | |||
{ | |||
$this->andWhere(['id_feature' => $feature]); | |||
$this->andWhere(['id_feature' => $feature->id]); | |||
return $this; | |||
} | |||
} |
@@ -1,25 +0,0 @@ | |||
<?php | |||
namespace common\logic\Feature\FeatureProducer\Service; | |||
use common\logic\AbstractDefinition; | |||
use common\logic\Feature\FeatureProducer\Model\FeatureProducer; | |||
use common\logic\Feature\FeatureProducer\Repository\FeatureProducerRepository; | |||
class FeatureProducerDefinition extends AbstractDefinition | |||
{ | |||
public function getEntityFqcn(): string | |||
{ | |||
return FeatureProducer::class; | |||
} | |||
public function getDefinition(): FeatureProducerDefinition | |||
{ | |||
return FeatureProducerDefinition::getInstance(); | |||
} | |||
public function getRepository(): FeatureProducerRepository | |||
{ | |||
return FeatureProducerRepository::getInstance(); | |||
} | |||
} |
@@ -21,8 +21,10 @@ class TillerManager extends AbstractManager | |||
public function loadDependencies(): void | |||
{ | |||
$this->producerSolver = $this->loadService(ProducerSolver::class); | |||
$this->tillerActivated = $this->producerSolver->getConfig('tiller'); | |||
$this->tillerClient = $this->getClient(); | |||
if($this->producerSolver->getProducerContext(false)) { | |||
$this->tillerActivated = $this->producerSolver->getConfig('tiller'); | |||
$this->tillerClient = $this->getClient(); | |||
} | |||
$this->orderSolver = $this->loadService(OrderSolver::class); | |||
$this->orderBuilder = $this->loadService(OrderBuilder::class); | |||
$this->productOrderSolver = $this->loadService(ProductOrderSolver::class); |
@@ -86,7 +86,7 @@ class PointSale extends ActiveRecordCommon | |||
[['id_producer', 'id_user', 'maximum_number_orders', 'status'], 'integer'], | |||
['id_producer', 'required'], | |||
[['users', 'users_comment', 'code'], 'safe'], | |||
[['product_price_percent'], 'double'], | |||
[['product_price_percent', 'minimum_order_amount'], 'double'], | |||
]; | |||
} | |||
@@ -129,7 +129,8 @@ class PointSale extends ActiveRecordCommon | |||
'button_generate_delivery_note_point_sale' => 'Activer le bouton de génération de bon de livraison par point de vente', | |||
'button_generate_delivery_note_each_user' => 'Activer le bouton de génération de bon de livraison par client', | |||
'exclude_export_shopping_cart_labels' => "Exclure de l'export d'étiquettes", | |||
'is_home_delivery' => "Livraison à domicile" | |||
'is_home_delivery' => "Livraison à domicile", | |||
'minimum_order_amount' => "Montant minimum de commande (€)" | |||
]; | |||
} | |||
@@ -116,6 +116,11 @@ class Producer extends ActiveRecordCommon | |||
*/ | |||
public $photoFile; | |||
/** | |||
* @var UploadedFile | |||
*/ | |||
public $document_image_bottomFile; | |||
/** | |||
* @inheritdoc | |||
*/ | |||
@@ -138,7 +143,7 @@ class Producer extends ActiveRecordCommon | |||
return $model->tiller == true; | |||
} | |||
], | |||
[['logoFile', 'photoFile'], 'file', 'extensions' => 'png, jpg, jpeg', 'mimeTypes' => 'image/png, image/jpeg'], | |||
[['logoFile', 'photoFile', 'document_image_bottomFile'], 'file', 'extensions' => 'png, jpg, jpeg', 'mimeTypes' => 'image/png, image/jpeg'], | |||
[ | |||
[ | |||
'order_delay', | |||
@@ -241,6 +246,8 @@ class Producer extends ActiveRecordCommon | |||
'option_testimony', | |||
'contact_email', | |||
'admin_comment', | |||
'export_shopping_cart_labels_format', | |||
'document_image_bottom', | |||
], | |||
'string' | |||
], | |||
@@ -290,6 +297,7 @@ class Producer extends ActiveRecordCommon | |||
'siret', | |||
'logo', | |||
'photo', | |||
'document_image_bottom', | |||
'postcode', | |||
'city', | |||
'code', | |||
@@ -339,8 +347,8 @@ class Producer extends ActiveRecordCommon | |||
'id' => 'ID', | |||
'name' => 'Nom', | |||
'siret' => 'Siret', | |||
'logo' => 'Logo', | |||
'photo' => 'Photo', | |||
'logoFile' => 'Logo', | |||
'photoFile' => 'Photo', | |||
'description' => 'Description', | |||
'postcode' => 'Code postal', | |||
'city' => 'Ville', | |||
@@ -398,6 +406,7 @@ class Producer extends ActiveRecordCommon | |||
'document_delivery_note_first_reference' => 'Première référence des bons de livraison', | |||
'document_infos_top' => 'Informations affichées en haut des documents', | |||
'document_infos_bottom' => 'Informations affichées en bas des documents', | |||
'document_image_bottomFile' => "Image affichée en bas des documents", | |||
'document_infos_quotation' => 'Informations affichées en bas des devis', | |||
'document_infos_invoice' => 'Informations affichées en bas des factures', | |||
'document_infos_delivery_note' => 'Informations affichées en bas des bons de livraison', | |||
@@ -455,9 +464,10 @@ class Producer extends ActiveRecordCommon | |||
'option_invoice_only_based_on_delivery_notes' => 'Facturer uniquement sur la base des bons de livraison', | |||
'option_document_width_logo' => 'Largeur du logo dans les documents', | |||
'export_shopping_cart_labels_number_per_column' => "Étiquettes (PDF) : nombre d'étiquettes par colonne", | |||
'export_shopping_cart_labels_format' => 'Étiquettes (PDF) : format', | |||
'option_document_display_price_unit_reference' => "Afficher les prix au kilogramme", | |||
'id_user_group_default' => "Groupe utilisateur par défaut attribué à l'inscription", | |||
'option_check_by_default_prevent_user_credit' => "Par défaut, prévenir l'utilisateur quand on crédite son compte" | |||
'option_check_by_default_prevent_user_credit' => "Par défaut, prévenir l'utilisateur quand on crédite son compte", | |||
]; | |||
} | |||
@@ -7,18 +7,18 @@ use yii\base\ErrorException; | |||
trait ProducerContextTrait | |||
{ | |||
protected ?Producer $producerContext = null; | |||
protected ?Producer $producerContext; | |||
public function setProducerContext(Producer $producer): self | |||
public function setProducerContext(Producer $producer = null): self | |||
{ | |||
$this->producerContext = $producer; | |||
return $this; | |||
} | |||
public function getProducerContext(): Producer | |||
public function getProducerContext(bool $throwExceptionIfNull = true): ?Producer | |||
{ | |||
if(is_null($this->producerContext)) { | |||
if($throwExceptionIfNull && is_null($this->producerContext)) { | |||
throw new ErrorException("Le contexte producteur n'est pas défini."); | |||
} | |||
@@ -29,4 +29,9 @@ trait ProducerContextTrait | |||
{ | |||
return $this->getProducerContext()->id; | |||
} | |||
public function isOutOfProducerContext(): bool | |||
{ | |||
return !$this->producerContext; | |||
} | |||
} |
@@ -0,0 +1,39 @@ | |||
<?php | |||
namespace common\logic\Setting; | |||
use common\logic\AbstractManager; | |||
use common\logic\Setting\SettingBuilder; | |||
use common\logic\Setting\SettingRepository; | |||
class AdminSettingBag extends AbstractManager | |||
{ | |||
protected SettingRepository $settingRepository; | |||
protected SettingBuilder $settingBuilder; | |||
public function loadDependencies(): void | |||
{ | |||
$this->settingRepository = $this->loadService(SettingRepository::class); | |||
$this->settingBuilder = $this->loadService(SettingBuilder::class); | |||
} | |||
public function get(string $name) | |||
{ | |||
$setting = $this->settingRepository->findOneAdminSettingByName($name); | |||
if($setting) { | |||
return $setting->getValue(); | |||
} | |||
return null; | |||
} | |||
public function set(string $name, $value) | |||
{ | |||
$setting = $this->settingBuilder->createSetting($name); | |||
if($setting) { | |||
$this->settingBuilder->updateValue($setting, $value); | |||
} | |||
} | |||
} |
@@ -0,0 +1,108 @@ | |||
<?php | |||
/** | |||
* Copyright distrib (2018) | |||
* | |||
* contact@opendistrib.net | |||
* | |||
* Ce logiciel est un programme informatique servant à aider les producteurs | |||
* à distribuer leur production en circuits courts. | |||
* | |||
* Ce logiciel est régi par la licence CeCILL soumise au droit français et | |||
* respectant les principes de diffusion des logiciels libres. Vous pouvez | |||
* utiliser, modifier et/ou redistribuer ce programme sous les conditions | |||
* de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA | |||
* sur le site "http://www.cecill.info". | |||
* | |||
* En contrepartie de l'accessibilité au code source et des droits de copie, | |||
* de modification et de redistribution accordés par cette licence, il n'est | |||
* offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons, | |||
* seule une responsabilité restreinte pèse sur l'auteur du programme, le | |||
* titulaire des droits patrimoniaux et les concédants successifs. | |||
* | |||
* A cet égard l'attention de l'utilisateur est attirée sur les risques | |||
* associés au chargement, à l'utilisation, à la modification et/ou au | |||
* développement et à la reproduction du logiciel par l'utilisateur étant | |||
* donné sa spécificité de logiciel libre, qui peut le rendre complexe à | |||
* manipuler et qui le réserve donc à des développeurs et des professionnels | |||
* avertis possédant des connaissances informatiques approfondies. Les | |||
* utilisateurs sont donc invités à charger et tester l'adéquation du | |||
* logiciel à leurs besoins dans des conditions permettant d'assurer la | |||
* sécurité de leurs systèmes et ou de leurs données et, plus généralement, | |||
* à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. | |||
* | |||
* Le fait que vous puissiez accéder à cet en-tête signifie que vous avez | |||
* pris connaissance de la licence CeCILL, et que vous en avez accepté les | |||
* termes. | |||
*/ | |||
namespace common\logic\Setting; | |||
use common\components\ActiveRecordCommon; | |||
use common\logic\Producer\Producer\Model\Producer; | |||
class Setting extends ActiveRecordCommon | |||
{ | |||
/** | |||
* @inheritdoc | |||
*/ | |||
public static function tableName() | |||
{ | |||
return 'setting'; | |||
} | |||
/** | |||
* @inheritdoc | |||
*/ | |||
public function rules() | |||
{ | |||
return [ | |||
[['name'], 'required'], | |||
[['id_producer'], 'integer'], | |||
[['id_producer'], 'exist', 'skipOnError' => true, 'targetClass' => Producer::class, 'targetAttribute' => ['id_producer' => 'id']], | |||
[['name', 'string', 'text'], 'string'], | |||
[['name','string'], 'string', 'max' => 255], | |||
[['date'], 'date', 'format' => 'php:Y-m-d'], | |||
[['integer'], 'integer'], | |||
[['float', 'double'], 'number'], | |||
[['boolean'], 'boolean'], | |||
[['name'], 'unique'], | |||
]; | |||
} | |||
/** | |||
* @inheritdoc | |||
*/ | |||
public function attributeLabels() | |||
{ | |||
return [ | |||
'id' => 'ID', | |||
'id_producer' => 'Producteur', | |||
'name' => 'Nom', | |||
]; | |||
} | |||
public function getValue() | |||
{ | |||
$settingDetail = $this->getSettingDetail(); | |||
$type = $settingDetail->getType(); | |||
return $this->$type; | |||
} | |||
public function getSettingDetail() | |||
{ | |||
return SettingDefinition::getInstance()->getSettingDetailByName($this->name); | |||
} | |||
public function getProducer() | |||
{ | |||
return $this->hasOne(Producer::class, ['id' => 'id_producer']); | |||
} | |||
public function populateProducer(Producer $producer = null): void | |||
{ | |||
if($producer) { | |||
$this->populateFieldObject('id_producer', 'producer', $producer); | |||
} | |||
} | |||
} |
@@ -0,0 +1,84 @@ | |||
<?php | |||
namespace common\logic\Setting; | |||
use common\logic\AbstractBuilder; | |||
use common\logic\Producer\Producer\Model\Producer; | |||
use yii\base\ErrorException; | |||
class SettingBuilder extends AbstractBuilder | |||
{ | |||
protected SettingDefinition $settingDefinition; | |||
protected SettingRepository $settingRepository; | |||
public function loadDependencies(): void | |||
{ | |||
$this->settingDefinition = $this->loadService(SettingDefinition::class); | |||
$this->settingRepository = $this->loadService(SettingRepository::class); | |||
} | |||
public function instanciateSetting( | |||
string $name, | |||
Producer $producer = null | |||
): Setting | |||
{ | |||
$setting = new Setting(); | |||
$setting->name = $name; | |||
$setting->populateProducer($producer); | |||
$this->initDefaultValue($setting); | |||
return $setting; | |||
} | |||
public function createSetting( | |||
string $name, | |||
Producer $producer = null | |||
): Setting | |||
{ | |||
if($producer) { | |||
$setting = $this->settingRepository->findOneProducerSettingByName($name); | |||
} | |||
else { | |||
$setting = $this->settingRepository->findOneAdminSettingByName($name); | |||
} | |||
if(!$setting) { | |||
$setting = $this->instanciateSetting($name); | |||
$this->create($setting); | |||
} | |||
return $setting; | |||
} | |||
public function initValue(Setting $setting, $value) | |||
{ | |||
$settingDetail = $this->settingDefinition->getSettingDetailByName($setting->name); | |||
$type = $settingDetail->getType(); | |||
if(in_array($type, ['string', 'text', 'date', 'integer', 'float', 'double', 'boolean'])) { | |||
$setting->$type = $value; | |||
} | |||
else { | |||
throw new ErrorException("Le type de donnée du SettingDetail n'est pas reconnu."); | |||
} | |||
} | |||
public function initDefaultValue(Setting $setting) | |||
{ | |||
$settingDetail = $this->settingDefinition->getSettingDetailByName($setting->name); | |||
if($settingDetail->getDefaultValue()) { | |||
$this->initValue($setting, $settingDetail->getDefaultValue()); | |||
} | |||
} | |||
public function updateValue(Setting $setting, $value): void | |||
{ | |||
$this->initValue($setting, $value); | |||
$this->update($setting); | |||
} | |||
public function updateDefaultValueByName(Setting $setting) | |||
{ | |||
$this->initDefaultValue($setting); | |||
$this->update($setting); | |||
} | |||
} |
@@ -0,0 +1,47 @@ | |||
<?php | |||
namespace common\logic\Setting; | |||
use common\logic\AbstractDefinition; | |||
use common\logic\Setting\SettingDetails\Admin\AdminSettingDefinition; | |||
use common\logic\Setting\SettingDetails\Producer\ProducerSettingDefinition; | |||
class SettingDefinition extends AbstractDefinition | |||
{ | |||
public function getEntityFqcn(): string | |||
{ | |||
return Setting::class; | |||
} | |||
public function getSettingDetailByName(string $name) | |||
{ | |||
$adminSettingDefinition = AdminSettingDefinition::getInstance(); | |||
$producerSettingDefinition = ProducerSettingDefinition::getInstance(); | |||
$settingDetail = $this->findSettingDetailInArray($name, $adminSettingDefinition->getSettingDetails()); | |||
if(!$settingDetail) { | |||
$this->findSettingDetailInArray($name, $producerSettingDefinition->getSettingDetails()); | |||
} | |||
if(!$settingDetail) { | |||
throw new \Exception('SettingDetail non trouvé'); | |||
} | |||
return $settingDetail; | |||
} | |||
public function findSettingDetailInArray(string $name, array $settingDetailsArray) | |||
{ | |||
foreach($settingDetailsArray as $section => $subsectionsArray) { | |||
foreach($subsectionsArray as $subsection => $settingDetailsArray) { | |||
foreach($settingDetailsArray as $settingDetail) { | |||
if($name == $settingDetail->getName()) { | |||
return $settingDetail; | |||
} | |||
} | |||
} | |||
} | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,170 @@ | |||
<?php | |||
namespace common\logic\Setting\SettingDetails; | |||
class AbstractSettingDetail | |||
{ | |||
public string $name; | |||
public string $label; | |||
public string $type; | |||
public string $section; | |||
public ?string $formType = null; | |||
public array $options = []; | |||
public $defaultValue = null; | |||
public ?string $subSection = null; | |||
public ?string $helpMessage = null; | |||
public function setName(string $name): self | |||
{ | |||
$this->name = $name; | |||
return $this; | |||
} | |||
public function getName(): string | |||
{ | |||
return $this->name; | |||
} | |||
public function setLabel(string $label): self | |||
{ | |||
$this->label = $label; | |||
return $this; | |||
} | |||
public function getLabel(): string | |||
{ | |||
return $this->label; | |||
} | |||
public function setSection(string $section): self | |||
{ | |||
$this->section = $section; | |||
return $this; | |||
} | |||
public function getSection(): string | |||
{ | |||
return $this->section; | |||
} | |||
public function setSubSection(string $subSection): self | |||
{ | |||
$this->subSection = $subSection; | |||
return $this; | |||
} | |||
public function getSubSection(): ?string | |||
{ | |||
return $this->subSection; | |||
} | |||
public function setHelpMessage(string $helpMessage): self | |||
{ | |||
$this->helpMessage = $helpMessage; | |||
return $this; | |||
} | |||
public function getHelpMessage(): ?string | |||
{ | |||
return $this->helpMessage; | |||
} | |||
public function getFormType(): ?string | |||
{ | |||
return $this->formType; | |||
} | |||
public function setFormTypeInput(): self | |||
{ | |||
$this->formType = 'input'; | |||
return $this; | |||
} | |||
public function setFormTypeTextarea(): self | |||
{ | |||
$this->formType = 'textarea'; | |||
return $this; | |||
} | |||
public function setFormTypeCheckbox(): self | |||
{ | |||
$this->formType = 'checkbox'; | |||
return $this; | |||
} | |||
public function setFormTypeToggle(): self | |||
{ | |||
$this->formType = 'toggle'; | |||
return $this; | |||
} | |||
public function setFormTypeSelect(array $options): self | |||
{ | |||
$this->formType = 'select'; | |||
$this->options = $options; | |||
return $this; | |||
} | |||
public function getOptions(): array | |||
{ | |||
return $this->options; | |||
} | |||
public function setDefaultValue($defaultValue): self | |||
{ | |||
$this->defaultValue = $defaultValue; | |||
return $this; | |||
} | |||
public function getDefaultValue() | |||
{ | |||
return $this->defaultValue; | |||
} | |||
public function setTypeString(): self | |||
{ | |||
$this->type = 'string'; | |||
return $this; | |||
} | |||
public function setTypeText(): self | |||
{ | |||
$this->type = 'text'; | |||
return $this; | |||
} | |||
public function setTypeBoolean(): self | |||
{ | |||
$this->type = 'boolean'; | |||
return $this; | |||
} | |||
public function setTypeDate(): self | |||
{ | |||
$this->type = 'date'; | |||
return $this; | |||
} | |||
public function setTypeInteger(): self | |||
{ | |||
$this->type = 'integer'; | |||
return $this; | |||
} | |||
public function setTypeFloat(): self | |||
{ | |||
$this->type = 'float'; | |||
return $this; | |||
} | |||
public function setTypeDouble(): self | |||
{ | |||
$this->type = 'double'; | |||
return $this; | |||
} | |||
public function getType(): string | |||
{ | |||
return $this->type; | |||
} | |||
} |
@@ -0,0 +1,67 @@ | |||
<?php | |||
namespace common\logic\Setting\SettingDetails\Admin; | |||
use common\logic\Setting\SettingDefinition; | |||
use common\logic\Setting\SettingDetails\Admin\General\AdministratorEmailAdminSetting; | |||
use common\logic\Setting\SettingDetails\Admin\General\AdministratorPhoneNumberAdminSetting; | |||
class AdminSettingDefinition extends SettingDefinition | |||
{ | |||
const SECTION_GENERAL = 'general'; | |||
const SUBSECTION_GENERAL = 'general.main'; | |||
public function getSettingDetails(): array | |||
{ | |||
return [ | |||
self::SECTION_GENERAL => [ | |||
self::SUBSECTION_GENERAL => [ | |||
new AdministratorEmailAdminSetting, | |||
new AdministratorPhoneNumberAdminSetting, | |||
] | |||
], | |||
]; | |||
} | |||
public function getSectionLabels(): array | |||
{ | |||
return [ | |||
self::SECTION_GENERAL => 'General', | |||
self::SUBSECTION_GENERAL => 'General', | |||
]; | |||
} | |||
public function getSectionsArray(): array | |||
{ | |||
$sectionsArray = []; | |||
foreach($this->getSettingDetails() as $sectionName => $subsectionsArray) { | |||
$sectionsArray[] = [ | |||
'name' => $sectionName, | |||
'nameDisplay' => $this->getSectionLabelBySectionName($sectionName), | |||
]; | |||
} | |||
return $sectionsArray; | |||
} | |||
public function getSettingDetailsFlat(): array | |||
{ | |||
$settingDetailsFlatArray = []; | |||
foreach($this->getSettingDetails() as $sectionsArray) { | |||
foreach($sectionsArray as $subsectionsArray) { | |||
foreach($subsectionsArray as $settingDetail) { | |||
$settingDetailsFlatArray[] = $settingDetail; | |||
} | |||
} | |||
} | |||
return $settingDetailsFlatArray; | |||
} | |||
public function getSectionLabelBySectionName(string $sectionName): string | |||
{ | |||
return $this->getSectionLabels()[$sectionName]; | |||
} | |||
} |
@@ -0,0 +1,17 @@ | |||
<?php | |||
namespace common\logic\Setting\SettingDetails\Admin\General; | |||
use common\logic\Setting\SettingDetails\AbstractSettingDetail; | |||
class AdministratorEmailAdminSetting extends AbstractSettingDetail | |||
{ | |||
public function __construct() | |||
{ | |||
$this | |||
->setName('administratorEmail') | |||
->setLabel("Email de l'administrateur") | |||
->setTypeString() | |||
->setFormTypeInput(); | |||
} | |||
} |
@@ -0,0 +1,17 @@ | |||
<?php | |||
namespace common\logic\Setting\SettingDetails\Admin\General; | |||
use common\logic\Setting\SettingDetails\AbstractSettingDetail; | |||
class AdministratorPhoneNumberAdminSetting extends AbstractSettingDetail | |||
{ | |||
public function __construct() | |||
{ | |||
$this | |||
->setName('administratorPhoneNumber') | |||
->setLabel("Numéro de téléphone de l'administrateur") | |||
->setTypeString() | |||
->setFormTypeInput(); | |||
} | |||
} |
@@ -0,0 +1,30 @@ | |||
<?php | |||
namespace common\logic\Setting\SettingDetails\Producer; | |||
use common\logic\Setting\SettingDefinition; | |||
class ProducerSettingDefinition extends SettingDefinition | |||
{ | |||
const SECTION_GENERAL = 'general'; | |||
const SUBSECTION_GENERAL = 'general.main'; | |||
public function getSettings(): array | |||
{ | |||
return [ | |||
self::SECTION_GENERAL => [ | |||
self::SUBSECTION_GENERAL => [ | |||
// ... | |||
] | |||
] | |||
]; | |||
} | |||
public function getSectionLabels(): array | |||
{ | |||
return [ | |||
self::SECTION_GENERAL => 'General', | |||
self::SUBSECTION_GENERAL => 'General', | |||
]; | |||
} | |||
} |
@@ -0,0 +1,37 @@ | |||
<?php | |||
namespace common\logic\Setting; | |||
use common\logic\AbstractManager; | |||
use common\logic\Setting\SettingDetails\Admin\AdminSettingDefinition; | |||
class SettingImporter extends AbstractManager | |||
{ | |||
protected AdminSettingDefinition $adminSettingDefinition; | |||
protected SettingBuilder $settingBuilder; | |||
public function loadDependencies(): void | |||
{ | |||
$this->adminSettingDefinition = $this->loadService(AdminSettingDefinition::class); | |||
$this->settingBuilder = $this->loadService(SettingBuilder::class); | |||
} | |||
public function importFromDefinitions() | |||
{ | |||
$this->importFromAdminSettingDefinition(); | |||
$this->importFromProducerSettingDefinition(); | |||
} | |||
public function importFromAdminSettingDefinition(): void | |||
{ | |||
\Yii::$app->logic->setProducerContext(null); | |||
foreach ($this->adminSettingDefinition->getSettingDetailsFlat() as $settingDetail) { | |||
$this->settingBuilder->createSetting($settingDetail->getName()); | |||
} | |||
} | |||
public function importFromProducerSettingDefinition(): void | |||
{ | |||
// /!\ bien définir le contexte producteur | |||
} | |||
} |
@@ -0,0 +1,53 @@ | |||
<?php | |||
namespace common\logic\Setting; | |||
use common\logic\AbstractModule; | |||
use common\logic\Setting\SettingDetails\Admin\AdminSettingDefinition; | |||
use common\logic\Setting\SettingDetails\Producer\ProducerSettingDefinition; | |||
class SettingModule extends AbstractModule | |||
{ | |||
public function getServices(): array | |||
{ | |||
return [ | |||
SettingDefinition::class, | |||
AdminSettingDefinition::class, | |||
ProducerSettingDefinition::class, | |||
SettingRepository::class, | |||
SettingBuilder::class, | |||
SettingImporter::class, | |||
AdminSettingBag::class | |||
]; | |||
} | |||
public function getDefinition(): SettingDefinition | |||
{ | |||
return SettingDefinition::getInstance(); | |||
} | |||
public function getAdminSettingDefinition(): AdminSettingDefinition | |||
{ | |||
return AdminSettingDefinition::getInstance(); | |||
} | |||
public function getProducerSettingDefinition(): ProducerSettingDefinition | |||
{ | |||
return ProducerSettingDefinition::getInstance(); | |||
} | |||
public function getRepository(): SettingRepository | |||
{ | |||
return SettingRepository::getInstance(); | |||
} | |||
public function getImporter(): SettingImporter | |||
{ | |||
return SettingImporter::getInstance(); | |||
} | |||
public function getAdminSettingBag(): AdminSettingBag | |||
{ | |||
return AdminSettingBag::getInstance(); | |||
} | |||
} |
@@ -0,0 +1,50 @@ | |||
<?php | |||
namespace common\logic\Setting; | |||
use common\logic\AbstractRepository; | |||
class SettingRepository extends AbstractRepository | |||
{ | |||
protected SettingRepositoryQuery $query; | |||
public function loadDependencies(): void | |||
{ | |||
$this->loadQuery(SettingRepositoryQuery::class); | |||
} | |||
public function getDefaultOptionsSearch(): array | |||
{ | |||
return [ | |||
self::WITH => ['producer'], | |||
self::JOIN_WITH => [], | |||
self::ORDER_BY => '', | |||
self::ATTRIBUTE_ID_PRODUCER => 'setting.id_producer' | |||
]; | |||
} | |||
public function findOneSettingByName(string $name) | |||
{ | |||
if($this->isOutOfProducerContext()) { | |||
return $this->findOneAdminSettingByName($name); | |||
} | |||
else { | |||
return $this->findOneProducerSettingByName($name); | |||
} | |||
} | |||
public function findOneAdminSettingByName(string $name) | |||
{ | |||
return $this->createQuery() | |||
->filterProducerIsNull() | |||
->filterByName($name) | |||
->findOne(); | |||
} | |||
public function findOneProducerSettingByName(string $name) | |||
{ | |||
return $this->createDefaultQuery() | |||
->filterByName($name) | |||
->findOne(); | |||
} | |||
} |
@@ -0,0 +1,27 @@ | |||
<?php | |||
namespace common\logic\Setting; | |||
use common\logic\AbstractRepositoryQuery; | |||
class SettingRepositoryQuery extends AbstractRepositoryQuery | |||
{ | |||
protected SettingDefinition $definition; | |||
public function loadDependencies(): void | |||
{ | |||
$this->loadDefinition(SettingDefinition::class); | |||
} | |||
public function filterProducerIsNull(): self | |||
{ | |||
$this->andWhere(['id_producer' => null]); | |||
return $this; | |||
} | |||
public function filterByName(string $name): self | |||
{ | |||
$this->andWhere(['name' => $name]); | |||
return $this; | |||
} | |||
} |
@@ -60,6 +60,8 @@ $orderModule = OrderModule::getInstance(); | |||
<?php endif; ?> | |||
<?php if(strlen($pointSale->locality) > 0): ?> situé à <?= Html::encode($pointSale->locality) ?><?php endif ?>.</p> | |||
<p>Retrouvez à tout moment votre commande dans l'espace de votre producteur via l'onglet <a href="<?= Yii::$app->urlManager->createAbsoluteUrl('order/history') ?>">Mes commandes</a>.</p> | |||
<?php $payment_infos = $producerModule->getConfig('option_payment_info') ; ?> | |||
<?php if($payment_infos && strlen($payment_infos) > 0): ?> | |||
<p><strong>Informations de paiement :</strong><br /> |
@@ -45,7 +45,7 @@ $userModule = UserModule::getInstance(); | |||
Bonjour, | |||
Le client <?= $userModule->getUsername() ?> vient de passer une commande pour le <?= date('d/m/Y',strtotime($distribution->date)) ?> mais le paiement par carte bancaire n'a pas abouti. | |||
Le client <?= $userModule->getUsername($user) ?> vient de passer une commande pour le <?= date('d/m/Y',strtotime($distribution->date)) ?> mais le paiement par carte bancaire n'a pas abouti. | |||
Il vient de recevoir un message pour régulariser le paiement par virement bancaire. | |||
Sa commande a été enregistrée avec l'état "non payé". |
@@ -0,0 +1,32 @@ | |||
<?php | |||
require_once dirname(__FILE__).'/_macros.php'; | |||
version( | |||
'13/11/2023', | |||
[ | |||
[ | |||
"[Administration] Utilisateurs > liste : possibilité de filtrer par groupe,", | |||
"[Administration] Utilisateurs > création : possibilité de choisir d'envoyer ou non l'email de bienvenue", | |||
"[Administration] Utilisateurs > import : possibilité de choisir d'envoyer ou non l'email de bienvenue", | |||
"[Administration] Documents : logo et nom/adresse du producteur sur la même ligne dans l'entête", | |||
"[Administration] Documents : possibilité d'afficher le prix au kg dans la colonne 'Prix unitaire' des PDF", | |||
"[Administration] Utilisateurs > formulaire crédit : possibilité de choisir si le champs 'Prévenir l'utilisateur' est coché par défaut ou non", | |||
"[Boutique] Inscription : possibilité d'ajouter automatiquement un utilisateur à un groupe au moment de son inscription", | |||
], | |||
[ | |||
"[Administration] Tableau de bord : correctif lien export distribution cassé (404)", | |||
] | |||
], | |||
[ | |||
[ | |||
"[Technique] Feature flag : première version" | |||
], | |||
[ | |||
"[Boutique] Contact : correctif spam et sender from", | |||
] | |||
], | |||
$userCurrent | |||
); | |||
?> |
@@ -0,0 +1,31 @@ | |||
<?php | |||
require_once dirname(__FILE__).'/_macros.php'; | |||
version( | |||
'20/11/2023', | |||
[ | |||
[ | |||
"[Administration] Export : première version étiquettes avancées (formats spécifiques)", | |||
"[Administration] Documents PDF : gestion images pied de page", | |||
"[Administration et boutique] Points de vente : minimum de commande", | |||
"[Boutique] Commander : envoi d'un email de confirmation lors d'une modification de commande", | |||
"[Boutique] Produits : gestion de l'affichage en grand des images", | |||
"[Boutique] Commander : suppression étape 'Confirmation'", | |||
], | |||
[ | |||
"[Administration] Communiquer > envoyer un email : correctif point de vente supprimé visible" | |||
] | |||
], | |||
[ | |||
[ | |||
"[Global] Système de feature flag", | |||
"[Technique] Paramètres : nouveau système de settings" | |||
], | |||
[ | |||
] | |||
], | |||
$userCurrent | |||
); | |||
?> |
@@ -0,0 +1,386 @@ | |||
.slbOverlay, .slbWrapOuter, .slbWrap { | |||
position: fixed; | |||
top: 0; | |||
right: 0; | |||
bottom: 0; | |||
left: 0; | |||
} | |||
.slbOverlay { | |||
overflow: hidden; | |||
z-index: 2000; | |||
background-color: #000; | |||
opacity: 0.7; | |||
-webkit-animation: slbOverlay 0.5s; | |||
-moz-animation: slbOverlay 0.5s; | |||
animation: slbOverlay 0.5s; | |||
} | |||
.slbWrapOuter { | |||
overflow-x: hidden; | |||
overflow-y: auto; | |||
z-index: 2010; | |||
} | |||
.slbWrap { | |||
position: absolute; | |||
text-align: center; | |||
} | |||
.slbWrap:before { | |||
content: ""; | |||
display: inline-block; | |||
height: 100%; | |||
vertical-align: middle; | |||
} | |||
.slbContentOuter { | |||
position: relative; | |||
display: inline-block; | |||
vertical-align: middle; | |||
margin: 0px auto; | |||
padding: 0 1em; | |||
box-sizing: border-box; | |||
z-index: 2020; | |||
text-align: left; | |||
max-width: 100%; | |||
} | |||
.slbContentEl .slbContentOuter { | |||
padding: 5em 1em; | |||
} | |||
.slbContent { | |||
position: relative; | |||
} | |||
.slbContentEl .slbContent { | |||
-webkit-animation: slbEnter 0.3s; | |||
-moz-animation: slbEnter 0.3s; | |||
animation: slbEnter 0.3s; | |||
background-color: #fff; | |||
box-shadow: 0 0.2em 1em rgba(0, 0, 0, 0.4); | |||
} | |||
.slbImageWrap { | |||
-webkit-animation: slbEnter 0.3s; | |||
-moz-animation: slbEnter 0.3s; | |||
animation: slbEnter 0.3s; | |||
position: relative; | |||
} | |||
.slbImageWrap:after { | |||
content: ""; | |||
position: absolute; | |||
left: 0; | |||
right: 0; | |||
top: 5em; | |||
bottom: 5em; | |||
display: block; | |||
z-index: -1; | |||
box-shadow: 0 0.2em 1em rgba(0, 0, 0, 0.6); | |||
background-color: #FFF; | |||
} | |||
.slbDirectionNext .slbImageWrap { | |||
-webkit-animation: slbEnterNext 0.4s; | |||
-moz-animation: slbEnterNext 0.4s; | |||
animation: slbEnterNext 0.4s; | |||
} | |||
.slbDirectionPrev .slbImageWrap { | |||
-webkit-animation: slbEnterPrev 0.4s; | |||
-moz-animation: slbEnterPrev 0.4s; | |||
animation: slbEnterPrev 0.4s; | |||
} | |||
.slbImage { | |||
width: auto; | |||
max-width: 100%; | |||
height: auto; | |||
display: block; | |||
line-height: 0; | |||
box-sizing: border-box; | |||
padding: 5em 0; | |||
margin: 0 auto; | |||
} | |||
.slbCaption { | |||
display: inline-block; | |||
max-width: 100%; | |||
overflow: hidden; | |||
text-overflow: ellipsis; | |||
white-space: nowrap; | |||
word-wrap: normal; | |||
font-size: 1.4em; | |||
position: absolute; | |||
left: 0; | |||
right: 0; | |||
bottom: 0; | |||
padding: 0.71429em 0; | |||
color: #fff; | |||
color: rgba(255, 255, 255, 0.7); | |||
text-align: center; | |||
} | |||
.slbCloseBtn, .slbArrow { | |||
margin: 0; | |||
padding: 0; | |||
border: 0; | |||
cursor: pointer; | |||
background: none; | |||
} | |||
.slbCloseBtn::-moz-focus-inner, .slbArrow::-moz-focus-inner { | |||
padding: 0; | |||
border: 0; | |||
} | |||
.slbCloseBtn:hover, .slbArrow:hover { | |||
opacity: 0.5; | |||
} | |||
.slbCloseBtn:active, .slbArrow:active { | |||
opacity: 0.8; | |||
} | |||
.slbCloseBtn { | |||
-webkit-animation: slbEnter 0.3s; | |||
-moz-animation: slbEnter 0.3s; | |||
animation: slbEnter 0.3s; | |||
font-size: 3em; | |||
width: 1.66667em; | |||
height: 1.66667em; | |||
line-height: 1.66667em; | |||
position: absolute; | |||
right: -0.33333em; | |||
top: 0; | |||
color: #fff; | |||
color: rgba(255, 255, 255, 0.7); | |||
text-align: center; | |||
} | |||
.slbLoading .slbCloseBtn { | |||
display: none; | |||
} | |||
.slbLoadingText { | |||
font-size: 1.4em; | |||
color: #fff; | |||
color: rgba(255, 255, 255, 0.9); | |||
} | |||
.slbArrows { | |||
position: fixed; | |||
top: 50%; | |||
left: 0; | |||
right: 0; | |||
} | |||
.slbLoading .slbArrows { | |||
display: none; | |||
} | |||
.slbArrow { | |||
position: absolute; | |||
top: 50%; | |||
margin-top: -5em; | |||
width: 5em; | |||
height: 10em; | |||
opacity: 0.7; | |||
text-indent: -999em; | |||
overflow: hidden; | |||
} | |||
.slbArrow:before { | |||
content: ""; | |||
position: absolute; | |||
top: 50%; | |||
left: 50%; | |||
margin: -0.8em 0 0 -0.8em; | |||
border: 0.8em solid transparent; | |||
} | |||
.slbArrow.next { | |||
right: 0; | |||
} | |||
.slbArrow.next:before { | |||
border-left-color: #fff; | |||
} | |||
.slbArrow.prev { | |||
left: 0; | |||
} | |||
.slbArrow.prev:before { | |||
border-right-color: #fff; | |||
} | |||
.slbIframeCont { | |||
width: 80em; | |||
height: 0; | |||
overflow: hidden; | |||
padding-top: 56.25%; | |||
margin: 5em 0; | |||
} | |||
.slbIframe { | |||
position: absolute; | |||
top: 0; | |||
left: 0; | |||
width: 100%; | |||
height: 100%; | |||
box-shadow: 0 0.2em 1em rgba(0, 0, 0, 0.6); | |||
background: #000; | |||
} | |||
@-webkit-keyframes slbOverlay { | |||
from { | |||
opacity: 0; | |||
} | |||
to { | |||
opacity: 0.7; | |||
} | |||
} | |||
@-moz-keyframes slbOverlay { | |||
from { | |||
opacity: 0; | |||
} | |||
to { | |||
opacity: 0.7; | |||
} | |||
} | |||
@keyframes slbOverlay { | |||
from { | |||
opacity: 0; | |||
} | |||
to { | |||
opacity: 0.7; | |||
} | |||
} | |||
@-webkit-keyframes slbEnter { | |||
from { | |||
opacity: 0; | |||
-webkit-transform: translate3d(0, -1em, 0); | |||
} | |||
to { | |||
opacity: 1; | |||
-webkit-transform: translate3d(0, 0, 0); | |||
} | |||
} | |||
@-moz-keyframes slbEnter { | |||
from { | |||
opacity: 0; | |||
-moz-transform: translate3d(0, -1em, 0); | |||
} | |||
to { | |||
opacity: 1; | |||
-moz-transform: translate3d(0, 0, 0); | |||
} | |||
} | |||
@keyframes slbEnter { | |||
from { | |||
opacity: 0; | |||
-webkit-transform: translate3d(0, -1em, 0); | |||
-moz-transform: translate3d(0, -1em, 0); | |||
-ms-transform: translate3d(0, -1em, 0); | |||
-o-transform: translate3d(0, -1em, 0); | |||
transform: translate3d(0, -1em, 0); | |||
} | |||
to { | |||
opacity: 1; | |||
-webkit-transform: translate3d(0, 0, 0); | |||
-moz-transform: translate3d(0, 0, 0); | |||
-ms-transform: translate3d(0, 0, 0); | |||
-o-transform: translate3d(0, 0, 0); | |||
transform: translate3d(0, 0, 0); | |||
} | |||
} | |||
@-webkit-keyframes slbEnterNext { | |||
from { | |||
opacity: 0; | |||
-webkit-transform: translate3d(4em, 0, 0); | |||
} | |||
to { | |||
opacity: 1; | |||
-webkit-transform: translate3d(0, 0, 0); | |||
} | |||
} | |||
@-moz-keyframes slbEnterNext { | |||
from { | |||
opacity: 0; | |||
-moz-transform: translate3d(4em, 0, 0); | |||
} | |||
to { | |||
opacity: 1; | |||
-moz-transform: translate3d(0, 0, 0); | |||
} | |||
} | |||
@keyframes slbEnterNext { | |||
from { | |||
opacity: 0; | |||
-webkit-transform: translate3d(4em, 0, 0); | |||
-moz-transform: translate3d(4em, 0, 0); | |||
-ms-transform: translate3d(4em, 0, 0); | |||
-o-transform: translate3d(4em, 0, 0); | |||
transform: translate3d(4em, 0, 0); | |||
} | |||
to { | |||
opacity: 1; | |||
-webkit-transform: translate3d(0, 0, 0); | |||
-moz-transform: translate3d(0, 0, 0); | |||
-ms-transform: translate3d(0, 0, 0); | |||
-o-transform: translate3d(0, 0, 0); | |||
transform: translate3d(0, 0, 0); | |||
} | |||
} | |||
@-webkit-keyframes slbEnterPrev { | |||
from { | |||
opacity: 0; | |||
-webkit-transform: translate3d(-4em, 0, 0); | |||
} | |||
to { | |||
opacity: 1; | |||
-webkit-transform: translate3d(0, 0, 0); | |||
} | |||
} | |||
@-moz-keyframes slbEnterPrev { | |||
from { | |||
opacity: 0; | |||
-moz-transform: translate3d(-4em, 0, 0); | |||
} | |||
to { | |||
opacity: 1; | |||
-moz-transform: translate3d(0, 0, 0); | |||
} | |||
} | |||
@keyframes slbEnterPrev { | |||
from { | |||
opacity: 0; | |||
-webkit-transform: translate3d(-4em, 0, 0); | |||
-moz-transform: translate3d(-4em, 0, 0); | |||
-ms-transform: translate3d(-4em, 0, 0); | |||
-o-transform: translate3d(-4em, 0, 0); | |||
transform: translate3d(-4em, 0, 0); | |||
} | |||
to { | |||
opacity: 1; | |||
-webkit-transform: translate3d(0, 0, 0); | |||
-moz-transform: translate3d(0, 0, 0); | |||
-ms-transform: translate3d(0, 0, 0); | |||
-o-transform: translate3d(0, 0, 0); | |||
transform: translate3d(0, 0, 0); | |||
} | |||
} |
@@ -0,0 +1,532 @@ | |||
(function(root, factory) { | |||
if (typeof define === 'function' && define.amd) { | |||
define([], factory); | |||
} else if (typeof module === 'object' && module.exports) { | |||
module.exports = factory(); | |||
} else { | |||
root.SimpleLightbox = factory(); | |||
} | |||
}(this, function() { | |||
function assign(target) { | |||
for (var i = 1; i < arguments.length; i++) { | |||
var obj = arguments[i]; | |||
if (obj) { | |||
for (var key in obj) { | |||
obj.hasOwnProperty(key) && (target[key] = obj[key]); | |||
} | |||
} | |||
} | |||
return target; | |||
} | |||
function addClass(element, className) { | |||
if (element && className) { | |||
element.className += ' ' + className; | |||
} | |||
} | |||
function removeClass(element, className) { | |||
if (element && className) { | |||
element.className = element.className.replace( | |||
new RegExp('(\\s|^)' + className + '(\\s|$)'), ' ' | |||
).trim(); | |||
} | |||
} | |||
function parseHtml(html) { | |||
var div = document.createElement('div'); | |||
div.innerHTML = html.trim(); | |||
return div.childNodes[0]; | |||
} | |||
function matches(el, selector) { | |||
return (el.matches || el.matchesSelector || el.msMatchesSelector).call(el, selector); | |||
} | |||
function getWindowHeight() { | |||
return 'innerHeight' in window | |||
? window.innerHeight | |||
: document.documentElement.offsetHeight; | |||
} | |||
function SimpleLightbox(options) { | |||
this.init.apply(this, arguments); | |||
} | |||
SimpleLightbox.defaults = { | |||
// add custom classes to lightbox elements | |||
elementClass: '', | |||
elementLoadingClass: 'slbLoading', | |||
htmlClass: 'slbActive', | |||
closeBtnClass: '', | |||
nextBtnClass: '', | |||
prevBtnClass: '', | |||
loadingTextClass: '', | |||
// customize / localize controls captions | |||
closeBtnCaption: 'Close', | |||
nextBtnCaption: 'Next', | |||
prevBtnCaption: 'Previous', | |||
loadingCaption: 'Loading...', | |||
bindToItems: true, // set click event handler to trigger lightbox on provided $items | |||
closeOnOverlayClick: true, | |||
closeOnEscapeKey: true, | |||
nextOnImageClick: true, | |||
showCaptions: true, | |||
captionAttribute: 'title', // choose data source for library to glean image caption from | |||
urlAttribute: 'href', // where to expect large image | |||
startAt: 0, // start gallery at custom index | |||
loadingTimeout: 100, // time after loading element will appear | |||
appendTarget: 'body', // append elsewhere if needed | |||
beforeSetContent: null, // convenient hooks for extending library behavoiur | |||
beforeClose: null, | |||
afterClose: null, | |||
beforeDestroy: null, | |||
afterDestroy: null, | |||
videoRegex: new RegExp(/youtube.com|vimeo.com/) // regex which tests load url for iframe content | |||
}; | |||
assign(SimpleLightbox.prototype, { | |||
init: function(options) { | |||
options = this.options = assign({}, SimpleLightbox.defaults, options); | |||
var self = this; | |||
var elements; | |||
if (options.$items) { | |||
elements = options.$items.get(); | |||
} | |||
if (options.elements) { | |||
elements = [].slice.call( | |||
typeof options.elements === 'string' | |||
? document.querySelectorAll(options.elements) | |||
: options.elements | |||
); | |||
} | |||
this.eventRegistry = {lightbox: [], thumbnails: []}; | |||
this.items = []; | |||
this.captions = []; | |||
if (elements) { | |||
elements.forEach(function(element, index) { | |||
self.items.push(element.getAttribute(options.urlAttribute)); | |||
self.captions.push(element.getAttribute(options.captionAttribute)); | |||
if (options.bindToItems) { | |||
self.addEvent(element, 'click', function(e) { | |||
e.preventDefault(); | |||
self.showPosition(index); | |||
}, 'thumbnails'); | |||
} | |||
}); | |||
} | |||
if (options.items) { | |||
this.items = options.items; | |||
} | |||
if (options.captions) { | |||
this.captions = options.captions; | |||
} | |||
}, | |||
addEvent: function(element, eventName, callback, scope) { | |||
this.eventRegistry[scope || 'lightbox'].push({ | |||
element: element, | |||
eventName: eventName, | |||
callback: callback | |||
}); | |||
element.addEventListener(eventName, callback); | |||
return this; | |||
}, | |||
removeEvents: function(scope) { | |||
this.eventRegistry[scope].forEach(function(item) { | |||
item.element.removeEventListener(item.eventName, item.callback); | |||
}); | |||
this.eventRegistry[scope] = []; | |||
return this; | |||
}, | |||
next: function() { | |||
return this.showPosition(this.currentPosition + 1); | |||
}, | |||
prev: function() { | |||
return this.showPosition(this.currentPosition - 1); | |||
}, | |||
normalizePosition: function(position) { | |||
if (position >= this.items.length) { | |||
position = 0; | |||
} else if (position < 0) { | |||
position = this.items.length - 1; | |||
} | |||
return position; | |||
}, | |||
showPosition: function(position) { | |||
var newPosition = this.normalizePosition(position); | |||
if (typeof this.currentPosition !== 'undefined') { | |||
this.direction = newPosition > this.currentPosition ? 'next' : 'prev'; | |||
} | |||
this.currentPosition = newPosition; | |||
return this.setupLightboxHtml() | |||
.prepareItem(this.currentPosition, this.setContent) | |||
.show(); | |||
}, | |||
loading: function(on) { | |||
var self = this; | |||
var options = this.options; | |||
if (on) { | |||
this.loadingTimeout = setTimeout(function() { | |||
addClass(self.$el, options.elementLoadingClass); | |||
self.$content.innerHTML = | |||
'<p class="slbLoadingText ' + options.loadingTextClass + '">' + | |||
options.loadingCaption + | |||
'</p>'; | |||
self.show(); | |||
}, options.loadingTimeout); | |||
} else { | |||
removeClass(this.$el, options.elementLoadingClass); | |||
clearTimeout(this.loadingTimeout); | |||
} | |||
}, | |||
prepareItem: function(position, callback) { | |||
var self = this; | |||
var url = this.items[position]; | |||
this.loading(true); | |||
if (this.options.videoRegex.test(url)) { | |||
callback.call(self, parseHtml( | |||
'<div class="slbIframeCont"><iframe class="slbIframe" frameborder="0" allowfullscreen src="' + url + '"></iframe></div>') | |||
); | |||
} else { | |||
var $imageCont = parseHtml( | |||
'<div class="slbImageWrap"><img class="slbImage" src="' + url + '" /></div>' | |||
); | |||
this.$currentImage = $imageCont.querySelector('.slbImage'); | |||
if (this.options.showCaptions && this.captions[position]) { | |||
$imageCont.appendChild(parseHtml( | |||
'<div class="slbCaption">' + this.captions[position] + '</div>') | |||
); | |||
} | |||
this.loadImage(url, function() { | |||
self.setImageDimensions(); | |||
callback.call(self, $imageCont); | |||
self.loadImage(self.items[self.normalizePosition(self.currentPosition + 1)]); | |||
}); | |||
} | |||
return this; | |||
}, | |||
loadImage: function(url, callback) { | |||
if (!this.options.videoRegex.test(url)) { | |||
var image = new Image(); | |||
callback && (image.onload = callback); | |||
image.src = url; | |||
} | |||
}, | |||
setupLightboxHtml: function() { | |||
var o = this.options; | |||
if (!this.$el) { | |||
this.$el = parseHtml( | |||
'<div class="slbElement ' + o.elementClass + '">' + | |||
'<div class="slbOverlay"></div>' + | |||
'<div class="slbWrapOuter">' + | |||
'<div class="slbWrap">' + | |||
'<div class="slbContentOuter">' + | |||
'<div class="slbContent"></div>' + | |||
'<button type="button" title="' + o.closeBtnCaption + '" class="slbCloseBtn ' + o.closeBtnClass + '">×</button>' + | |||
(this.items.length > 1 | |||
? '<div class="slbArrows">' + | |||
'<button type="button" title="' + o.prevBtnCaption + '" class="prev slbArrow' + o.prevBtnClass + '">' + o.prevBtnCaption + '</button>' + | |||
'<button type="button" title="' + o.nextBtnCaption + '" class="next slbArrow' + o.nextBtnClass + '">' + o.nextBtnCaption + '</button>' + | |||
'</div>' | |||
: '' | |||
) + | |||
'</div>' + | |||
'</div>' + | |||
'</div>' + | |||
'</div>' | |||
); | |||
this.$content = this.$el.querySelector('.slbContent'); | |||
} | |||
this.$content.innerHTML = ''; | |||
return this; | |||
}, | |||
show: function() { | |||
if (!this.modalInDom) { | |||
document.querySelector(this.options.appendTarget).appendChild(this.$el); | |||
addClass(document.documentElement, this.options.htmlClass); | |||
this.setupLightboxEvents(); | |||
this.modalInDom = true; | |||
} | |||
return this; | |||
}, | |||
setContent: function(content) { | |||
var $content = typeof content === 'string' | |||
? parseHtml(content) | |||
: content | |||
; | |||
this.loading(false); | |||
this.setupLightboxHtml(); | |||
removeClass(this.$content, 'slbDirectionNext'); | |||
removeClass(this.$content, 'slbDirectionPrev'); | |||
if (this.direction) { | |||
addClass(this.$content, this.direction === 'next' | |||
? 'slbDirectionNext' | |||
: 'slbDirectionPrev' | |||
); | |||
} | |||
if (this.options.beforeSetContent) { | |||
this.options.beforeSetContent($content, this); | |||
} | |||
this.$content.appendChild($content); | |||
return this; | |||
}, | |||
setImageDimensions: function() { | |||
if (this.$currentImage) { | |||
this.$currentImage.style.maxHeight = getWindowHeight() + 'px'; | |||
} | |||
}, | |||
setupLightboxEvents: function() { | |||
var self = this; | |||
if (this.eventRegistry.lightbox.length) { | |||
return this; | |||
} | |||
this.addEvent(this.$el, 'click', function(e) { | |||
var $target = e.target; | |||
if (matches($target, '.slbCloseBtn') || (self.options.closeOnOverlayClick && matches($target, '.slbWrap'))) { | |||
self.close(); | |||
} else if (matches($target, '.slbArrow')) { | |||
matches($target, '.next') ? self.next() : self.prev(); | |||
} else if (self.options.nextOnImageClick && self.items.length > 1 && matches($target, '.slbImage')) { | |||
self.next(); | |||
} | |||
}).addEvent(document, 'keyup', function(e) { | |||
self.options.closeOnEscapeKey && e.keyCode === 27 && self.close(); | |||
if (self.items.length > 1) { | |||
(e.keyCode === 39 || e.keyCode === 68) && self.next(); | |||
(e.keyCode === 37 || e.keyCode === 65) && self.prev(); | |||
} | |||
}).addEvent(window, 'resize', function() { | |||
self.setImageDimensions(); | |||
}); | |||
return this; | |||
}, | |||
close: function() { | |||
if (this.modalInDom) { | |||
this.runHook('beforeClose'); | |||
this.removeEvents('lightbox'); | |||
this.$el && this.$el.parentNode.removeChild(this.$el); | |||
removeClass(document.documentElement, this.options.htmlClass); | |||
this.modalInDom = false; | |||
this.runHook('afterClose'); | |||
} | |||
this.direction = undefined; | |||
this.currentPosition = this.options.startAt; | |||
}, | |||
destroy: function() { | |||
this.close(); | |||
this.runHook('beforeDestroy'); | |||
this.removeEvents('thumbnails'); | |||
this.runHook('afterDestroy'); | |||
}, | |||
runHook: function(name) { | |||
this.options[name] && this.options[name](this); | |||
} | |||
}); | |||
SimpleLightbox.open = function(options) { | |||
var instance = new SimpleLightbox(options); | |||
return options.content | |||
? instance.setContent(options.content).show() | |||
: instance.showPosition(instance.options.startAt); | |||
}; | |||
SimpleLightbox.registerAsJqueryPlugin = function($) { | |||
$.fn.simpleLightbox = function(options) { | |||
var lightboxInstance; | |||
var $items = this; | |||
return this.each(function() { | |||
if (!$.data(this, 'simpleLightbox')) { | |||
lightboxInstance = lightboxInstance || new SimpleLightbox($.extend({}, options, {$items: $items})); | |||
$.data(this, 'simpleLightbox', lightboxInstance); | |||
} | |||
}); | |||
}; | |||
$.SimpleLightbox = SimpleLightbox; | |||
}; | |||
if (typeof window !== 'undefined' && window.jQuery) { | |||
SimpleLightbox.registerAsJqueryPlugin(window.jQuery); | |||
} | |||
return SimpleLightbox; | |||
})); |
@@ -37,7 +37,8 @@ | |||
"weluse/yii2-mailjet": "^0.2.0", | |||
"ext-json": "*", | |||
"ext-curl": "*", | |||
"yiisoft/yii2-twig": "^2.4" | |||
"yiisoft/yii2-twig": "^2.4", | |||
"letyii/yii2-tinymce": "dev-master" | |||
}, | |||
"require-dev": { | |||
"yiisoft/yii2-codeception": "*", |
@@ -4,7 +4,7 @@ | |||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", | |||
"This file is @generated automatically" | |||
], | |||
"content-hash": "a8cbf9ba6bfa2f0b47fba2344732ac95", | |||
"content-hash": "95e88fd70427210dc0d1edd79d17cce1", | |||
"packages": [ | |||
{ | |||
"name": "2amigos/yii2-chartjs-widget", | |||
@@ -1190,6 +1190,48 @@ | |||
], | |||
"time": "2022-09-19T18:31:07+00:00" | |||
}, | |||
{ | |||
"name": "letyii/yii2-tinymce", | |||
"version": "dev-master", | |||
"source": { | |||
"type": "git", | |||
"url": "https://github.com/letyii/yii2-tinymce.git", | |||
"reference": "861873f30d9e16f76239ae827f2848879f66f78f" | |||
}, | |||
"dist": { | |||
"type": "zip", | |||
"url": "https://api.github.com/repos/letyii/yii2-tinymce/zipball/861873f30d9e16f76239ae827f2848879f66f78f", | |||
"reference": "861873f30d9e16f76239ae827f2848879f66f78f", | |||
"shasum": "" | |||
}, | |||
"require": { | |||
"php": ">=5.4", | |||
"tinymce/tinymce": ">=4", | |||
"yiisoft/yii2": "*" | |||
}, | |||
"default-branch": true, | |||
"type": "library", | |||
"autoload": { | |||
"psr-4": { | |||
"letyii\\tinymce\\": "" | |||
} | |||
}, | |||
"notification-url": "https://packagist.org/downloads/", | |||
"license": [ | |||
"MIT" | |||
], | |||
"description": "TinyMce for yii2 textarea", | |||
"homepage": "https://github.com/letyii/yii2-tinymce", | |||
"keywords": [ | |||
"tinymce", | |||
"yii2" | |||
], | |||
"support": { | |||
"issues": "https://github.com/letyii/yii2-tinymce/issues", | |||
"source": "https://github.com/letyii/yii2-tinymce/tree/master" | |||
}, | |||
"time": "2015-07-08T08:11:14+00:00" | |||
}, | |||
{ | |||
"name": "linslin/yii2-curl", | |||
"version": "1.5.0", | |||
@@ -2546,6 +2588,65 @@ | |||
], | |||
"time": "2022-11-03T14:55:06+00:00" | |||
}, | |||
{ | |||
"name": "tinymce/tinymce", | |||
"version": "6.7.2", | |||
"source": { | |||
"type": "git", | |||
"url": "https://github.com/tinymce/tinymce-dist.git", | |||
"reference": "a4c139bde17a4e8b2e84d225020cd5acc24a728a" | |||
}, | |||
"dist": { | |||
"type": "zip", | |||
"url": "https://api.github.com/repos/tinymce/tinymce-dist/zipball/a4c139bde17a4e8b2e84d225020cd5acc24a728a", | |||
"reference": "a4c139bde17a4e8b2e84d225020cd5acc24a728a", | |||
"shasum": "" | |||
}, | |||
"type": "component", | |||
"extra": { | |||
"component": { | |||
"scripts": [ | |||
"tinymce.js", | |||
"plugins/*/plugin.js", | |||
"themes/*/theme.js", | |||
"models/*/model.js", | |||
"icons/*/icons.js" | |||
], | |||
"files": [ | |||
"tinymce.min.js", | |||
"plugins/*/plugin.min.js", | |||
"themes/*/theme.min.js", | |||
"models/*/model.min.js", | |||
"skins/**", | |||
"icons/*/icons.min.js" | |||
] | |||
} | |||
}, | |||
"notification-url": "https://packagist.org/downloads/", | |||
"license": [ | |||
"MIT-only" | |||
], | |||
"description": "Web based JavaScript HTML WYSIWYG editor control.", | |||
"homepage": "https://www.tiny.cloud/", | |||
"keywords": [ | |||
"contenteditable", | |||
"editing", | |||
"html", | |||
"javascript", | |||
"rich editor", | |||
"rich text", | |||
"rich text editor", | |||
"richtext", | |||
"rte", | |||
"text", | |||
"tinymce", | |||
"wysiwyg" | |||
], | |||
"support": { | |||
"source": "https://github.com/tinymce/tinymce-dist/tree/6.7.2" | |||
}, | |||
"time": "2023-10-25T06:42:18+00:00" | |||
}, | |||
{ | |||
"name": "twig/twig", | |||
"version": "v3.7.1", | |||
@@ -6669,7 +6770,8 @@ | |||
"stability-flags": { | |||
"kartik-v/yii2-mpdf": 20, | |||
"c006/yii2-paypal-ipn": 20, | |||
"yurkinx/yii2-image": 20 | |||
"yurkinx/yii2-image": 20, | |||
"letyii/yii2-tinymce": 20 | |||
}, | |||
"prefer-stable": false, | |||
"prefer-lowest": false, |
@@ -2,11 +2,12 @@ | |||
namespace console\commands; | |||
use common\logic\Feature\Feature\Module\FeatureModule; | |||
use common\logic\Feature\Feature\FeatureModule; | |||
use yii\console\Controller; | |||
class ImportFeaturesController extends Controller | |||
{ | |||
// ./yii import-features/index | |||
public function actionIndex() | |||
{ | |||
$featureModule = FeatureModule::getInstance(); |
@@ -0,0 +1,18 @@ | |||
<?php | |||
namespace console\commands; | |||
use common\logic\Setting\SettingModule; | |||
use yii\console\Controller; | |||
class SettingController extends Controller | |||
{ | |||
// ./yii setting/import | |||
public function actionImport() | |||
{ | |||
$settingModule = SettingModule::getInstance(); | |||
$settingModule->getImporter()->importFromDefinitions(); | |||
} | |||
} | |||
?> |
@@ -0,0 +1,25 @@ | |||
<?php | |||
use yii\db\Migration; | |||
/** | |||
* Class m231113_073008_add_column_feature_position | |||
*/ | |||
class m231113_073008_add_column_feature_position extends Migration | |||
{ | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeUp() | |||
{ | |||
$this->addColumn('feature', 'position', $this->integer()->notNull()->defaultValue(0)); | |||
} | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeDown() | |||
{ | |||
$this->dropColumn('feature', 'position'); | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
<?php | |||
use yii\db\Migration; | |||
use yii\db\Schema; | |||
/** | |||
* Class m231113_084553_add_column_point_sale_minimum_order_amount | |||
*/ | |||
class m231113_084553_add_column_point_sale_minimum_order_amount extends Migration | |||
{ | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeUp() | |||
{ | |||
$this->addColumn('point_sale', 'minimum_order_amount', Schema::TYPE_FLOAT); | |||
} | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeDown() | |||
{ | |||
$this->dropColumn('point_sale', 'minimum_order_amount'); | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
<?php | |||
use yii\db\Migration; | |||
use yii\db\Schema; | |||
/** | |||
* Class m231113_131131_add_column_producer_export_shopping_cart_labels_format | |||
*/ | |||
class m231113_131131_add_column_producer_export_shopping_cart_labels_format extends Migration | |||
{ | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeUp() | |||
{ | |||
$this->addColumn('producer', 'export_shopping_cart_labels_format', Schema::TYPE_STRING); | |||
} | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeDown() | |||
{ | |||
$this->dropColumn('producer', 'export_shopping_cart_labels_format'); | |||
} | |||
} |
@@ -0,0 +1,37 @@ | |||
<?php | |||
use yii\db\Migration; | |||
use yii\db\Schema; | |||
/** | |||
* Class m231114_085352_create_table_setting | |||
*/ | |||
class m231114_085352_create_table_setting extends Migration | |||
{ | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeUp() | |||
{ | |||
$this->createTable('setting', [ | |||
'id' => 'pk', | |||
'name' => Schema::TYPE_STRING.' NOT NULL', | |||
'id_producer' => Schema::TYPE_INTEGER, | |||
'string' => Schema::TYPE_STRING, | |||
'text' => Schema::TYPE_TEXT, | |||
'date' => Schema::TYPE_DATE, | |||
'integer' => Schema::TYPE_INTEGER, | |||
'float' => Schema::TYPE_FLOAT, | |||
'double' => Schema::TYPE_DOUBLE, | |||
'boolean' => Schema::TYPE_BOOLEAN, | |||
]); | |||
} | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeDown() | |||
{ | |||
$this->dropTable('setting'); | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
<?php | |||
use yii\db\Migration; | |||
use yii\db\Schema; | |||
/** | |||
* Class m231115_083420_add_column_producer_document_image_bottom | |||
*/ | |||
class m231115_083420_add_column_producer_document_image_bottom extends Migration | |||
{ | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeUp() | |||
{ | |||
$this->addColumn('producer', 'document_image_bottom', Schema::TYPE_STRING); | |||
} | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeDown() | |||
{ | |||
$this->dropColumn('producer', 'document_image_bottom'); | |||
} | |||
} |
@@ -138,9 +138,12 @@ class SiteController extends FrontendController | |||
public function actionService() | |||
{ | |||
$paidFeaturesArray = $this->getFeatureModule()->getRepository()->findPaidFeatures(); | |||
return $this->render('service', [ | |||
'producerDemoAccount' => $this->getProducerModule()->findOneProducerDemoAccount(), | |||
'dataProviderPrices' => $this->getDataProviderPrices() | |||
'dataProviderPrices' => $this->getDataProviderPrices(), | |||
'paidFeaturesArray' => $paidFeaturesArray | |||
]); | |||
} | |||
@@ -36,7 +36,9 @@ | |||
* termes. | |||
*/ | |||
use common\helpers\Price; | |||
use yii\grid\GridView; | |||
use yii\helpers\Html; | |||
?> | |||
@@ -89,16 +91,15 @@ GridView::widget([ | |||
</tr> | |||
</thead> | |||
<tbody> | |||
<?php foreach($paidFeaturesArray as $paidFeature): ?> | |||
<tr> | |||
<td> | |||
<strong>Paiement en ligne</strong><br> | |||
<p>Le paiement en ligne permet à vos clients d'alimenter leur crédit (compte prépayé en ligne) par carte bancaire.<br> | |||
Le logiciel fonctionne avec la plateforme <a href="https://stripe.com/fr">Stripe</a> pour accepter les paiements.<br> | |||
<a href="https://stripe.com/fr/pricing">Voir les tarifs Stripe</a> | |||
</p> | |||
<div><strong><?= Html::encode($paidFeature->name) ?></strong></div> | |||
<div><?= $paidFeature->description ?></div> | |||
</td> | |||
<td>120 €</td> | |||
<td><?= Price::format($paidFeature->price, 0) ?></td> | |||
</tr> | |||
<?php endforeach; ?> | |||
</tbody> | |||
</table> | |||
@@ -140,7 +140,10 @@ $this->setIcon('console'); | |||
</h2> | |||
</div> | |||
<div class="panel-body"> | |||
<?= $this->render('_prices_producer', ['dataProviderPrices' => $dataProviderPrices]); ?> | |||
<?= $this->render('_prices_producer', [ | |||
'dataProviderPrices' => $dataProviderPrices, | |||
'paidFeaturesArray' => $paidFeaturesArray | |||
]); ?> | |||
</div> | |||
</div> | |||
@@ -40,6 +40,7 @@ namespace producer\controllers; | |||
use common\helpers\GlobalParam; | |||
use common\helpers\MeanPayment; | |||
use common\logic\Feature\Feature\Feature; | |||
use common\logic\Payment\Model\Payment; | |||
use producer\models\CreditForm; | |||
use yii\filters\VerbFilter; | |||
@@ -108,12 +109,14 @@ class CreditController extends ProducerBaseController | |||
public function actionAdd() | |||
{ | |||
$featureChecker = $this->getFeatureModule()->getChecker(); | |||
$producer = $this->getProducerCurrent(); | |||
if (\Yii::$app->user->isGuest) { | |||
return $this->redirect($this->getUrlManagerFrontend()->createAbsoluteUrl(['site/producer', 'id' => $producer->id])); | |||
} | |||
if ($producer->online_payment || $producer->option_stripe_mode_test) { | |||
if ($featureChecker->isEnabled(Feature::ALIAS_ONLINE_PAYMENT) | |||
&& ($producer->online_payment || $producer->option_stripe_mode_test)) { | |||
$creditForm = new CreditForm; | |||
@@ -132,7 +135,7 @@ class CreditController extends ProducerBaseController | |||
'product_data' => [ | |||
'name' => 'Alimentation crédit', | |||
], | |||
'unit_amount' => (float) $creditForm->amount * 100, | |||
'unit_amount' => (float)$creditForm->amount * 100, | |||
], | |||
'quantity' => 1, | |||
] | |||
@@ -180,153 +183,156 @@ class CreditController extends ProducerBaseController | |||
$paymentManager = $this->getPaymentModule(); | |||
$producerModule = $this->getProducerModule(); | |||
$userModule = $this->getUserModule(); | |||
$producer = $this->getProducerCurrent(); | |||
$contactProducer = $producerModule->getMainContact($producer); | |||
$payload = @file_get_contents('php://input'); | |||
$sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE']; | |||
try { | |||
$event = \Stripe\Webhook::constructEvent( | |||
$payload, | |||
$sig_header, | |||
$producerModule->getPrivateKeyEndpointStripe($producer) | |||
); | |||
} catch (\UnexpectedValueException $e) { | |||
// Invalid payload | |||
http_response_code(400); | |||
exit(); | |||
} catch (\Stripe\Exception\SignatureVerificationException $e) { | |||
// Invalid signature | |||
http_response_code(400); | |||
exit(); | |||
} | |||
$featureChecker = $this->getFeatureModule()->getChecker(); | |||
$paymentIntent = $event->data->object; | |||
$paymentIntentMetadata = $paymentIntent->metadata; | |||
$amount = $paymentIntent->amount / 100; | |||
$idUser = $paymentIntentMetadata->user_id; | |||
if ($featureChecker->isEnabled(Feature::ALIAS_ONLINE_PAYMENT)) { | |||
$producer = $this->getProducerCurrent(); | |||
$contactProducer = $producerModule->getMainContact($producer); | |||
if($idUser) { | |||
$user = $userModule->findOneUserById($idUser); | |||
$payload = @file_get_contents('php://input'); | |||
$sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE']; | |||
if (isset($paymentIntentMetadata->order_id)) { | |||
$order = $this->getOrderModule()->findOneOrderById($paymentIntentMetadata->order_id); | |||
$orderModule->initOrder($order); | |||
$pointSale = $this->getPointSaleModule()->findOnePointSaleById($order->id_point_sale); | |||
$distribution = $this-> getDistributionModule()->findOneDistributionById($order->id_distribution); | |||
try { | |||
$event = \Stripe\Webhook::constructEvent( | |||
$payload, | |||
$sig_header, | |||
$producerModule->getPrivateKeyEndpointStripe($producer) | |||
); | |||
} catch (\UnexpectedValueException $e) { | |||
// Invalid payload | |||
http_response_code(400); | |||
exit(); | |||
} catch (\Stripe\Exception\SignatureVerificationException $e) { | |||
// Invalid signature | |||
http_response_code(400); | |||
exit(); | |||
} | |||
// Handle the event | |||
switch ($event->type) { | |||
case 'charge.succeeded': | |||
$paymentIntent = $event->data->object; | |||
$paymentIntentMetadata = $paymentIntent->metadata; | |||
$amount = $paymentIntent->amount / 100; | |||
$idUser = $paymentIntentMetadata->user_id; | |||
$paymentExist = Payment::searchOne([ | |||
'id_user' => $idUser, | |||
'amount' => $amount, | |||
], [ | |||
'conditions' => [ | |||
'date > DATE_SUB(NOW(), INTERVAL 1 MINUTE)' | |||
] | |||
]); | |||
if ($idUser) { | |||
$user = $userModule->findOneUserById($idUser); | |||
if (!$paymentExist) { | |||
if (isset($paymentIntentMetadata->order_id)) { | |||
$order = $this->getOrderModule()->findOneOrderById($paymentIntentMetadata->order_id); | |||
$orderModule->initOrder($order); | |||
$pointSale = $this->getPointSaleModule()->findOnePointSaleById($order->id_point_sale); | |||
$distribution = $this->getDistributionModule()->findOneDistributionById($order->id_distribution); | |||
} | |||
$paymentManager->creditUser($user, $amount, MeanPayment::CREDIT_CARD, $user); | |||
// Handle the event | |||
switch ($event->type) { | |||
case 'charge.succeeded': | |||
if (isset($order) && $order) { | |||
$paymentExist = Payment::searchOne([ | |||
'id_user' => $idUser, | |||
'amount' => $amount, | |||
], [ | |||
'conditions' => [ | |||
'date > DATE_SUB(NOW(), INTERVAL 1 MINUTE)' | |||
] | |||
]); | |||
if (!$paymentExist) { | |||
$paymentManager->creditUser($user, $amount, MeanPayment::CREDIT_CARD, $user); | |||
if (isset($order) && $order) { | |||
$paymentManager->payOrder($order, MeanPayment::CREDIT_CARD, $user, true); | |||
// client : envoi d'un email de confirmation de paiement | |||
/*\Yii::$app->mailerService->sendFromProducer( | |||
'Confirmation de commande', | |||
'paymentOrderConfirm', | |||
[ | |||
'amount' => $amount, | |||
'user' => $user, | |||
'producer' => $producer, | |||
], | |||
$user->email, | |||
$producer | |||
);*/ | |||
// producteur : mail de confirmation | |||
\Yii::$app->mailerService->sendFromSite( | |||
'Confirmation de commande', | |||
'orderConfirmProducer', | |||
[ | |||
'order' => $order, | |||
'pointSale' => $pointSale, | |||
'distribution' => $distribution, | |||
'user' => $user, | |||
'producer' => $producer | |||
], | |||
$contactProducer->email | |||
); | |||
} else { | |||
$userProducer = $this->getUserProducerModule()->findOneUserProducer($user); | |||
\Yii::$app->mailerService->sendFromProducer( | |||
'Alimentation de votre crédit', | |||
'creditConfirm', | |||
[ | |||
'user' => $user, | |||
'userProducer' => $userProducer, | |||
'producer' => $producer, | |||
'amount' => $amount, | |||
], | |||
$user->email, | |||
$producer | |||
); | |||
} | |||
} | |||
$paymentManager->payOrder($order, MeanPayment::CREDIT_CARD, $user, true); | |||
break; | |||
case 'charge.failed': | |||
// client : envoi d'un email de confirmation de paiement | |||
/*\Yii::$app->mailerService->sendFromProducer( | |||
'Confirmation de commande', | |||
'paymentOrderConfirm', | |||
[ | |||
'amount' => $amount, | |||
'user' => $user, | |||
'producer' => $producer, | |||
], | |||
$user->email, | |||
$producer | |||
);*/ | |||
// client | |||
\Yii::$app->mailerService->sendFromProducer( | |||
'Erreur de paiement', | |||
'paymentError', | |||
[ | |||
'amount' => $amount, | |||
'user' => $user, | |||
'producer' => $producer, | |||
], | |||
$user->email, | |||
$producer | |||
); | |||
// producteur : mail de confirmation | |||
// producteur | |||
if (isset($order) && $order) { | |||
\Yii::$app->mailerService->sendFromSite( | |||
'Confirmation de commande', | |||
'orderConfirmProducer', | |||
[ | |||
'order' => $order, | |||
'pointSale' => $pointSale, | |||
'distribution' => $distribution, | |||
'user' => $user, | |||
'producer' => $producer | |||
], | |||
$contactProducer->email | |||
); | |||
} else { | |||
$userProducer = $this->getUserProducerModule()->findOneUserProducer($user); | |||
\Yii::$app->mailerService->sendFromProducer( | |||
'Alimentation de votre crédit', | |||
'creditConfirm', | |||
'Erreur de paiement', | |||
'paymentErrorProducer', | |||
[ | |||
'amount' => $amount, | |||
'user' => $user, | |||
'userProducer' => $userProducer, | |||
'producer' => $producer, | |||
'amount' => $amount, | |||
'order' => $order, | |||
'distribution' => $distribution | |||
], | |||
$user->email, | |||
$producer | |||
$contactProducer->email, | |||
); | |||
} | |||
} | |||
break; | |||
case 'charge.failed': | |||
// client | |||
\Yii::$app->mailerService->sendFromProducer( | |||
'Erreur de paiement', | |||
'paymentError', | |||
[ | |||
'amount' => $amount, | |||
'user' => $user, | |||
'producer' => $producer, | |||
], | |||
$user->email, | |||
$producer | |||
); | |||
// producteur | |||
if (isset($order) && $order) { | |||
\Yii::$app->mailerService->sendFromSite( | |||
'Erreur de paiement', | |||
'paymentErrorProducer', | |||
[ | |||
'amount' => $amount, | |||
'user' => $user, | |||
'producer' => $producer, | |||
'order' => $order, | |||
'distribution' => $distribution | |||
], | |||
$contactProducer->email, | |||
); | |||
} | |||
break; | |||
break; | |||
// handle other event types | |||
default: | |||
echo 'Received unknown event type ' . $event->type; | |||
} | |||
// handle other event types | |||
default: | |||
echo 'Received unknown event type ' . $event->type; | |||
http_response_code(200); | |||
} else { | |||
http_response_code(200); | |||
} | |||
http_response_code(200); | |||
} | |||
else { | |||
http_response_code(200); | |||
} | |||
die(); |
@@ -50,7 +50,6 @@ use common\logic\Order\ProductOrder\Model\ProductOrder; | |||
use common\logic\PointSale\PointSale\Model\PointSale; | |||
use common\logic\Producer\Producer\Model\Producer; | |||
use common\logic\Product\Product\Model\Product; | |||
use common\logic\User\CreditHistory\Model\CreditHistory; | |||
use common\logic\User\User\Model\User; | |||
use DateTime; | |||
use yii\base\UserException; | |||
@@ -476,44 +475,42 @@ class OrderController extends ProducerBaseController | |||
/* | |||
* Envoi email de confirmation | |||
*/ | |||
if ($isNewOrder) { | |||
$emailSubject = 'Confirmation de commande'; | |||
$emailContentParams = [ | |||
'order' => $order, | |||
'pointSale' => $pointSale, | |||
'distribution' => $distribution, | |||
'user' => $user, | |||
'producer' => $producer | |||
]; | |||
// au client | |||
if ($producerModule->getConfig('option_email_confirm')) { | |||
\Yii::$app->mailerService->sendFromProducer( | |||
$emailSubject, | |||
'orderConfirm', | |||
$emailContentParams, | |||
$user->email, | |||
$producer | |||
); | |||
$emailSubject = 'Confirmation de commande'; | |||
$emailContentParams = [ | |||
'order' => $order, | |||
'pointSale' => $pointSale, | |||
'distribution' => $distribution, | |||
'user' => $user, | |||
'producer' => $producer | |||
]; | |||
} | |||
// au client | |||
if ($producerModule->getConfig('option_email_confirm')) { | |||
\Yii::$app->mailerService->sendFromProducer( | |||
$emailSubject, | |||
'orderConfirm', | |||
$emailContentParams, | |||
$user->email, | |||
$producer | |||
); | |||
// au producteur | |||
$contactProducer = $producerModule->getMainContact($producer); | |||
if ($producerModule->getConfig('option_email_confirm_producer') && $contactProducer && strlen( | |||
$contactProducer->email | |||
)) { | |||
\Yii::$app->mailerService->sendFromSite( | |||
$emailSubject, | |||
'orderConfirmProducer', | |||
$emailContentParams, | |||
$contactProducer->email | |||
); | |||
} | |||
} | |||
// au producteur | |||
$contactProducer = $producerModule->getMainContact($producer); | |||
if ($producerModule->getConfig('option_email_confirm_producer') && $contactProducer && strlen( | |||
$contactProducer->email | |||
)) { | |||
\Yii::$app->mailerService->sendFromSite( | |||
$emailSubject, | |||
'orderConfirmProducer', | |||
$emailContentParams, | |||
$contactProducer->email | |||
); | |||
} | |||
$order = $orderModule->findOneOrderById($order->id); | |||
$orderModule->initOrder($order); | |||
$orderModule->updateOrderTillerSynchronization($order); | |||
@@ -935,6 +932,7 @@ class OrderController extends ProducerBaseController | |||
$product['photo'] = ''; | |||
} | |||
else { | |||
$product['photo_big'] = Image::getThumbnailBig($product['photo']); | |||
$product['photo'] = Image::getThumbnailSmall($product['photo']); | |||
} | |||
@@ -40,7 +40,7 @@ namespace producer\controllers; | |||
use common\forms\ContactForm; | |||
use common\helpers\GlobalParam; | |||
use common\logic\Feature\Feature\Model\Feature; | |||
use common\logic\Feature\Feature\Feature; | |||
use common\logic\Product\Product\Model\Product; | |||
use yii\data\ActiveDataProvider; | |||
use yii\helpers\Html; | |||
@@ -180,7 +180,7 @@ class SiteController extends ProducerBaseController | |||
public function actionContact() | |||
{ | |||
$featureModule = $this->getFeatureModule(); | |||
if($featureModule->getManager()->isDisabled(Feature::ALIAS_CONTACT)) { | |||
if($featureModule->getChecker()->isDisabled(Feature::ALIAS_CONTACT)) { | |||
return $this->redirect(['site/index']); | |||
} | |||
@@ -36,15 +36,18 @@ | |||
* termes. | |||
*/ | |||
use common\logic\Feature\Feature\Feature; | |||
use common\logic\Feature\Feature\FeatureModule; | |||
use common\logic\Payment\Module\PaymentModule; | |||
use yii\grid\GridView; | |||
$paymentManager = PaymentModule::getInstance(); | |||
$featureChecker = FeatureModule::getInstance()->getChecker(); | |||
$producer = $this->context->getProducerCurrent(); | |||
$this->setTitle('Crédit : <span id="credit-user">' . number_format($creditUser, 2) . ' €</span>'); | |||
$this->setPageTitle('Crédit'); | |||
if ($this->context->getProducerCurrent()->online_payment) { | |||
if ($featureChecker->isEnabled(Feature::ALIAS_ONLINE_PAYMENT) && $this->context->getProducerCurrent()->online_payment) { | |||
$this->addButton( | |||
[ | |||
'label' => '<span class="glyphicon glyphicon-credit-card"></span> Créditer mon compte', |
@@ -36,8 +36,8 @@ | |||
* termes. | |||
*/ | |||
use common\logic\Feature\Feature\Model\Feature; | |||
use common\logic\Feature\Feature\Module\FeatureModule; | |||
use common\logic\Feature\Feature\Feature; | |||
use common\logic\Feature\Feature\FeatureModule; | |||
use common\logic\Order\Order\Model\Order; | |||
use common\logic\Producer\Producer\Module\ProducerModule; | |||
use common\logic\User\User\Module\UserModule; | |||
@@ -181,7 +181,7 @@ if (!Yii::$app->user->isGuest) { | |||
'label' => '<span class="glyphicon glyphicon-envelope"></span> Contact', | |||
'url' => $this->getUrlManagerProducer()->createUrl(['site/contact']), | |||
'active' => $this->getControllerAction() == 'site/contact', | |||
'visible' => $featureModule->getManager()->isEnabled(Feature::ALIAS_CONTACT) | |||
'visible' => $featureModule->getChecker()->isEnabled(Feature::ALIAS_CONTACT) | |||
], | |||
], | |||
]); |
@@ -112,7 +112,7 @@ $this->setTitle('Commander'); | |||
></step-date> | |||
<?php endif; ?> | |||
<li id="step-products" :class="'col-md-3 '+((step == 'products') ? 'active ' : '')"> | |||
<li id="step-products" :class="'col-md-4 '+((step == 'products') ? 'active ' : '')"> | |||
<button @click="changeStep('products')" | |||
:class="'btn '+ (step == 'products' ? 'btn-primary' : 'btn-default')" | |||
:disabled="step == 'date' || step == 'point-sale'"> | |||
@@ -123,14 +123,14 @@ $this->setTitle('Commander'); | |||
{{ countProductOrdered() }} produit{{ (countProductOrdered() > 1) ? 's' : '' }} | |||
</div> | |||
</li> | |||
<li id="step-payment" :class="'col-md-3 '+((step == 'payment') ? 'active' : '')"> | |||
<!--<li id="step-payment" :class="'col-md-3 '+((step == 'payment') ? 'active' : '')"> | |||
<button @click="changeStep('payment')" | |||
:class="'btn '+ (step == 'payment' ? 'btn-primary' : 'btn-default')" | |||
:disabled="step == 'date' || step == 'point-sale' || step == 'products'"> | |||
<span class="button-content"><span | |||
class="glyphicon glyphicon-ok"></span> Confirmation</span> | |||
</button> | |||
</li> | |||
</li>--> | |||
</ul> | |||
<div class="clr"></div> | |||
</div> | |||
@@ -240,6 +240,9 @@ $this->setTitle('Commander'); | |||
</div> | |||
<div class="comment" v-if="pointSale.infos && pointSale.infos.length > 0" | |||
v-html="pointSale.infos"></div> | |||
<div class="minimum-order-amount" v-if="pointSale.minimum_order_amount"> | |||
Montant minimum de commande : {{ formatPrice(pointSale.minimum_order_amount) }} | |||
</div> | |||
</td> | |||
<td class="locality">{{ pointSale.locality }}</td> | |||
<td class="actions"> | |||
@@ -325,8 +328,9 @@ $this->setTitle('Commander'); | |||
<tr v-for="product in products" | |||
v-if="product.id_product_category == category.id && product.productDistribution && product.productDistribution[0] && product.productDistribution[0].active == 1"> | |||
<td class="photo"> | |||
<img v-if="product.photo.length" class="photo-product" | |||
:src="product.photo"/> | |||
<a class="product-photo" :href="product.photo_big" :title="product.name"> | |||
<img v-if="product.photo.length" class="photo-product" :src="product.photo"/> | |||
</a> | |||
</td> | |||
<td class="name product-name-description-block"> | |||
<span class="name">{{ product.name }}</span> | |||
@@ -425,137 +429,132 @@ $this->setTitle('Commander'); | |||
</tr> | |||
</tbody> | |||
</table> | |||
<div class="block-actions"> | |||
<button class="btn btn-primary" @click="changeStep('payment')">Valider</button> | |||
</div> | |||
</div> | |||
<div class="alert alert-warning" v-else> | |||
Aucun produit disponible | |||
</div> | |||
</div> | |||
</div> | |||
</transition> | |||
<transition name="slide"> | |||
<div id="content-step-payment" v-if="step == 'payment'"> | |||
<div> | |||
<div class="delivery"> | |||
<div class="delivery-home" v-if="pointSaleActive.is_home_delivery"> | |||
<label for="deliver-address">Adresse de livraison</label> | |||
<textarea id="deliver-address" v-model="deliveryAddress" class="form-control" | |||
required="required"></textarea> | |||
</div> | |||
</div> | |||
<div class="comment"> | |||
<label for="order-comment">Commentaire</label> | |||
<textarea id="order-comment" v-model="comment" class="form-control"></textarea> | |||
</div> | |||
<div id="content-step-payment"> | |||
<div> | |||
<div class="delivery"> | |||
<div class="delivery-home" v-if="pointSaleActive.is_home_delivery"> | |||
<label for="deliver-address">Adresse de livraison</label> | |||
<textarea id="deliver-address" v-model="deliveryAddress" class="form-control" | |||
required="required"></textarea> | |||
</div> | |||
</div> | |||
<template | |||
v-if="producer.credit == 1 && pointSaleActive.credit == 1 && (pointSaleActive.credit_functioning == 'mandatory' || (pointSaleActive.credit_functioning == 'user' && user.credit_active)) && !checkCreditLimit(order) "> | |||
<div class="alert alert-danger"> | |||
Vous devez | |||
<template v-if="producer.online_payment == 1"><a | |||
href="<?= \Yii::$app->urlManager->createUrl(['credit/add']) ?>">recharger | |||
votre crédit</a></template> | |||
<template v-else>recharger votre crédit</template> | |||
auprès de votre producteur ou supprimer des produits.</span> | |||
Votre producteur n'autorise pas un crédit inférieur | |||
à <strong>{{ formatPrice(producer.credit_limit) }}</strong>. | |||
</div> | |||
<div class="block-actions"> | |||
<a class="btn btn-primary" | |||
href="<?= \Yii::$app->urlManager->createUrl(['site/index']) ?>">Retour à | |||
l'accueil</a> | |||
</div> | |||
</template> | |||
<template v-else> | |||
<div class="credit"> | |||
<div v-if="user && producer.credit == 1 && pointSaleActive.credit == 1 && (pointSaleActive.credit_functioning != 'user' || (pointSaleActive.credit_functioning == 'user' && user.credit_active))"> | |||
<input type="checkbox" id="use-credit" v-model="useCredit" disabled="disabled" | |||
v-if="pointSaleActive.credit_functioning == 'mandatory' || (pointSaleActive.credit_functioning == 'user' && user.credit_active)"/> | |||
<input type="checkbox" id="use-credit" v-model="useCredit" v-else/> <label | |||
for="use-credit">Utiliser mon Crédit ({{ formatPrice(user.credit) | |||
}})</label> | |||
<div class="comment"> | |||
<label for="order-comment">Commentaire</label> | |||
<textarea id="order-comment" v-model="comment" class="form-control"></textarea> | |||
</div> | |||
<template | |||
v-if="producer.credit == 1 && pointSaleActive.credit == 1 && (pointSaleActive.credit_functioning == 'mandatory' || (pointSaleActive.credit_functioning == 'user' && user.credit_active)) && !checkCreditLimit(order) "> | |||
<div class="alert alert-danger"> | |||
Vous devez | |||
<template v-if="producer.online_payment == 1"><a | |||
href="<?= \Yii::$app->urlManager->createUrl(['credit/add']) ?>">recharger | |||
votre crédit</a></template> | |||
<template v-else>recharger votre crédit</template> | |||
auprès de votre producteur ou supprimer des produits.</span> | |||
Votre producteur n'autorise pas un crédit inférieur | |||
à <strong>{{ formatPrice(producer.credit_limit) }}</strong>. | |||
</div> | |||
<div class="block-actions"> | |||
<a class="btn btn-primary" | |||
href="<?= \Yii::$app->urlManager->createUrl(['site/index']) ?>">Retour à | |||
l'accueil</a> | |||
</div> | |||
</template> | |||
<template v-else> | |||
<div class="credit"> | |||
<div v-if="user && producer.credit == 1 && pointSaleActive.credit == 1 && (pointSaleActive.credit_functioning != 'user' || (pointSaleActive.credit_functioning == 'user' && user.credit_active))"> | |||
<input type="checkbox" id="use-credit" v-model="useCredit" disabled="disabled" | |||
v-if="pointSaleActive.credit_functioning == 'mandatory' || (pointSaleActive.credit_functioning == 'user' && user.credit_active)"/> | |||
<input type="checkbox" id="use-credit" v-model="useCredit" v-else/> <label | |||
for="use-credit">Utiliser mon Crédit ({{ formatPrice(user.credit) | |||
}})</label> | |||
<div class="info" v-if="useCredit"> | |||
<template v-if="order == null || order.amount_paid == 0"> | |||
<span v-if="checkCreditLimit(order)">{{ priceTotal(true) }} seront débités</span> | |||
<span v-else> | |||
<div class="info" v-if="useCredit"> | |||
<template v-if="order == null || order.amount_paid == 0"> | |||
<span v-if="checkCreditLimit(order)">{{ priceTotal(true) }} seront débités</span> | |||
<span v-else> | |||
{{ formatPrice(user.credit) }} seront débités. (Limite de crédit à {{ formatPrice(producer.credit_limit) }})<br/> | |||
Restera {{ formatPrice(priceTotal() - user.credit) }} à régler. | |||
</span> | |||
</template> | |||
<template | |||
v-else-if="order != null && order.amount_paid > 0 && order.amount_paid < priceTotal()"> | |||
<span v-if="checkCreditLimit(order)">{{ formatPrice(priceTotal() - order.amount_paid) }} seront débités</span> | |||
<span v-else> | |||
</template> | |||
<template | |||
v-else-if="order != null && order.amount_paid > 0 && order.amount_paid < priceTotal()"> | |||
<span v-if="checkCreditLimit(order)">{{ formatPrice(priceTotal() - order.amount_paid) }} seront débités</span> | |||
<span v-else> | |||
{{ formatPrice(user.credit) }} seront débités. (Limite de crédit à {{ formatPrice(producer.credit_limit) }})<br/> | |||
Restera {{ formatPrice(priceTotal() - order.amount_paid - user.credit) }} à régler. | |||
</span> | |||
</template> | |||
<template v-else-if="order != null && order.amount_paid > priceTotal()"> | |||
<span>{{ formatPrice(order.amount_paid - priceTotal()) }} seront remboursés</span> | |||
</template> | |||
</div> | |||
</div> | |||
<div v-else> | |||
<span class="glyphicon glyphicon-chevron-right"></span> | |||
<?php if ($producerModule->isOnlinePaymentActiveAndTypeOrder($producer)): ?> | |||
La commande est à payer en ligne lors de l'étape suivante. | |||
<?php elseif ($producer->option_payment_info && strlen($producer->option_payment_info) > 0): ?> | |||
Confirmez votre commande et retrouvez les informations liées au paiement sur la page suivante. | |||
<?php else: ?> | |||
La commande sera à régler sur place. | |||
<?php endif; ?> | |||
</template> | |||
<template v-else-if="order != null && order.amount_paid > priceTotal()"> | |||
<span>{{ formatPrice(order.amount_paid - priceTotal()) }} seront remboursés</span> | |||
</template> | |||
</div> | |||
</div> | |||
<div v-else> | |||
<span class="glyphicon glyphicon-chevron-right"></span> | |||
<?php if ($producerModule->isOnlinePaymentActiveAndTypeOrder($producer)): ?> | |||
La commande est à payer en ligne lors de l'étape suivante. | |||
<?php elseif ($producer->option_payment_info && strlen($producer->option_payment_info) > 0): ?> | |||
Confirmez votre commande et retrouvez les informations liées au paiement sur la page suivante. | |||
<?php else: ?> | |||
La commande sera à régler sur place. | |||
<?php endif; ?> | |||
</div> | |||
</div> | |||
<div id="signup-guest" v-if="!user && producer.option_allow_order_guest"> | |||
<h3>Informations personnelles</h3> | |||
<form action="#"> | |||
<div class="form-group field-signupguest-email required"> | |||
<label class="control-label" for="signupguest-email">Email</label> | |||
<input type="email" id="signupguest-email" class="form-control" | |||
name="SignupForm[email]"> | |||
<p class="help-block help-block-error"></p> | |||
</div> | |||
<div class="form-group field-signupguest-firstname required"> | |||
<label class="control-label" for="signupguest-firstname">Prénom</label> | |||
<input type="text" id="signupguest-firstname" class="form-control" | |||
name="SignupForm[firstname]"> | |||
<p class="help-block help-block-error"></p> | |||
</div> | |||
<div class="form-group field-signupguest-lastname required"> | |||
<label class="control-label" for="signupguest-lastname">Nom</label> | |||
<input type="text" id="signupguest-lastname" class="form-control" | |||
name="SignupForm[lastname]"> | |||
<p class="help-block help-block-error"></p> | |||
</div> | |||
<div class="form-group field-signupguest-phone required"> | |||
<label class="control-label" for="signupguest-phone">Téléphone</label> | |||
<input type="text" id="signupguest-phone" class="form-control" | |||
name="SignupForm[phone]"> | |||
<p class="help-block help-block-error"></p> | |||
</div> | |||
</form> | |||
</div> | |||
<div class="block-actions"> | |||
<button class="btn btn-primary" disabled="disabled" v-if="disableConfirmButton || !oneProductOrdered()">Je | |||
confirme ma commande | |||
</button> | |||
<button class="btn btn-primary" v-else @click="confirmClick">Je confirme ma | |||
commande | |||
</button> | |||
</div> | |||
</template> | |||
</div> | |||
</div> | |||
<div id="signup-guest" v-if="!user && producer.option_allow_order_guest"> | |||
<h3>Informations personnelles</h3> | |||
<form action="#"> | |||
<div class="form-group field-signupguest-email required"> | |||
<label class="control-label" for="signupguest-email">Email</label> | |||
<input type="email" id="signupguest-email" class="form-control" | |||
name="SignupForm[email]"> | |||
<p class="help-block help-block-error"></p> | |||
</div> | |||
<!--<div class="form-group field-signupguest-password required"> | |||
<label class="control-label" for="signupguest-password">Mot de passe</label> | |||
<input type="password" id="signupguest-password" class="form-control" name="SignupForm[password]"> | |||
<p class="help-block help-block-error"></p> | |||
</div>--> | |||
<div class="form-group field-signupguest-firstname required"> | |||
<label class="control-label" for="signupguest-firstname">Prénom</label> | |||
<input type="text" id="signupguest-firstname" class="form-control" | |||
name="SignupForm[firstname]"> | |||
<p class="help-block help-block-error"></p> | |||
</div> | |||
<div class="form-group field-signupguest-lastname required"> | |||
<label class="control-label" for="signupguest-lastname">Nom</label> | |||
<input type="text" id="signupguest-lastname" class="form-control" | |||
name="SignupForm[lastname]"> | |||
<p class="help-block help-block-error"></p> | |||
</div> | |||
<div class="form-group field-signupguest-phone required"> | |||
<label class="control-label" for="signupguest-phone">Téléphone</label> | |||
<input type="text" id="signupguest-phone" class="form-control" | |||
name="SignupForm[phone]"> | |||
<p class="help-block help-block-error"></p> | |||
</div> | |||
</form> | |||
</div> | |||
<div class="block-actions"> | |||
<button class="btn btn-primary" disabled="disabled" v-if="disableConfirmButton">Je | |||
confirme ma commande | |||
</button> | |||
<button class="btn btn-primary" v-else @click="confirmClick">Je confirme ma | |||
commande | |||
</button> | |||
</div> | |||
</template> | |||
</div> | |||
<div class="alert alert-warning" v-else> | |||
Aucun produit disponible | |||
</div> | |||
</div> | |||
</div> | |||
</transition> | |||
<transition name="slide"> | |||
</transition> | |||
</div> | |||
</div> | |||
@@ -647,7 +646,7 @@ $this->setTitle('Commander'); | |||
</div> | |||
<script type="text/x-template" id="template-step-date"> | |||
<li id="step-date" :class="'col-md-3'+((step == 'date') ? ' active' : '')+(first ? ' first' : '')"> | |||
<li id="step-date" :class="'col-md-4'+((step == 'date') ? ' active' : '')+(first ? ' first' : '')"> | |||
<button @click="changeStep('date')" :class="'btn '+ (step == 'date' ? 'btn-primary' : 'btn-default')" | |||
:disabled="producer && producer.option_order_entry_point == 'point-sale' && !pointSaleActive"> | |||
<span class="button-content"><span class="glyphicon glyphicon-time"></span> Date</span></span> | |||
@@ -659,7 +658,7 @@ $this->setTitle('Commander'); | |||
</script> | |||
<script type="text/x-template" id="template-step-point-sale"> | |||
<li id="step-point-sale" :class="'col-md-3'+((step == 'point-sale') ? ' active ' : '')+(first ? ' first' : '')"> | |||
<li id="step-point-sale" :class="'col-md-4'+((step == 'point-sale') ? ' active ' : '')+(first ? ' first' : '')"> | |||
<button @click="changeStep('point-sale')" | |||
:class="'btn '+ (step == 'point-sale' ? 'btn-primary' : 'btn-default')" | |||
:disabled="producer && (producer.option_order_entry_point == 'date' && step == 'date')"> |
@@ -157,7 +157,7 @@ $this->setPageTitle(Html::encode($producer->type . ' à ' . $producer->city)); | |||
'contentOptions' => ['class' => 'photo'], | |||
'value' => function ($model) { | |||
if (strlen($model->photo)) { | |||
return '<img class="photo-product" src="'. Image::getThumbnailSmall($model->photo).'" />'; | |||
return '<a class="product-photo" href="'.Image::getThumbnailBig($model->photo).'" title="'.Html::encode($model->name).'"><img class="photo-product" src="'. Image::getThumbnailSmall($model->photo).'" />'; | |||
} | |||
return ''; | |||
} |
@@ -1347,7 +1347,7 @@ termes. | |||
padding-right: 0px; | |||
} | |||
/* line 72, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order #steps ul li#step-payment .btn::after, .order-order #main #app-order-order #steps ul li.first .btn::before { | |||
.order-order #main #app-order-order #steps ul li#step-products .btn::after, .order-order #main #app-order-order #steps ul li.first .btn::before { | |||
display: none; | |||
} | |||
/* line 77, ../sass/order/_order.scss */ | |||
@@ -1471,26 +1471,28 @@ termes. | |||
font-weight: bold; | |||
} | |||
/* line 222, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#points-sale td.name .comment { | |||
.order-order #main #app-order-order table#points-sale td.name .comment, | |||
.order-order #main #app-order-order table#points-sale td.name .minimum-order-amount { | |||
color: gray; | |||
} | |||
/* line 225, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#points-sale td.name .comment a { | |||
/* line 226, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#points-sale td.name .comment a, | |||
.order-order #main #app-order-order table#points-sale td.name .minimum-order-amount a { | |||
color: #F39C12; | |||
} | |||
/* line 231, ../sass/order/_order.scss */ | |||
/* line 232, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#points-sale td.actions { | |||
width: 150px; | |||
} | |||
/* line 233, ../sass/order/_order.scss */ | |||
/* line 234, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#points-sale td.actions button { | |||
width: 100%; | |||
} | |||
/* line 239, ../sass/order/_order.scss */ | |||
/* line 240, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#points-sale tr.selected td { | |||
background-color: white; | |||
} | |||
/* line 247, ../sass/order/_order.scss */ | |||
/* line 248, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products td.category-name { | |||
font-family: "highvoltageregular"; | |||
font-size: 22px; | |||
@@ -1498,12 +1500,12 @@ termes. | |||
text-transform: uppercase; | |||
padding-top: 13px; | |||
} | |||
/* line 254, ../sass/order/_order.scss */ | |||
/* line 255, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products td.category-name .glyphicon-triangle-bottom, | |||
.order-order #main #app-order-order table#products td.category-name .glyphicon-triangle-right { | |||
font-size: 15px; | |||
} | |||
/* line 259, ../sass/order/_order.scss */ | |||
/* line 260, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products td.category-name span.label { | |||
font-family: "Arial"; | |||
font-weight: normal; | |||
@@ -1511,17 +1513,17 @@ termes. | |||
text-transform: none; | |||
margin-left: 15px; | |||
} | |||
/* line 268, ../sass/order/_order.scss */ | |||
/* line 269, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products td.category-name:hover { | |||
cursor: pointer; | |||
background-color: #F39C12; | |||
color: white; | |||
} | |||
/* line 276, ../sass/order/_order.scss */ | |||
/* line 277, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products td.photo img { | |||
width: 100px; | |||
} | |||
/* line 286, ../sass/order/_order.scss */ | |||
/* line 287, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products .price-unit .decreasing-prices { | |||
margin-top: 10px; | |||
font-size: 10px; | |||
@@ -1529,34 +1531,34 @@ termes. | |||
padding-bottom: 2px; | |||
margin-bottom: 0px; | |||
} | |||
/* line 294, ../sass/order/_order.scss */ | |||
/* line 295, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products .price-unit .decreasing-prices ul li { | |||
margin-bottom: 5px; | |||
} | |||
/* line 296, ../sass/order/_order.scss */ | |||
/* line 297, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products .price-unit .decreasing-prices ul li strong { | |||
font-weight: bold; | |||
} | |||
/* line 304, ../sass/order/_order.scss */ | |||
/* line 305, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products .price-unit, .order-order #main #app-order-order table#products .price-total { | |||
width: 135px; | |||
text-align: center; | |||
} | |||
/* line 308, ../sass/order/_order.scss */ | |||
/* line 309, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products .price-unit .unit, .order-order #main #app-order-order table#products .price-total .unit { | |||
color: gray; | |||
font-size: 13px; | |||
} | |||
/* line 313, ../sass/order/_order.scss */ | |||
/* line 314, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products .td-quantity { | |||
width: 175px; | |||
} | |||
/* line 315, ../sass/order/_order.scss */ | |||
/* line 316, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products .td-quantity input.quantity { | |||
text-align: center; | |||
border-right: 0px none; | |||
} | |||
/* line 319, ../sass/order/_order.scss */ | |||
/* line 320, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products .td-quantity .input-group-addon { | |||
padding: 5px; | |||
padding-left: 0px; | |||
@@ -1564,69 +1566,69 @@ termes. | |||
border-left: 0px none; | |||
border-right: 0px none; | |||
} | |||
/* line 330, ../sass/order/_order.scss */ | |||
/* line 331, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products tr.total .summary h3 { | |||
margin-top: 0px; | |||
font-family: "capsuularegular"; | |||
text-transform: none; | |||
margin-bottom: 5px; | |||
} | |||
/* line 337, ../sass/order/_order.scss */ | |||
/* line 338, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products tr.total .summary ul { | |||
margin-bottom: 15px; | |||
padding-left: 20px; | |||
font-size: 23px; | |||
} | |||
/* line 344, ../sass/order/_order.scss */ | |||
/* line 345, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products tr.total .summary ul li .quantity { | |||
font-size: 18px; | |||
} | |||
/* line 348, ../sass/order/_order.scss */ | |||
/* line 349, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products tr.total .summary ul li .name { | |||
font-family: "capsuularegular"; | |||
font-size: 24px; | |||
} | |||
/* line 352, ../sass/order/_order.scss */ | |||
/* line 353, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products tr.total .summary ul li .other { | |||
font-family: "capsuularegular"; | |||
font-size: 18px; | |||
} | |||
/* line 360, ../sass/order/_order.scss */ | |||
/* line 361, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products tr.total .price-total { | |||
font-size: 23px; | |||
} | |||
/* line 368, ../sass/order/_order.scss */ | |||
/* line 369, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order #content-step-payment .delivery { | |||
margin-bottom: 20px; | |||
} | |||
/* line 371, ../sass/order/_order.scss */ | |||
/* line 372, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order #content-step-payment .delivery .delivery-home { | |||
margin-bottom: 20px; | |||
} | |||
/* line 380, ../sass/order/_order.scss */ | |||
/* line 381, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order #content-step-payment .comment { | |||
margin-bottom: 20px; | |||
} | |||
/* line 385, ../sass/order/_order.scss */ | |||
/* line 386, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order #content-step-payment .credit .info { | |||
margin-left: 20px; | |||
color: gray; | |||
} | |||
/* line 392, ../sass/order/_order.scss */ | |||
/* line 393, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order #specific-delays { | |||
margin-top: 15px; | |||
} | |||
/* line 400, ../sass/order/_order.scss */ | |||
/* line 401, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order #infos { | |||
margin-top: 30px; | |||
} | |||
/* line 402, ../sass/order/_order.scss */ | |||
/* line 403, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order #infos .panel-body { | |||
padding-top: 0px; | |||
white-space: pre-line; | |||
} | |||
/* line 412, ../sass/order/_order.scss */ | |||
/* line 413, ../sass/order/_order.scss */ | |||
#main #content .panel h3 { | |||
font-family: "highvoltageregular"; | |||
margin: 0px; |
@@ -85,6 +85,8 @@ function opendistrib_products() { | |||
$(this).hide(); | |||
$(this).parent().find('.content').show(); | |||
}); | |||
$('a.product-photo').simpleLightbox(); | |||
} | |||
function opendistrib_datepicker() { | |||
@@ -101,11 +103,11 @@ function opendistrib_fix_width_sidebar() { | |||
} | |||
function opendistrib_scroll(id) { | |||
if ($("#" + id).size()) | |||
if ($("#" + id).size()) { | |||
$('html,body').animate({ | |||
scrollTop: $("#" + id).offset().top | |||
}, | |||
1000); | |||
}, 500); | |||
} | |||
} | |||
function opendistrib_base_url(with_slug) { |
@@ -509,6 +509,7 @@ var app = new Vue({ | |||
return thePriceWithTax; | |||
} | |||
}, | |||
confirmClick: function() { | |||
var app = this ; | |||
@@ -516,7 +517,16 @@ var app = new Vue({ | |||
// delivery | |||
if(app.pointSaleActive.is_home_delivery && !app.deliveryAddress) { | |||
this.errors = [] ; | |||
this.errors.push('Veuillez saisir une adresse de livraison') ; | |||
this.errors.push('Veuillez saisir une adresse de livraison.') ; | |||
opendistrib_scroll('page-title'); | |||
return false ; | |||
} | |||
// montant minimum de commande | |||
if(app.pointSaleActive.minimum_order_amount > 0 && app.priceTotal() < app.pointSaleActive.minimum_order_amount) { | |||
this.errors = [] ; | |||
this.errors.push('Le montant minimum de commande est de '+app.formatPrice(app.pointSaleActive.minimum_order_amount)+' pour ce point de vente.') ; | |||
opendistrib_scroll('page-title'); | |||
return false ; | |||
} | |||
@@ -69,7 +69,7 @@ | |||
padding-right: 0px ; | |||
} | |||
&#step-payment .btn::after, | |||
&#step-products .btn::after, | |||
&.first .btn::before { | |||
display: none ; | |||
} | |||
@@ -219,7 +219,8 @@ | |||
font-weight: bold; | |||
} | |||
.comment { | |||
.comment, | |||
.minimum-order-amount { | |||
color: gray; | |||
a { |