<?php
namespace Whater\Domain\Product\Model;
use Whater\Domain\Common\Exception\InvalidUUIDException;
use Ramsey\Uuid\Uuid;
use Whater\Domain\Product\Exception\InvalidWalletOperationTypeException;
use Whater\Domain\User\Model\User;
use Whater\Domain\Whater\Model\WhaterOrganization;
/**
*
* @package Whater\Domain\Product\Model
*/
class WalletOperation
{
/**
* See Readme.md#Wallet
*/
const WOT_PURCHASE_WHATERCOINS = 'WOT_PURCHASE_WHATERCOINS';
const WOT_GIFT_WHATERCOINS = 'WOT_GIFT_WHATERCOINS';
const WOT_PURCHASE_PRODUCT_WITH_MONEY = 'WOT_PURCHASE_PRODUCT_WITH_MONEY';
const WOT_PURCHASE_PRODUCT_WITH_COINS = 'WOT_PURCHASE_PRODUCT_WITH_COINS';
const WOT_REFUND_PRODUCT_WITH_MONEY = 'WOT_REFUND_PRODUCT_WITH_MONEY';
const WOT_REFUND_PRODUCT_WITH_COINS = 'WOT_REFUND_PRODUCT_WITH_COINS';
const WOT_TRANSFER_COINS = 'WOT_TRANSFER_COINS';
const WO_CURRENCY_EURO = 'EUR';
/**
* @var string
*/
protected $uuid;
/**
* @var \DateTime
*/
protected $operationDate;
/**
* @var string
*/
protected $walletOperationType;
// USER AND/OR WHATERORGANIZATION
/**
* @var User
*/
protected $buyerUser;
/**
* @var WhaterOrganization
*/
protected $buyerWhaterOrganization;
/**
* @var WhaterOrganization
*/
protected $sellerWhaterOrganization;
// MONEY
/**
* @var float
*/
protected $buyerUserMoney;
/**
* @var float
*/
protected $buyerWhaterOrganizationMoney;
/**
* @var float
*/
protected $sellerWhaterOrganizationMoney;
/**
* @var float
*/
protected $whaterAppMoney;
/**
* @var float
*/
protected $stripeCommisionMoney;
// WHATERCOINS
/**
* @var float
*/
protected $buyerUserCoins;
/**
* @var float
*/
protected $buyerWhaterOrganizationCoins;
/**
* @var float
*/
protected $sellerWhaterOrganizationCoins;
/**
* @var float
*/
protected $whaterAppCoins;
// CURRENCY
/**
* @var string
*/
protected $currency;
/**
* @var PaymentInstructionOrder
*/
protected $paymentInstructionOrder;
/**
* @var string
*/
protected $checksum;
/**
* @var string
*/
protected $privateNote;
/**
* @var string
*/
protected $publicNote;
/**
* @var \DateTime
*/
protected $createdAt;
/**
* @var WalletLiquidationRequest
*/
protected $walletLiquidationRequest;
/**
* WalletOperation constructor.
*/
private function __construct(
string $walletOperationId = null,
\DateTime $operationDate,
string $walletOperationType,
User $buyerUser = null,
WhaterOrganization $buyerWhaterOrganization = null,
WhaterOrganization $sellerWhaterOrganization = null,
float $buyerUserMoney = 0,
float $buyerWhaterOrganizationMoney = 0,
float $sellerWhaterOrganizationMoney = 0,
float $whaterAppMoney = 0,
float $stripeCommisionMoney = 0,
string $currency = WalletOperation::WO_CURRENCY_EURO,
float $buyerUserCoins = 0,
float $buyerWhaterOrganizationCoins = 0,
float $sellerWhaterOrganizationCoins = 0,
float $whaterAppCoins = 0,
) {
try {
$this->uuid = Uuid::fromString($walletOperationId ?: Uuid::uuid4())->toString();
} catch (\InvalidArgumentException $e) {
throw new InvalidUUIDException();
}
$this->operationDate = $operationDate;
switch ($walletOperationType) {
case WalletOperation::WOT_PURCHASE_WHATERCOINS:
$this->walletOperationType = $walletOperationType;
$this->buyerUser = $buyerUser;
$this->buyerWhaterOrganization = $buyerWhaterOrganization;
$this->buyerUserMoney = $buyerUserMoney;
$this->buyerWhaterOrganizationMoney = $buyerWhaterOrganizationMoney;
$this->whaterAppMoney = $whaterAppMoney;
$this->buyerUserCoins = $buyerUserCoins;
$this->buyerWhaterOrganizationCoins = $buyerWhaterOrganizationCoins;
$this->whaterAppCoins = $whaterAppCoins;
break;
case WalletOperation::WOT_GIFT_WHATERCOINS:
$this->walletOperationType = $walletOperationType;
$this->buyerUser = $buyerUser;
$this->buyerWhaterOrganization = $buyerWhaterOrganization;
$this->buyerUserCoins = $buyerUserCoins;
$this->buyerWhaterOrganizationCoins = $buyerWhaterOrganizationCoins;
$this->whaterAppCoins = $whaterAppCoins;
break;
case WalletOperation::WOT_PURCHASE_PRODUCT_WITH_MONEY:
$this->walletOperationType = $walletOperationType;
$this->buyerUser = $buyerUser;
$this->buyerWhaterOrganization = $buyerWhaterOrganization;
$this->sellerWhaterOrganization = $sellerWhaterOrganization;
$this->buyerUserMoney = $buyerUserMoney;
$this->buyerWhaterOrganizationMoney = $buyerWhaterOrganizationMoney;
$this->sellerWhaterOrganizationMoney = $sellerWhaterOrganizationMoney;
$this->whaterAppMoney = $whaterAppMoney;
break;
case WalletOperation::WOT_PURCHASE_PRODUCT_WITH_COINS:
$this->walletOperationType = $walletOperationType;
$this->buyerUser = $buyerUser;
$this->buyerWhaterOrganization = $buyerWhaterOrganization;
$this->sellerWhaterOrganization = $sellerWhaterOrganization;
$this->buyerUserMoney = $buyerUserMoney;
$this->buyerWhaterOrganizationMoney = $buyerWhaterOrganizationMoney;
$this->sellerWhaterOrganizationMoney = $sellerWhaterOrganizationMoney;
$this->whaterAppMoney = $whaterAppMoney;
$this->buyerUserCoins = $buyerUserCoins;
$this->buyerWhaterOrganizationCoins = $buyerWhaterOrganizationCoins;
$this->sellerWhaterOrganizationCoins = $sellerWhaterOrganizationCoins;
$this->whaterAppCoins = $whaterAppCoins;
break;
case WalletOperation::WOT_REFUND_PRODUCT_WITH_MONEY:
$this->walletOperationType = $walletOperationType;
$this->buyerUser = $buyerUser;
$this->buyerWhaterOrganization = $buyerWhaterOrganization;
$this->sellerWhaterOrganization = $sellerWhaterOrganization;
$this->buyerUserMoney = $buyerUserMoney;
$this->buyerWhaterOrganizationMoney = $buyerWhaterOrganizationMoney;
$this->sellerWhaterOrganizationMoney = $sellerWhaterOrganizationMoney;
$this->whaterAppMoney = $whaterAppMoney;
break;
case WalletOperation::WOT_REFUND_PRODUCT_WITH_COINS:
$this->walletOperationType = $walletOperationType;
$this->buyerUser = $buyerUser;
$this->buyerWhaterOrganization = $buyerWhaterOrganization;
$this->sellerWhaterOrganization = $sellerWhaterOrganization;
$this->buyerUserMoney = $buyerUserMoney;
$this->buyerWhaterOrganizationMoney = $buyerWhaterOrganizationMoney;
$this->sellerWhaterOrganizationMoney = $sellerWhaterOrganizationMoney;
$this->whaterAppMoney = $whaterAppMoney;
$this->buyerUserCoins = $buyerUserCoins;
$this->buyerWhaterOrganizationCoins = $buyerWhaterOrganizationCoins;
$this->sellerWhaterOrganizationCoins = $sellerWhaterOrganizationCoins;
$this->whaterAppCoins = $whaterAppCoins;
break;
case WalletOperation::WOT_TRANSFER_COINS:
$this->walletOperationType = $walletOperationType;
$this->buyerUser = $buyerUser;
$this->buyerWhaterOrganization = $buyerWhaterOrganization;
$this->sellerWhaterOrganization = $sellerWhaterOrganization;
$this->buyerUserCoins = $buyerUserCoins;
$this->buyerWhaterOrganizationCoins = $buyerWhaterOrganizationCoins;
$this->sellerWhaterOrganizationCoins = $sellerWhaterOrganizationCoins;
$this->whaterAppCoins = $whaterAppCoins;
break;
default:
throw new InvalidWalletOperationTypeException();
}
$this->stripeCommisionMoney = $stripeCommisionMoney;
if ($currency != null) {
switch ($currency) {
case WalletOperation::WO_CURRENCY_EURO:
$this->currency = $currency;
break;
default:
throw new InvalidWalletOperationTypeException();
}
}
// Calculate checksum
$operationDate = clone $this->operationDate();
$operationDate->setTimezone(new \DateTimeZone('UTC'));
$hash = md5($operationDate->format('dmYHis'));
$hash = md5($hash . $this->walletOperationType());
if ($this->buyerUser != null) {
$hash = md5($hash . $this->buyerUser->id());
}
if ($this->buyerWhaterOrganization != null) {
$hash = md5($hash . $this->buyerWhaterOrganization->id());
}
if ($this->sellerWhaterOrganization != null) {
$hash = md5($hash . $this->sellerWhaterOrganization->id());
}
$this->checksum = $hash;
$this->createdAt = new \DateTime();
}
public static function buildOperationForPurchaseOfCoins(
\DateTime $operationDate,
User $buyerUser = null,
WhaterOrganization $buyerWhaterOrganization = null,
float $money,
float $coins,
float $stripeCommisionMoney,
string $currency
): WalletOperation {
if ($buyerUser == null && $buyerWhaterOrganization == null) {
throw new InvalidWalletOperationTypeException();
}
if ($buyerUser != null && $buyerWhaterOrganization != null) {
throw new InvalidWalletOperationTypeException();
}
if ($buyerUser != null) {
$buyerUserCoins = $coins;
$buyerWhaterOrganizarionCoins = 0;
$buyerUserMoney = -$money;
$buyerWhaterOrganizationMoney = 0;
} else if ($buyerWhaterOrganization != null) {
$buyerUserCoins = 0;
$buyerWhaterOrganizarionCoins = $coins;
$buyerUserMoney = 0;
$buyerWhaterOrganizationMoney = -$money;
}
$walletOperation = new WalletOperation(
null,
$operationDate,
WalletOperation::WOT_PURCHASE_WHATERCOINS,
$buyerUser,
$buyerWhaterOrganization,
null,
$buyerUserMoney,
$buyerWhaterOrganizationMoney,
0,
$money,
$stripeCommisionMoney,
$currency,
$buyerUserCoins,
$buyerWhaterOrganizarionCoins,
0,
-$coins
);
return $walletOperation;
}
public static function buildOperationForGitfOfCoins(
\DateTime $operationDate,
User $buyerUser = null,
WhaterOrganization $buyerWhaterOrganization = null,
float $coins
): WalletOperation {
if ($buyerUser == null && $buyerWhaterOrganization == null) {
throw new InvalidWalletOperationTypeException();
}
if ($buyerUser != null && $buyerWhaterOrganization != null) {
throw new InvalidWalletOperationTypeException();
}
if ($buyerUser != null) {
$buyerUserCoins = $coins;
$buyerWhaterOrganizarionCoins = 0;
} else if ($buyerWhaterOrganization != null) {
$buyerUserCoins = 0;
$buyerWhaterOrganizarionCoins = $coins;
}
$walletOperation = new WalletOperation(
null,
$operationDate,
WalletOperation::WOT_GIFT_WHATERCOINS,
$buyerUser,
$buyerWhaterOrganization,
null,
0,
0,
0,
0,
0,
WalletOperation::WO_CURRENCY_EURO,
$buyerUserCoins,
$buyerWhaterOrganizarionCoins,
0,
-$coins
);
return $walletOperation;
}
public static function buildOperationForPurchaseOfProductsWithMoney(
\DateTime $operationDate,
User $buyerUser = null,
WhaterOrganization $buyerWhaterOrganization = null,
WhaterOrganization $sellerWhaterOrganization = null,
float $money,
float $sellerMoney,
float $stripeCommisionMoney,
float $whaterAppCommisionMoney,
string $currency
): WalletOperation {
if ($buyerUser == null && $buyerWhaterOrganization == null) {
throw new InvalidWalletOperationTypeException();
}
if ($buyerUser != null && $buyerWhaterOrganization != null) {
throw new InvalidWalletOperationTypeException();
}
if ($sellerWhaterOrganization != null) {
//if there is a sellerWhaterOrganization, check sellerMoney
$m1 = -$money;
$m2 = ($sellerMoney + $stripeCommisionMoney + $whaterAppCommisionMoney);
if(($m1 - $m2) > PHP_FLOAT_EPSILON){
throw new InvalidWalletOperationTypeException();
}
}
if ($buyerUser != null) {
$buyerUserMoney = $money;
$buyerWhaterOrganizarionMoney = 0;
} else if ($buyerWhaterOrganization != null) {
$buyerUserMoney = 0;
$buyerWhaterOrganizarionMoney = $money;
}
$walletOperation = new WalletOperation(
null,
$operationDate,
WalletOperation::WOT_PURCHASE_PRODUCT_WITH_MONEY,
$buyerUser,
$buyerWhaterOrganization,
$sellerWhaterOrganization,
$buyerUserMoney,
$buyerWhaterOrganizarionMoney,
$sellerMoney,
$whaterAppCommisionMoney,
$stripeCommisionMoney,
$currency,
0,
0,
0,
0
);
return $walletOperation;
}
public static function buildOperationForPurchaseOfProductsWithCoins(
\DateTime $operationDate,
User $buyerUser = null,
WhaterOrganization $buyerWhaterOrganization = null,
float $coins
): WalletOperation {
if ($buyerUser == null && $buyerWhaterOrganization == null) {
throw new InvalidWalletOperationTypeException();
}
if ($buyerUser != null && $buyerWhaterOrganization != null) {
throw new InvalidWalletOperationTypeException();
}
if ($buyerUser != null) {
$buyerUserCoins = -$coins;
$buyerWhaterOrganizarionCoins = 0;
} else if ($buyerWhaterOrganization != null) {
$buyerUserCoins = 0;
$buyerWhaterOrganizarionCoins = -$coins;
}
$walletOperation = new WalletOperation(
null,
$operationDate,
WalletOperation::WOT_PURCHASE_PRODUCT_WITH_COINS,
$buyerUser,
$buyerWhaterOrganization,
null,
0,
0,
0,
0,
0,
WalletOperation::WO_CURRENCY_EURO,
$buyerUserCoins,
$buyerWhaterOrganizarionCoins,
0,
$coins
);
return $walletOperation;
}
public static function buildOperationForRefundsOfProductsWithMoney(
\DateTime $operationDate,
User $buyerUser = null,
WhaterOrganization $buyerWhaterOrganization = null,
WhaterOrganization $sellerWhaterOrganization = null,
float $money,
float $sellerMoney,
float $stripeCommisionMoney,
float $whaterAppCommisionMoney,
string $currency
): WalletOperation {
if ($buyerUser == null && $buyerWhaterOrganization == null) {
throw new InvalidWalletOperationTypeException();
}
if ($buyerUser != null && $buyerWhaterOrganization != null) {
throw new InvalidWalletOperationTypeException();
}
if ($money != $sellerMoney) {
throw new InvalidWalletOperationTypeException();
}
if ($buyerUser != null) {
$buyerUserMoney = $money;
$buyerWhaterOrganizarionMoney = 0;
} else if ($buyerWhaterOrganization != null) {
$buyerUserMoney = 0;
$buyerWhaterOrganizarionMoney = $money;
}
$walletOperation = new WalletOperation(
null,
$operationDate,
WalletOperation::WOT_REFUND_PRODUCT_WITH_MONEY,
$buyerUser,
$buyerWhaterOrganization,
$sellerWhaterOrganization,
$buyerUserMoney,
$buyerWhaterOrganizarionMoney,
-$sellerMoney,
$whaterAppCommisionMoney,
$stripeCommisionMoney,
$currency,
0,
0,
0,
0
);
return $walletOperation;
}
public static function buildOperationForRefundsOfProductsWithCoins(
\DateTime $operationDate,
User $buyerUser = null,
WhaterOrganization $buyerWhaterOrganization = null,
WhaterOrganization $sellerWhaterOrganization,
float $coins
): WalletOperation {
if ($buyerUser == null && $buyerWhaterOrganization == null) {
throw new InvalidWalletOperationTypeException();
}
if ($buyerUser != null && $buyerWhaterOrganization != null) {
throw new InvalidWalletOperationTypeException();
}
if ($buyerUser != null) {
$buyerUserCoins = $coins;
$buyerWhaterOrganizarionCoins = 0;
} else if ($buyerWhaterOrganization != null) {
$buyerUserCoins = 0;
$buyerWhaterOrganizarionCoins = $coins;
}
if ($sellerWhaterOrganization == null) {
throw new InvalidWalletOperationTypeException();
}
$walletOperation = new WalletOperation(
null,
$operationDate,
WalletOperation::WOT_REFUND_PRODUCT_WITH_COINS,
$buyerUser,
$buyerWhaterOrganization,
$sellerWhaterOrganization,
0,
0,
0,
0,
0,
WalletOperation::WO_CURRENCY_EURO,
$buyerUserCoins,
$buyerWhaterOrganizarionCoins,
-$coins,
0
);
return $walletOperation;
}
public static function buildOperationForTransferCoins(
\DateTime $operationDate,
User $targetUser,
WhaterOrganization $sourceWhaterOrganization,
float $coins
): WalletOperation {
$walletOperation = new WalletOperation(
null,
$operationDate,
WalletOperation::WOT_TRANSFER_COINS,
$targetUser,
null,
$sourceWhaterOrganization,
0,
0,
0,
0,
0,
WalletOperation::WO_CURRENCY_EURO,
$coins,
0,
-$coins,
0
);
return $walletOperation;
}
public function updateNotes(
string $privateNote = null,
string $publicNote = null
) {
$this->privateNote = $privateNote;
$this->publicNote = $publicNote;
return $this;
}
public function checkWalletOperationChecksum(): bool
{
// Calculate checksum
$operationDate = clone $this->operationDate();
$operationDate->setTimezone(new \DateTimeZone('UTC'));
$hash = md5($operationDate->format('dmYHis'));
$hash = md5($hash . $this->walletOperationType());
if ($this->buyerUser != null) {
$hash = md5($hash . $this->buyerUser->id());
}
if ($this->buyerWhaterOrganization != null) {
$hash = md5($hash . $this->buyerWhaterOrganization->id());
}
if ($this->sellerWhaterOrganization != null) {
$hash = md5($hash . $this->sellerWhaterOrganization->id());
}
if ($hash == $this->checksum) {
return true;
}
return false;
}
/**
* @return string
*/
public function id(): string
{
return $this->uuid;
}
/**
* @return User
*/
public function buyerUser(): ?User
{
return $this->buyerUser;
}
/**
* @return WhaterOrganization
*/
public function buyerWhaterOrganization(): ?WhaterOrganization
{
return $this->buyerWhaterOrganization;
}
/**
* @return WhaterOrganization
*/
public function sellerWhaterOrganization(): ?WhaterOrganization
{
return $this->sellerWhaterOrganization;
}
/**
* @return \DateTime
*/
public function operationDate(): \DateTime
{
return $this->operationDate;
}
/**
* @return string
*/
public function walletOperationType(): string
{
return $this->walletOperationType;
}
/**
* @return float
*/
public function buyerUserMoney(): ?float
{
return $this->buyerUserMoney;
}
/**
* @return float
*/
public function buyerWhaterOrganizationMoney(): ?float
{
return $this->buyerWhaterOrganizationMoney;
}
/**
* @return float
*/
public function sellerWhaterOrganizationMoney(): ?float
{
return $this->sellerWhaterOrganizationMoney;
}
/**
* @return float
*/
public function whaterAppMoney(): ?float
{
return $this->whaterAppMoney;
}
/**
* @return float
*/
public function stripeCommisionMoney(): ?float
{
return $this->stripeCommisionMoney;
}
/**
* @return float
*/
public function buyerUserCoins(): ?float
{
return $this->buyerUserCoins;
}
/**
* @return float
*/
public function buyerWhaterOrganizationCoins(): ?float
{
return $this->buyerWhaterOrganizationCoins;
}
/**
* @return float
*/
public function sellerWhaterOrganizationCoins(): ?float
{
return $this->sellerWhaterOrganizationCoins;
}
/**
* @return float
*/
public function whaterAppCoins(): ?float
{
return $this->whaterAppCoins;
}
/**
* @return string
*/
public function currency(): string
{
return $this->currency;
}
/**
* @return string
*/
public function checksum(): string
{
return $this->checksum;
}
/**
* @return string
*/
public function privateNote(): ?string
{
return $this->privateNote;
}
/**
* @return string
*/
public function publicNote(): ?string
{
return $this->publicNote;
}
/**
* @return \DateTime
*/
public function createdAt(): \DateTime
{
return $this->createdAt;
}
/**
* @return WalletLiquidationRequest
*/
public function walletLiquidationRequest(): ?WalletLiquidationRequest
{
return $this->walletLiquidationRequest;
}
}