@@ -0,0 +1,42 @@ | |||
<?php | |||
namespace backend\controllers; | |||
use backend\controllers\BackendController; | |||
use domain\Feature\Feature\Feature; | |||
use yii\filters\AccessControl; | |||
class SponsorshipController extends BackendController | |||
{ | |||
public function behaviors() | |||
{ | |||
return [ | |||
'access' => [ | |||
'class' => AccessControl::class, | |||
'rules' => [ | |||
[ | |||
'allow' => true, | |||
'roles' => ['@'], | |||
'matchCallback' => function ($rule, $action) { | |||
return | |||
$this->getFeatureModule()->getChecker()->isEnabled(Feature::ALIAS_SPONSORSHIP) | |||
&& $this->getUserModule() | |||
->getAuthorizationChecker() | |||
->isGrantedAsProducer($this->getUserCurrent()); | |||
} | |||
], | |||
], | |||
], | |||
]; | |||
} | |||
public function actionIndex() | |||
{ | |||
$producerCurrent = $this->getProducerCurrent(); | |||
return $this->render('index', [ | |||
'producer' => $producerCurrent, | |||
'producersGodsonsArray' => $this->getProducerModule()->getRepository()->findProducersSponsorshipGodsons($producerCurrent) | |||
]); | |||
} | |||
} |
@@ -279,6 +279,13 @@ $isUserCurrentGrantedAsProducer = $userModule->getAuthorizationChecker()->isGran | |||
'template' => '<a href="{url}">{icon} {label}' . $countProducerInvoicesUnpaidLabel . '</a>' | |||
], | |||
['label' => 'Tarifs & modules', 'icon' => 'euro', 'url' => ['/producer/billing'], 'visible' => $isUserCurrentGrantedAsProducer], | |||
[ | |||
'label' => 'Parrainage', | |||
'icon' => 'users', | |||
'url' => ['/sponsorship/index'], | |||
'visible' => $isUserCurrentGrantedAsProducer && $featureChecker->isEnabled(Feature::ALIAS_SPONSORSHIP), | |||
'active' => Yii::$app->controller->id == 'sponsorship' | |||
], | |||
[ | |||
'label' => 'Développement', | |||
'icon' => 'code', |
@@ -0,0 +1,110 @@ | |||
<?php | |||
/** | |||
Copyright La boîte à pain (2018) | |||
contact@souke.fr | |||
Ce logiciel est un programme informatique servant à aider les producteurs | |||
à distribuer leur production en circuits courts. | |||
Ce logiciel est régi par la licence CeCILL soumise au droit français et | |||
respectant les principes de diffusion des logiciels libres. Vous pouvez | |||
utiliser, modifier et/ou redistribuer ce programme sous les conditions | |||
de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA | |||
sur le site "http://www.cecill.info". | |||
En contrepartie de l'accessibilité au code source et des droits de copie, | |||
de modification et de redistribution accordés par cette licence, il n'est | |||
offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons, | |||
seule une responsabilité restreinte pèse sur l'auteur du programme, le | |||
titulaire des droits patrimoniaux et les concédants successifs. | |||
A cet égard l'attention de l'utilisateur est attirée sur les risques | |||
associés au chargement, à l'utilisation, à la modification et/ou au | |||
développement et à la reproduction du logiciel par l'utilisateur étant | |||
donné sa spécificité de logiciel libre, qui peut le rendre complexe à | |||
manipuler et qui le réserve donc à des développeurs et des professionnels | |||
avertis possédant des connaissances informatiques approfondies. Les | |||
utilisateurs sont donc invités à charger et tester l'adéquation du | |||
logiciel à leurs besoins dans des conditions permettant d'assurer la | |||
sécurité de leurs systèmes et ou de leurs données et, plus généralement, | |||
à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. | |||
Le fait que vous puissiez accéder à cet en-tête signifie que vous avez | |||
pris connaissance de la licence CeCILL, et que vous en avez accepté les | |||
termes. | |||
*/ | |||
use common\helpers\Price; | |||
use yii\helpers\Html; | |||
$this->setTitle('Parrainage') ; | |||
$this->addBreadcrumb($this->getTitle()) ; | |||
$sponsorshipLink = $this->getProducerModule()->getSolver()->getSponsorshipLink($producer); | |||
?> | |||
<div class="alert alert-dark"> | |||
<p> | |||
<i class="bi bi-link"></i> | |||
Votre lien de parrainage : <br /> | |||
<strong> | |||
<?= $sponsorshipLink ?> | |||
<a class="btn btn-xs btn-default" id="sponsorship-link-copy" href="<?= $sponsorshipLink ?>" title="Copier le lien dans le presse-papier"> | |||
<span class="glyphicon glyphicon-link"></span> | |||
</a> | |||
</strong> | |||
</p> | |||
</div> | |||
<div class="panel panel-default"> | |||
<div class="panel-heading"> | |||
<h3 class="panel-title"> | |||
<i class="fa fa-info"></i> | |||
Comment ça marche ? | |||
</h3> | |||
</div> | |||
<div class="panel-body"> | |||
<p> | |||
Partagez votre lien de parrainage avec les producteurs que vous souhaitez parrainer. Quand un de ces | |||
producteurs s'inscrit en suivant ce lien, il devient votre filleul et obtenez tous les deux une récompense : | |||
</p> | |||
<ul> | |||
<li>Votre filleul démarre avec <strong>3 mois offerts</strong> d'utilisation du logiciel</li> | |||
<li>Vous obtenez <strong>30€ d'avoir</strong> sur vos prochaines factures</li> | |||
</ul> | |||
</div> | |||
</div> | |||
<div class="panel panel-default"> | |||
<div class="panel-heading"> | |||
<h3 class="panel-title"> | |||
<i class="fa fa-users"></i> | |||
Vos filleuls | |||
</h3> | |||
</div> | |||
<div class="panel-body"> | |||
<?php if($producersGodsonsArray && count($producersGodsonsArray)): ?> | |||
<table class="table table-bordered table-striped"> | |||
<thead> | |||
<tr> | |||
<th>Producteur</th> | |||
<th>Date</th> | |||
</tr> | |||
</thead> | |||
<tbody> | |||
<?php foreach($producersGodsonsArray as $producerGodson): ?> | |||
<tr> | |||
<td><?= Html::encode($producerGodson->getName()); ?></td> | |||
<td><?= date('d/m/Y', strtotime($producerGodson->date_creation)); ?></td> | |||
</tr> | |||
<?php endforeach; ?> | |||
</tbody> | |||
</table> | |||
<?php else: ?> | |||
<p>Vous n'avez encore aucun producteur parrainé.</p> | |||
<?php endif; ?> | |||
</div> | |||
</div> |
@@ -59,8 +59,17 @@ $(document).ready(function () { | |||
opendistrib_check_all_checkboxes(); | |||
opendistrib_dashboard_admin_statistics(); | |||
opendistrib_tinymce_responsive(); | |||
opendistrib_sponsorship(); | |||
}); | |||
function opendistrib_sponsorship() { | |||
$('#sponsorship-link-copy').click(function() { | |||
navigator.clipboard.writeText($(this).attr('href')); | |||
appAlerts.alert('success', 'Lien de parrainage copié'); | |||
return false; | |||
}); | |||
} | |||
function saveData (data, fileName) { | |||
var a = document.createElement("a"); | |||
document.body.appendChild(a); |
@@ -0,0 +1,41 @@ | |||
<?php | |||
use common\helpers\Password; | |||
use domain\Producer\Producer\ProducerBuilder; | |||
use domain\Producer\Producer\ProducerRepository; | |||
use yii\db\Migration; | |||
use yii\db\Schema; | |||
/** | |||
* Class m240613_070747_add_columns_producer_sponsorship | |||
*/ | |||
class m240613_070747_add_columns_producer_sponsorship extends Migration | |||
{ | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeUp() | |||
{ | |||
$this->addColumn('producer', 'sponsorship_code', Schema::TYPE_STRING); | |||
$this->addColumn('producer', 'sponsored_by', Schema::TYPE_INTEGER); | |||
$this->addColumn('producer', 'sponsorship_sponsor_reward', Schema::TYPE_BOOLEAN); | |||
$this->addColumn('producer', 'sponsorship_godson_reward', Schema::TYPE_BOOLEAN); | |||
$producersArray = ProducerRepository::getInstance()->findAll(); | |||
foreach($producersArray as $producer) { | |||
ProducerBuilder::getInstance()->initSponsorshipCode($producer); | |||
$producer->save(); | |||
} | |||
} | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeDown() | |||
{ | |||
$this->dropColumn('producer', 'sponsorship_code'); | |||
$this->dropColumn('producer', 'sponsored_by'); | |||
$this->dropColumn('producer', 'sponsorship_sponsor_reward'); | |||
$this->dropColumn('producer', 'sponsorship_godson_reward'); | |||
} | |||
} |
@@ -52,6 +52,7 @@ class Feature extends ActiveRecordCommon | |||
const ALIAS_SHOP_SUPPORT = 'shop_support'; | |||
const ALIAS_SHARED_POINT_SALE = 'shared_point_sale'; | |||
const ALIAS_SUMUP_SYNCHRONIZATION = 'sumup_synchronization'; | |||
const ALIAS_SPONSORSHIP = 'sponsorship'; | |||
/** | |||
* @inheritdoc |
@@ -21,7 +21,8 @@ class FeatureDefinition extends AbstractDefinition | |||
Feature::ALIAS_SETTINGS => 'Système de paramètres', | |||
Feature::ALIAS_SHOP_SUPPORT => 'Support boutique', | |||
Feature::ALIAS_SHARED_POINT_SALE => 'Points de vente partagés', | |||
Feature::ALIAS_SUMUP_SYNCHRONIZATION => "Synchronisation de commandes avec Sumup / Tiller" | |||
Feature::ALIAS_SUMUP_SYNCHRONIZATION => "Synchronisation de commandes avec Sumup / Tiller", | |||
Feature::ALIAS_SPONSORSHIP => "Parrainage producteurs" | |||
]; | |||
} | |||
} |
@@ -173,7 +173,8 @@ class Producer extends ActiveRecordCommon | |||
'option_weeks_distributions_activated_in_advance', | |||
'option_document_width_logo', | |||
'export_shopping_cart_labels_number_per_column', | |||
'id_user_group_default' | |||
'id_user_group_default', | |||
'sponsored_by' | |||
], | |||
'integer' | |||
], | |||
@@ -261,6 +262,7 @@ class Producer extends ActiveRecordCommon | |||
'option_leave_period_message_title', | |||
'option_leave_period_message', | |||
'option_credit_description', | |||
'sponsorship_code' | |||
], | |||
'string' | |||
], | |||
@@ -304,7 +306,9 @@ class Producer extends ActiveRecordCommon | |||
'delivery_note_automatic_validation', | |||
'is_new', | |||
'agree_contact_about_software_development', | |||
'option_leave_period_message_display' | |||
'option_leave_period_message_display', | |||
'sponsorship_sponsor_reward', | |||
'sponsorship_godson_reward', | |||
], | |||
'boolean' | |||
], | |||
@@ -550,6 +554,50 @@ class Producer extends ActiveRecordCommon | |||
return $this->name; | |||
} | |||
public function getSponsorshipCode(): string | |||
{ | |||
return $this->sponsorship_code; | |||
} | |||
public function setSponsorshipCode(string $sponsorshipCode): self | |||
{ | |||
$this->sponsorship_code = $sponsorshipCode; | |||
return $this; | |||
} | |||
public function getSponsoredBy(): ?User | |||
{ | |||
return $this->sponsoredByRelation; | |||
} | |||
public function setSponsoredBy(User $user): self | |||
{ | |||
$this->populateFieldObject('sponsored_by', 'sponsoredByRelation', $user); | |||
return $this; | |||
} | |||
public function getSponsorshipSponsorReward(): ?bool | |||
{ | |||
return $this->sponsorship_sponsor_reward; | |||
} | |||
public function setSponsorshipSponsorReward(bool $sponsorshipSponsorReward = null): self | |||
{ | |||
$this->sponsorship_sponsor_reward = $sponsorshipSponsorReward; | |||
return $this; | |||
} | |||
public function getSponsorshipGodsonReward(): ?bool | |||
{ | |||
return $this->sponsorship_godson_reward; | |||
} | |||
public function setSponsorshipGodsonReward(bool $sponsorshipGodsonReward = null): self | |||
{ | |||
$this->sponsorship_godson_reward = $sponsorshipGodsonReward; | |||
return $this; | |||
} | |||
/* | |||
* Relations | |||
*/ |
@@ -30,8 +30,10 @@ class ProducerBuilder extends AbstractBuilder | |||
public function instanciateProducer(): Producer | |||
{ | |||
$producer = new Producer(); | |||
$producer->order_deadline = Producer::ORDER_DEADLINE_DEFAULT; | |||
$producer->order_delay = Producer::ORDER_DELAY_DEFAULT; | |||
$this->initSponsorshipCode($producer); | |||
return $producer; | |||
} | |||
@@ -161,4 +163,10 @@ class ProducerBuilder extends AbstractBuilder | |||
$producer->save(); | |||
} | |||
} | |||
public function initSponsorshipCode(Producer $producer): self | |||
{ | |||
$producer->setSponsorshipCode(Password::generate()); | |||
return $this; | |||
} | |||
} |
@@ -445,4 +445,18 @@ class ProducerRepository extends AbstractRepository | |||
return 0; | |||
} | |||
public function findOneProducerBySponsorshipCode(string $sponsorshipCode): ?Producer | |||
{ | |||
return $this->createQuery() | |||
->filterBySponsorshipCode($sponsorshipCode) | |||
->findOne(); | |||
} | |||
public function findProducersSponsorshipGodsons(Producer $producer): array | |||
{ | |||
return $this->createQuery() | |||
->filterBySponsoredBy($producer) | |||
->find(); | |||
} | |||
} |
@@ -42,4 +42,17 @@ class ProducerRepositoryQuery extends AbstractRepositoryQuery | |||
$this->andWhere('producer.option_time_saved > 0'); | |||
return $this; | |||
} | |||
public function filterBySponsorshipCode(string $sponsorshipCode): self | |||
{ | |||
$this->andWhere('producer.sponsorship_code LIKE :sponsorship_code') | |||
->addParams(['sponsorship_code' => $sponsorshipCode]); | |||
return $this; | |||
} | |||
public function filterBySponsoredBy(Producer $producer): self | |||
{ | |||
$this->andWhere(['producer.sponsored_by' => $producer->id]); | |||
return $this; | |||
} | |||
} |
@@ -307,4 +307,9 @@ class ProducerSolver extends AbstractService implements SolverInterface | |||
return false; | |||
} | |||
public function getSponsorshipLink(Producer $producer): string | |||
{ | |||
return \Yii::$app->urlManagerFrontend->createAbsoluteUrl(['site/signup', 'from' => $producer->getSponsorshipCode()]); | |||
} | |||
} |
@@ -80,7 +80,6 @@ class SiteController extends FrontendController | |||
[ | |||
'actions' => ['signup-producer'], | |||
'allow' => true, | |||
'roles' => ['@'], | |||
], | |||
[ | |||
'actions' => ['logout'], | |||
@@ -396,12 +395,23 @@ class SiteController extends FrontendController | |||
public function actionSignupProducer() | |||
{ | |||
$userCurrent = $this->getUserCurrent(); | |||
if(!$userCurrent) { | |||
// Lien parrainage | |||
if(Yii::$app->request->get('from')) { | |||
$this->redirect(['site/signup', 'from' => Yii::$app->request->get('from')]); | |||
} | |||
else { | |||
$this->redirect(['site/signup']); | |||
} | |||
} | |||
$model = new SignupForm(); | |||
$model->signup_producer_only = 'producer'; | |||
$model->option_user_producer = 'producer'; | |||
if ($model->load(Yii::$app->request->post())) { | |||
$user = $model->signup($this->getUserCurrent()); | |||
$user = $model->signup($userCurrent); | |||
if($user) { | |||
$this->redirect(['site/signup-confirm']); | |||
} |