<?php
/**
* Created by simpson <simpsonwork@gmail.com>
* Date: 2019-06-27
* Time: 11:00
*/
namespace App\Entity\Sales;
use App\Entity\Management\StaffAccount;
use App\Entity\User;
use App\Repository\AccountEnrollmentRepository;
use Doctrine\ORM\Mapping as ORM;
use Money\Currency;
use Money\Money;
/**
* Пополнение счета аккаунта (погашение купленных кодов)
*/
#[ORM\Table(name: 'account_enrollments')]
#[ORM\Entity(repositoryClass: AccountEnrollmentRepository::class)]
class AccountEnrollment
{
#[ORM\Id]
#[ORM\Column(name: 'id', type: 'integer')]
#[ORM\GeneratedValue(strategy: 'AUTO')]
protected int $id;
#[ORM\JoinColumn(name: 'account_id', referencedColumnName: 'id')]
#[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'enrollments')]
protected User $account;
/**
* Аккаунт оператора, совершившего начисление вручную
*/
#[ORM\JoinColumn(name: 'staff_account_id', referencedColumnName: 'id')]
#[ORM\ManyToOne(targetEntity: StaffAccount::class)]
protected ?StaffAccount $enrolledBy;
#[ORM\Column(name: 'operation_id', type: 'string', length: 64, nullable: true)]
protected ?string $operationId;
#[ORM\JoinColumn(name: 'payment_product_id', referencedColumnName: 'id')]
#[ORM\ManyToOne(targetEntity: PaymentProduct::class)]
protected ?PaymentProduct $paidProduct;
/**
* Фактическая сумма платежа
*/
#[ORM\Column(name: 'paid_amount', type: 'integer')]
protected string $paidAmount;
/**
* Начисленная на счет юзера сумма (вместе с бонусной частью)
*/
#[ORM\Column(name: 'enrolled_amount', type: 'integer')]
protected string $enrolledAmount;
#[ORM\Column(name: 'currency', type: 'string', length: 3)]
protected string $currency;
#[ORM\Column(name: 'date', type: 'datetimetz_immutable')]
protected \DateTimeImmutable $date;
#[ORM\Column(name: 'redeemed_token', type: 'string', length: 64, nullable: true)]
protected ?string $redeemedToken;
#[ORM\OneToOne(targetEntity: AccountTransaction::class, mappedBy: 'enrollment', cascade: ['all'])]
protected AccountTransaction $transaction;
#[ORM\Column(type: 'json', nullable: true)]
protected ?array $params = null;
public static function enrollPaidValueByStaff(StaffAccount $staff, User $account, Money $enrolledMoney, \DateTimeImmutable $date): self
{
$enrollment = new static($account, $enrolledMoney, $enrolledMoney, $date);
$enrollment->enrolledBy = $staff;
return $enrollment;
}
/**
* Начисление компенсаций и вознаграждений админами (без реального платежа)
*/
public static function enrollBonusValueByStaff(StaffAccount $staff, User $account, Money $enrolledMoney, \DateTimeImmutable $date): self
{
$enrollment = new static($account, null, $enrolledMoney, $date);
$enrollment->enrolledBy = $staff;
return $enrollment;
}
public static function enrollPaidValue(User $account, Money $paidValue, Money $enrolledMoney, \DateTimeImmutable $date, string $operationId): self
{
$enrollment = new static($account, $paidValue, $enrolledMoney, $date);
$enrollment->operationId = $operationId;
return $enrollment;
}
public static function enrollWithPrepaidToken(PaymentProduct $paymentProduct, User $account, Money $paidMoney, Money $enrolledMoney, \DateTimeImmutable $date, string $operationId, string $redeemedToken, ?StaffAccount $staffAccount = null): self
{
$enrollment = new static($account, $paidMoney, $enrolledMoney, $date);
$enrollment->paidProduct = $paymentProduct;
$enrollment->operationId = $operationId;
$enrollment->redeemedToken = $redeemedToken;
$enrollment->enrolledBy = $staffAccount;
return $enrollment;
}
/**
* Начисление бонуса по промо-коду (без реального платежа)
*/
public static function enrollWithCustomToken(User $account, Money $enrolledMoney, \DateTimeImmutable $date, string $redeemedToken, ?array $params): self
{
$enrollment = new static($account, null, $enrolledMoney, $date);
$enrollment->redeemedToken = $redeemedToken;
$enrollment->params = $params;
return $enrollment;
}
protected function __construct(User $account, ?Money $paidMoney, Money $enrolledMoney, \DateTimeImmutable $date)
{
if (null !== $paidMoney && !$enrolledMoney->isSameCurrency($paidMoney)) {
throw new \LogicException('Currency mismatch between paid and enrolled amounts.');
}
$this->account = $account;
$this->paidAmount = $paidMoney?->getAmount() ?: '0';
$this->enrolledAmount = $enrolledMoney->getAmount();
$this->currency = $enrolledMoney->getCurrency()->getCode();
$this->date = $date;
$this->transaction = AccountTransaction::fromEnrollment($this);
}
public function getId(): int
{
return $this->id;
}
public function getEnrolledBy(): ?StaffAccount
{
return $this->enrolledBy;
}
public function getEnrolledByDescription(): ?string
{
if (null !== $this->enrolledBy) {
return $this->enrolledBy->getEmail();
}
if (null !== $this->paidProduct) {
return 'Digiseller';
}
if ($this->paidAmount > 0) {
return 'BetaTransfer';
}
if (null !== $this->redeemedToken) {
return 'Bonus';
}
return null;
}
public function getAccount(): User
{
return $this->account;
}
public function getOperationId(): ?string
{
return $this->operationId;
}
public function getPaidProduct(): ?PaymentProduct
{
return $this->paidProduct;
}
public function getPaidMoney(): Money
{
return new Money($this->paidAmount, new Currency($this->currency));
}
public function getEnrolledMoney(): Money
{
return new Money($this->enrolledAmount, new Currency($this->currency));
}
public function getDate(): \DateTimeImmutable
{
return $this->date;
}
public function getRedeemedToken(): ?string
{
return $this->redeemedToken;
}
public function getTransaction(): AccountTransaction
{
return $this->transaction;
}
public function getParams(): ?array
{
return $this->params;
}
}