Browse Source

Parrainage producteurs

feature/rotating_product
Guillaume Bourgeois 6 months ago
parent
commit
3162c80d74
13 changed files with 314 additions and 5 deletions
  1. +42
    -0
      backend/controllers/SponsorshipController.php
  2. +7
    -0
      backend/views/layouts/left.php
  3. +110
    -0
      backend/views/sponsorship/index.php
  4. +9
    -0
      backend/web/js/backend.js
  5. +41
    -0
      console/migrations/m240613_070747_add_columns_producer_sponsorship.php
  6. +1
    -0
      domain/Feature/Feature/Feature.php
  7. +2
    -1
      domain/Feature/Feature/FeatureDefinition.php
  8. +50
    -2
      domain/Producer/Producer/Producer.php
  9. +8
    -0
      domain/Producer/Producer/ProducerBuilder.php
  10. +14
    -0
      domain/Producer/Producer/ProducerRepository.php
  11. +13
    -0
      domain/Producer/Producer/ProducerRepositoryQuery.php
  12. +5
    -0
      domain/Producer/Producer/ProducerSolver.php
  13. +12
    -2
      frontend/controllers/SiteController.php

+ 42
- 0
backend/controllers/SponsorshipController.php View File

@@ -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)
]);
}
}

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

@@ -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',

+ 110
- 0
backend/views/sponsorship/index.php View File

@@ -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>

+ 9
- 0
backend/web/js/backend.js View File

@@ -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);

+ 41
- 0
console/migrations/m240613_070747_add_columns_producer_sponsorship.php View File

@@ -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');
}
}

+ 1
- 0
domain/Feature/Feature/Feature.php View File

@@ -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

+ 2
- 1
domain/Feature/Feature/FeatureDefinition.php View File

@@ -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"
];
}
}

+ 50
- 2
domain/Producer/Producer/Producer.php View File

@@ -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
*/

+ 8
- 0
domain/Producer/Producer/ProducerBuilder.php View File

@@ -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;
}
}

+ 14
- 0
domain/Producer/Producer/ProducerRepository.php View File

@@ -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();
}
}

+ 13
- 0
domain/Producer/Producer/ProducerRepositoryQuery.php View File

@@ -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;
}
}

+ 5
- 0
domain/Producer/Producer/ProducerSolver.php View File

@@ -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()]);
}
}

+ 12
- 2
frontend/controllers/SiteController.php View File

@@ -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']);
}

Loading…
Cancel
Save