Commit 42166e72 authored by Olivia Madrid's avatar Olivia Madrid

(feat): Referrals console

1 merge request!236epic/referrals
Pipeline #71566618 passed with stages
in 7 minutes and 6 seconds
This diff is collapsed.
......@@ -58,6 +58,10 @@ class NotificationDelegate
$entityGuid = $referral->getReferrerGuid();
$entity = $this->entitiesBuilder->single($entityGuid);
if ($referral->getJoinTimestamp()) {
return;
}
$this->dispatcher->trigger('notification', 'all', [
'to' => [$referral->getProspectGuid()],
'entity' => $entity,
......
......@@ -4,7 +4,11 @@
*/
namespace Minds\Core\Referrals;
use Minds\Core\Referrals\Referral;
use Minds\Core\Referrals\Repository;
use Minds\Core\Referrals\Delegates\NotificationDelegate;
use Minds\Core\EntitiesBuilder;
use Minds\Common\Repository\Response;
use Minds\Core\Di\Di;
class Manager
......
......@@ -51,7 +51,7 @@ class Referral
*/
public function getState()
{
// the referral goes from pending to complete when the prospect joins rewards
// Referral goes from pending to complete when the prospect joins rewards
if ($this->joinTimestamp) {
return 'complete';
}
......@@ -64,16 +64,21 @@ class Referral
*/
public function getPingable()
{
// Duration referrer must wait before re-pinging (in seconds)
$waitTime= 60*60*24*7; // 7 days
// Duration referrer must wait before re-pinging
$waitTime= 1000*60*60*24*7; // 7 days
$now = time() * 1000;
$now = time();
$elapsedTime = $now - $this->pingTimestamp;
if ($this->pingTimestamp && $elapsedTime < $waitTime ) {
if ($this->pingTimestamp && $elapsedTime < $waitTime) {
return false;
}
// Also disable ping if they've already joined rewards
if ($this->joinTimestamp) {
return false;
}
return true;
}
......@@ -87,9 +92,6 @@ class Referral
'referrer_guid' => $this->referrerGuid,
'prospect' => $this->prospect ? $this->prospect->export() : null,
'state' => $this->getState(),
'register_timestamp' => $this->registerTimestamp,
'join_timestamp' => $this->joinTimestamp,
'ping_timestamp' => $this->pingTimestamp,
'pingable' => $this->getPingable(),
];
}
......
......@@ -6,7 +6,7 @@ namespace Minds\Core\Referrals;
use Minds\Common\Repository\Response;
use Minds\Core\Di\Di;
use Minds\Core\Data\Cassandra\Prepared;
use Minds\Core\Data\Cassandra\Prepared;
use Cassandra;
use Cassandra\Bigint;
......@@ -60,22 +60,22 @@ class Repository
foreach ($rows as $row) {
$referral = new Referral();
$referral = new Referral();
$referral->setProspectGuid((string) $row['prospect_guid'])
->setReferrerGuid((string) $row['referrer_guid'])
->setRegisterTimestamp((string) $row['register_timestamp'])
->setJoinTimestamp((string) $row['join_timestamp'])
->setPingTimestamp((string) $row['ping_timestamp']);
->setRegisterTimestamp(isset($row['register_timestamp']) ? (int) $row['register_timestamp']->time() : null)
->setJoinTimestamp(isset($row['join_timestamp']) ? (int) $row['join_timestamp']->time() : null)
->setPingTimestamp(isset($row['ping_timestamp']) ? (int) $row['ping_timestamp']->time() : null);
$response[] = $referral;
}
$response->setPagingToken(base64_encode($rows->pagingStateToken()));
$response->setLastPage($rows->isLastPage());
$response->setLastPage($rows->isLastPage());
} catch (\Exception $e) {
$response = $e;
// $response = $e;
return $response;
}
......@@ -144,9 +144,9 @@ class Repository
if (!$referral->getJoinTimestamp()) {
throw new \Exception('Join timestamp is required');
}
$template = "UPDATE referrals SET join_timestamp = ? WHERE referrer_guid = ? AND prospect_guid = ?";
$values = [
new Cassandra\Timestamp($referral->getJoinTimestamp()),
new Cassandra\Bigint($referral->getReferrerGuid()),
......@@ -179,13 +179,13 @@ class Repository
if (!$referral->getProspectGuid()) {
throw new \Exception('Prospect GUID is required');
}
if (!$referral->getPingTimestamp()) {
throw new \Exception('Ping timestamp is required');
}
$template = "UPDATE referrals SET ping_timestamp = ? WHERE referrer_guid = ? AND prospect_guid = ?";
$values = [
new Cassandra\Timestamp($referral->getPingTimestamp()),
new Cassandra\Bigint($referral->getReferrerGuid()),
......
......@@ -157,12 +157,12 @@ class Join
->setAction('joined')
->push();
// Receive one free token automatically when you join rewards
// User receives one free token automatically when they join rewards
$transactions = Di::_()->get('Blockchain\Wallets\OffChain\Transactions');
$transactions
->setUser($this->user)
->setType('joined')
->setAmount(pow(10,18)); // TODO: v important - verify this is correct
->setAmount(pow(10,18));
$transaction = $transactions->create();
}
......
<?php
namespace Spec\Minds\Core\Referrals\Delegates;
use Minds\Core\Referrals\Referral;
use Minds\Core\Referrals\Manager;
use Minds\Core\Referrals\Repository;
use Minds\Core\Referrals\Delegates\NotificationDelegate;
use Minds\Core\Di\Di;
use Minds\Core\Events\EventsDispatcher;
use Minds\Core\EntitiesBuilder;
use Minds\Entities\Entity;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class NotificationDelegateSpec extends ObjectBehavior
{
/** @var EventsDispatcher $dispatcher */
private $dispatcher;
/** @var EntitiesBuilder $entitiesBuilder */
private $entitiesBuilder;
function let(
EventsDispatcher $dispatcher,
EntitiesBuilder $entitiesBuilder
)
{
$this->beConstructedWith($dispatcher, $entitiesBuilder);
$this->dispatcher=$dispatcher;
$this->entitiesBuilder = $entitiesBuilder;
}
function it_is_initializable()
{
$this->shouldHaveType(NotificationDelegate::class);
}
function it_should_send_a_pending_referral_notification_to_referrer(Referral $referral, Entity $entity)
{
$referral->getReferrerGuid()
->shouldBeCalled()
->willReturn(456);
$referral->getProspectGuid()
->shouldBeCalled()
->willReturn(123);
$this->entitiesBuilder->single(123)
->willReturn($entity);
$referral->getJoinTimestamp()
->shouldBeCalled()
->willReturn(null); // Referral is pending bc hasn't joined rewards yet
$this->dispatcher->trigger('notification', 'all', Argument::that(function ($opts) {
return $opts['notification_view'] === 'referral_pending';
}))
->shouldBeCalled();
$this->notifyReferrer($referral);
}
function it_should_send_a_completed_referral_notification_to_referrer(Referral $referral, Entity $entity )
{
$referral->getReferrerGuid()
->shouldBeCalled()
->willReturn(456);
$referral->getProspectGuid()
->shouldBeCalled()
->willReturn(123);
$this->entitiesBuilder->single(123)
->willReturn($entity);
$referral->getJoinTimestamp()
->shouldBeCalled()
->willReturn(111); // Referral is complete bc prospect has joined rewards
$this->dispatcher->trigger('notification', 'all', Argument::that(function ($opts) {
return $opts['notification_view'] === 'referral_complete';
}))
->shouldBeCalled();
$this->notifyReferrer($referral);
}
function it_should_send_a_ping_notification_to_pending_prospect(Referral $referral, Entity $entity )
{
$referral->getProspectGuid()
->shouldBeCalled()
->willReturn(123);
$referral->getReferrerGuid()
->shouldBeCalled()
->willReturn(456);
$this->entitiesBuilder->single(456)
->willReturn($entity);
$referral->getJoinTimestamp()
->shouldBeCalled()
->willReturn(); // Referral is pending bc hasn't joined rewards yet
$this->dispatcher->trigger('notification', 'all', Argument::that(function ($opts) {
return $opts['notification_view'] === 'referral_ping';
}))
->shouldBeCalled();
$this->notifyProspect($referral);
}
function it_should_not_send_a_ping_notification_to_completed_prospect(Referral $referral, Entity $entity )
{
$referral->getReferrerGuid()
->shouldBeCalled()
->willReturn(456);
$this->entitiesBuilder->single(456)
->willReturn($entity);
$referral->getJoinTimestamp()
->shouldBeCalled()
->willReturn(111); // Referral is complete bc joined rewards
$this->dispatcher->trigger('notification', 'all', Argument::that(function ($opts) {
return $opts['notification_view'] === 'referral_ping';
}))
->shouldNotBeCalled();
$this->notifyProspect($referral);
}
}
......@@ -2,18 +2,16 @@
namespace Spec\Minds\Core\Referrals;
use Minds\Core\Referrals\Referral;
use Minds\Core\Referrals\Manager;
use Minds\Core\Referrals\Referral;
use Minds\Core\Referrals\Repository;
use Minds\Core\Referrals\Delegates\NotificationDelegate;
use Minds\Core\Di\Di;
use Minds\Core\EntitiesBuilder;
use Minds\Entities\User;
use Minds\Common\Repository\Response;
use Minds\Core\Di\Di;
use Minds\Core\EntitiesBuilder;
use Minds\Core;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ManagerSpec extends ObjectBehavior
{
......@@ -25,30 +23,29 @@ class ManagerSpec extends ObjectBehavior
Repository $repository,
NotificationDelegate $notificationDelegate,
EntitiesBuilder $entitiesBuilder
)
)
{
// $this->beConstructedWith($repository, $entitiesBuilder);
$this->beConstructedWith($repository, $notificationDelegate);
$this->repository=$repository;
$this->notificationDelegate = $notificationDelegate ?: new Delegates\NotificationDelegate;
// $this->entitiesBuilder = $entitiesBuilder;
$this->entitiesBuilder = Di::_()->get('EntitiesBuilder');
$this->beConstructedWith($repository, $notificationDelegate, $entitiesBuilder);
$this->repository = $repository;
$this->notificationDelegate = $notificationDelegate;
$this->entitiesBuilder = $entitiesBuilder;
}
function it_is_initializable()
{
$this->shouldHaveType(Manager::class);
}
function it_should_add_a_referral()
{
{
$referral = new Referral();
$referral->setProspectGuid(444)
->setReferrerGuid(456)
->setRegisterTimestamp(21);
$this->repository->add($referral)
->shouldBeCalled();
$this->notificationDelegate->notifyReferrer($referral)
->shouldBeCalled();
$this->add($referral)
->shouldReturn(true);
}
......@@ -61,67 +58,67 @@ class ManagerSpec extends ObjectBehavior
->setJoinTimestamp(22);
$this->repository->update($referral)
->shouldBeCalled();
$this->notificationDelegate->notifyReferrer($referral)
->shouldBeCalled();
$this->update($referral)
->shouldReturn(true);
}
// function it_should_return_a_list_of_referrals()
// {
// $response = new Response();
// $response[] = (new Referral)
// ->setReferrerGuid(123)
// ->setProspectGuid(777)
// ->setRegisterTimestamp(11)
// ->setJoinTimestamp(12);
// $response[] = (new Referral)
// ->setReferrerGuid(123)
// ->setProspectGuid(888)
// ->setRegisterTimestamp(13)
// ->setJoinTimestamp(14);
// $this->repository->getList([
// 'limit' => 12,
// 'offset' => '',
// 'referrer_guid' => 123,
// 'hydrate' => true,
// ])
// ->shouldBeCalled()
// ->willReturn($response);
// $this->entitiesBuilder->single(777)
// ->shouldBeCalled()
// ->willReturn((new User)->set('guid', 777));
// $this->entitiesBuilder->single(888)
// ->shouldBeCalled()
// ->willReturn((new User)->set('guid', 888));
// $newResponse = $this->getList([
// 'limit' => 12,
// 'offset' => '',
// 'referrer_guid' => 123,
// 'hydrate' => true
// ]);
function it_should_update_ping_timestamp_and_trigger_ping_notification()
{
$referral = new Referral();
$referral->setProspectGuid(123)
->setReferrerGuid(456)
->setPingTimestamp(111);
$this->repository->ping($referral)
->shouldBeCalled();
$this->notificationDelegate->notifyProspect($referral)
->shouldBeCalled();
$this->ping($referral)
->shouldReturn(true);
}
// $newResponse[0]->getReferrerGuid()
// ->shouldBe(123);
// $newResponse[0]->getProspect()->getGuid()
// ->shouldBe(777);
// $newResponse[0]->getRegisterTimestamp()
// ->shouldBe(11);
// $newResponse[0]->getJoinTimestamp()
// ->shouldBe(12);
// $newResponse[1]->getReferrerGuid()
// ->shouldBe(123);
// $newResponse[1]->getProspect()->getGuid()
// ->shouldBe(888);
// $newResponse[1]->getRegisterTimestamp()
// ->shouldBe(13);
// $newResponse[1]->getJoinTimestamp()
// ->shouldBe(14);
// }
function it_should_get_a_list_of_referrals()
{
$response = new Response();
$response[] = (new Referral)
->setReferrerGuid(123)
->setProspectGuid(456)
->setRegisterTimestamp(11)
->setJoinTimestamp(22)
->setPingTimestamp(null);
$this->repository->getList([
'limit' => 12,
'offset' => '',
'referrer_guid' => 123,
'hydrate' => true,
])
->shouldBeCalled()
->willReturn($response);
$this->entitiesBuilder->single(456)
->shouldBeCalled()
->willReturn((new User)->set('guid', 456));
$newResponse = $this->getList([
'limit' => 12,
'offset' => '',
'referrer_guid' => 123,
'hydrate' => true
]);
$newResponse[0]->getReferrerGuid()
->shouldBe(123);
$newResponse[0]->getProspectGuid()
->shouldBe(456);
$newResponse[0]->getProspect()->getGuid()
->shouldBe(456);
$newResponse[0]->getRegisterTimestamp()
->shouldBe(11);
$newResponse[0]->getJoinTimestamp()
->shouldBe(22);
$newResponse[0]->getPingTimestamp()
->shouldBe(null);
}
}
......@@ -3,9 +3,7 @@
namespace Spec\Minds\Core\Referrals;
use Minds\Core\Referrals\Referral;
use Minds\Entities\User;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ReferralSpec extends ObjectBehavior
{
......
......@@ -10,18 +10,21 @@ use Cassandra\Bigint;
use Cassandra\Timestamp;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Spec\Minds\Mocks\Cassandra\Rows;
class RepositorySpec extends ObjectBehavior
{
private $client;
function let(Client $client)
{
$this->beConstructedWith($client);
$this->client = $client;
}
function it_is_initializable()
{
$this->shouldHaveType(Repository::class);
......@@ -63,46 +66,50 @@ class RepositorySpec extends ObjectBehavior
$referral->setReferrerGuid(123)
->setProspectGuid(456)
->setJoinTimestamp(789);
$this
->update($referral)
->shouldReturn(true);
}
// function it_should_return_a_list_of_referrals()
// {
// $this->client->request(Argument::that(function($prepared) {
// return true;
// }))
// ->shouldBeCalled()
// ->willReturn([
// [
// 'referrer_guid' => new Bigint(123),
// 'prospect_guid' => new Bigint(456),
// 'register_timestamp' => new Timestamp(1545451597777),
// 'join_timestamp' => new Timestamp(1545451597778),
// ],
// [
// 'referrer_guid' => new Bigint(123),
// 'prospect_guid' => new Bigint(567),
// 'register_timestamp' => new Timestamp(1545451598888),
// 'join_timestamp' => new Timestamp(1545451598889),
// ],
// ]);
// $response = $this->getList([
// 'referrer_guid' => 123,
// ]);
// $response->shouldHaveCount(2);
// $response[0]->getProspectGuid()
// ->shouldBe(456);
// $response[0]->getRegisterTimestamp()
// ->shouldBe(1545451597777);
// $response[0]->getJoinTimestamp()
// ->shouldBe(1545451597778);
// // err:Error("Call to a member function pagingStateToken() on array")
// }
function it_should_return_a_list_of_referrals()
{
$this->client->request(Argument::that(function($prepared) {
return true;
}))
->shouldBeCalled()
->willReturn(new Rows([
[
'referrer_guid' => new Bigint(123),
'prospect_guid' => new Bigint(456),
'register_timestamp' => new Timestamp(1545451597777),
'join_timestamp' => new Timestamp(1545451597778),
'ping_timestamp' => null,
],
[
'referrer_guid' => new Bigint(123),
'prospect_guid' => new Bigint(567),
'register_timestamp' => new Timestamp(1545451598888),
'join_timestamp' => new Timestamp(1545451598889),
'ping_timestamp' => null,
],
], 'my-cool-paging-token'));
$response = $this->getList([
'referrer_guid' => 123,
]);
$response->shouldHaveCount(2);
$response[0]->getProspectGuid()
->shouldBe('456');
$response[0]->getRegisterTimestamp()
->shouldBe(1545451597777);
$response[0]->getJoinTimestamp()
->shouldBe(1545451597778);
}
function it_should_throw_if_no_referrer_guid_during_get_list()
......
<?php
namespace Spec\Minds\Core\Rewards\Delegates;
use Minds\Core\Rewards\Delegates\ReferralDelegate;
use Minds\Core\Referrals\Referral;
use Minds\Core\Referrals\Manager;
use Minds\Entities\User;
use Minds\Core\Di\Di;
use PhpSpec\ObjectBehavior;
class ReferralDelegateSpec extends ObjectBehavior
{
/** @var Manager $manager */
private $manager;
/** @var User $user */
private $user;
function let(
Manager $manager,
User $user
)
{
$this->beConstructedWith($manager, $user);
$this->manager = $manager;
$this->user = $user;
}
function it_is_initializable()
{
$this->shouldHaveType(ReferralDelegate::class);
}
function it_should_tell_manager_to_update_referral(User $user)
{
$user->referrer = 123;
$user->guid = 456;
$referral = new Referral;
$referral->setReferrerGuid($user->referrer)
->shouldBeCalled();
$referral->setProspectGuid($user->guid)
->shouldBeCalled();
$referral->setJoinTimestamp(time())
->shouldBeCalled();
$this->manager->update($referral)
->shouldBeCalled();
$this->onReferral($user);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment