<?php
namespace AppBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use JMS\Serializer\Annotation as Serializer;
use DateTime;
/**
* @ORM\Entity(repositoryClass="AppBundle\Entity\Repository\RecurringClaimRepository")
* @ORM\Table(name="recurringclaim")
* @Serializer\ExclusionPolicy("all")
*/
class RecurringClaim extends AbstractEntity
{
const CLAIM_TYPE = 'recurring';
const STATUS_PENDING = 'pending';
const STATUS_ATTENTION = 'attention';
const STATUS_APPROVED = 'approved';
const STATUS_REJECTED = 'rejected';
const STATUS_CLOSED = 'closed'; // Alternative rejection. Possible TODO: consider actual status rejected, and separate into a sub-status field
const STATUS_CANCELED = 'canceled';
// Recurring frequency is defined in terms of the period
const FREQUENCY_WEEKLY = '1 week';
const FREQUENCY_BIWEEKLY = '2 week';
const FREQUENCY_SEMIMONTHLY = '.5 month';
const FREQUENCY_MONTHLY = '1 month';
const FREQUENCY_QUARTERLY = '3 month';
const FREQUENCY_SEMIANNUALLY = '6 month';
const FREQUENCY_ANNUALLY = '12 month';
// Irregular frequency requiring manual one-time claim creation
const FREQUENCY_MANUAL = 'manual';
const START_NOW = 'Now';
const START_LATER = 'Later';
const APPROVAL_AUTOMATIC = 'automatic';
const APPROVAL_WITH_ATTESTATION = 'attest';
const APPROVAL_WITH_COVERAGE = 'coverage';
protected static $allStatuses = array(
self::STATUS_PENDING,
self::STATUS_ATTENTION,
self::STATUS_APPROVED,
self::STATUS_REJECTED,
self::STATUS_CLOSED,
self::STATUS_CANCELED
);
protected static $allFrequencies = array(
self::FREQUENCY_WEEKLY,
self::FREQUENCY_BIWEEKLY,
self::FREQUENCY_SEMIMONTHLY,
self::FREQUENCY_MONTHLY,
self::FREQUENCY_QUARTERLY,
self::FREQUENCY_SEMIANNUALLY,
self::FREQUENCY_ANNUALLY,
self::FREQUENCY_MANUAL
);
/**
* @var int
* @ORM\Column(type="integer", name="RecurringClaimId")
* @ORM\Id
* @ORM\GeneratedValue
*/
protected $id;
/**
* @var Participant
* @ORM\ManyToOne(targetEntity="Participant")
* @ORM\JoinColumn(name="ParticipantId", referencedColumnName="ParticipantId")
* @Serializer\Expose
* @Serializer\Groups({"mainRecurring"})
*/
protected $participant;
/**
* @var ParticipantPolicy
* @ORM\ManyToOne(targetEntity="ParticipantPolicy")
* @ORM\JoinColumn(name="PolicyId", referencedColumnName="Id")
* @Serializer\Expose
* @Serializer\Groups({"details"})
*/
protected $policy;
/**
* @var RecurringClaimReview
* @ORM\OneToOne(targetEntity="RecurringClaimReview", mappedBy="recurringClaim")
* @Serializer\Expose
* @Serializer\Groups({"supervisor"})
*/
protected $review;
/**
* @var RecurringClaim
* @ORM\OneToOne(targetEntity="RecurringClaim")
* @ORM\JoinColumn(name="ReplacesClaimId", referencedColumnName="RecurringClaimId")
* @Serializer\Expose
* @Serializer\Groups({"supervisor"})
*/
protected $replacesClaim;
/**
* @var Collection
* @ORM\OneToMany(targetEntity="ClaimDocument", mappedBy="recurringClaim")
* @Serializer\Expose
*/
protected $documents;
/**
* @var Collection
* @ORM\OneToMany(targetEntity="Claim", mappedBy="recurringClaim")
*/
protected $claims;
/**
* @var DateTime
* @ORM\Column(type="datetime", name="Approved")
*/
protected $dateApproved;
/**
* @var DateTime
* @ORM\Column(type="datetime", name="Rejected")
*/
protected $dateRejected;
/**
* @var DateTime
* @ORM\Column(type="datetime", name="Canceled")
*/
protected $dateCanceled;
/**
* @todo There should be no need for a serialized array here, but for now there is
* @var array
* @ORM\Column(type="array", name="ClaimInfo")
*/
protected $claimInfo = array(
'SubmittedByDependentId' => '',
'ParticipantNote' => '',
'SupervisorNote' => '',
'SupervisorPrivateNote' => '',
'Receipt' => '',
'ReceiptLocation' => '',
'ClaimType' => 'Health Insurance Premium',
'ReceiptImageType' => '',
'IsHSA' => 0,
'DateOfService' => null,
'EndDateOfService' => null,
'OriginalAmount' => 0,
'ProviderOfService' => '',
'RecipientOfService' => '',
'RecipientDependentId' => '',
'EnteredBySupervisor' => '',
'POPFullPolicyAmount' => 0,
'StartDate' => null,
'StartDateOption' => self::START_NOW,
'EndDate' => null
);
/**
* @var string
* @ORM\Column(type="string", name="Status", length=9)
* @Serializer\Expose
*/
protected $status = self::STATUS_PENDING;
/**
* @var string
* @ORM\Column(type="string", name="Period")
* @Serializer\Expose
*/
protected $period;
/**
* @var int
* @ORM\Column(type="integer", name="Level")
* @Serializer\Expose
*/
protected $level = 1;
/**
* @var DateTime
* @ORM\Column(type="datetime", name="DateOfNextStep", nullable=true)
* @Serializer\Expose
*/
protected $dateOfNextStep;
/**
* @var DateTime
* @ORM\Column(type="datetime", name="CreationDate")
* @Serializer\Expose
* @Serializer\SerializedName("dateCreated")
*/
protected $dateCreated;
/**
* @var DateTime
* @ORM\Column(type="datetime", name="LastModified", nullable=true)
* @Serializer\Expose
*/
protected $dateLastModified;
/**
* @var Supervisor
* @ORM\ManyToOne(targetEntity="Supervisor")
* @ORM\JoinColumn(name="LastModifiedBySupervisorId", referencedColumnName="SupervisorId")
* @Serializer\Expose
* @Serializer\Groups({"details"})
*/
protected $lastModifiedBySupervisor;
/**
* @var Supervisor
* @ORM\ManyToOne(targetEntity="Supervisor")
* @ORM\JoinColumn(name="ProcessedSupervisorId", referencedColumnName="SupervisorId")
* @Serializer\Expose
* @Serializer\Groups({"details"})
*/
protected $processedBySupervisor;
/**
* @var bool
* @ORM\Column(type="boolean", name="ApproveFirstClaim")
*/
protected $approveFirstClaim = true;
protected $dateOfService;
public function __construct()
{
$this->documents = new ArrayCollection();
$this->claims = new ArrayCollection();
$this->dateCreated = new DateTime();
}
/**
* @return string
* @Serializer\VirtualProperty
*/
public function getClaimType()
{
return self::CLAIM_TYPE;
}
/**
* @param Participant $participant
* @return self
*/
public function setParticipant(Participant $participant)
{
$this->participant = $participant;
return $this;
}
/**
* @return Participant
*/
public function getParticipant()
{
return $this->participant;
}
/**
* @return ParticipantPolicy
*
*/
public function getPolicy()
{
return $this->policy;
}
/**
* @param ParticipantPolicy $policy
* @return self
*/
public function setPolicy(ParticipantPolicy $policy = null)
{
$this->policy = $policy;
return $this;
}
/**
* @return RecurringClaimReview
*/
public function getReview()
{
return $this->review;
}
/**
* @param RecurringClaimReview $review
* @return self
*/
public function setReview(RecurringClaimReview $review = null)
{
$this->review = $review;
// Ensure two-way relationship
if ($review && $review->getRecurringClaim() !== $this) {
$review->setRecurringClaim($this);
}
return $this;
}
/**
* @return ClaimDocument[]
*/
public function getDocuments()
{
return $this->documents->toArray();
}
/**
* @return string
*/
public function getStatus()
{
return $this->status;
}
/**
* @param string $new
* @return self
*/
public function setStatus($new)
{
if (!in_array($new, self::$allStatuses, true)) {
throw new \InvalidArgumentException("Invalid status: '$new'");
}
$this->status = $new;
return $this;
}
/**
* @Serializer\VirtualProperty
* @Serializer\SerializedName("approvedAmount")
* @return float
*/
public function getApprovedAmount()
{
return $this->claimInfo['OriginalAmount'];
}
/**
* @param float $new
* @return self
*/
public function setApprovedAmount($new)
{
$this->claimInfo['OriginalAmount'] = $new;
return $this;
}
/**
* @Assert\GreaterThan(value=0)
* @Serializer\VirtualProperty
* @Serializer\SerializedName("originalAmount")
* @return float
*/
public function getOriginalAmount()
{
return $this->claimInfo['OriginalAmount'];
}
/**
* @param float $new
* @return self
*/
public function setOriginalAmount($new)
{
$this->claimInfo['OriginalAmount'] = $new;
return $this;
}
/**
* @Serializer\VirtualProperty
* @return float
*/
public function getPremiumAmount()
{
return $this->claimInfo['POPFullPolicyAmount'];
}
/**
* @param float $new
* @return self
*/
public function setPremiumAmount($new)
{
$this->claimInfo['POPFullPolicyAmount'] = $new;
return $this;
}
/**
* @Serializer\VirtualProperty
* @Serializer\SerializedName("recipientDependentId")
* @return int
*/
public function getRecipientDependentId()
{
return $this->claimInfo['RecipientDependentId'];
}
/**
* @return Participant|Dependent
*/
public function getRecipient()
{
$dependentId = $this->claimInfo['RecipientDependentId'];
if ($dependentId) {
foreach ($this->getParticipant()->getDependents() as $dependent) {
if ($dependent->getId() === $dependentId) {
return $dependent;
}
}
}
return $this->participant;
}
/**
* @param Participant|Dependent $recipient
* @return self
*/
public function setRecipient($recipient)
{
if ($recipient instanceof Dependent) {
$this->claimInfo['RecipientDependentId'] = $recipient->getId();
}
else {
$this->claimInfo['RecipientDependentId'] = 0;
}
$this->claimInfo['RecipientOfService'] = $recipient->getFirstName() . ' ' . $recipient->getLastName();
return $this;
}
/**
* @Serializer\VirtualProperty
* @Serializer\SerializedName("participantNote")
* @return string
*/
public function getParticipantNote()
{
return $this->claimInfo['ParticipantNote'];
}
/**
* @param string $new
* @return self
*/
public function setParticipantNote($new)
{
$this->claimInfo['ParticipantNote'] = $new;
return $this;
}
/**
* @Serializer\VirtualProperty
* @Serializer\SerializedName("supervisorNote")
* @return string
*/
public function getSupervisorNote()
{
return $this->getClaimInfoIndex('SupervisorNote');
}
/**
* @param string $new
* @return self
*/
public function setSupervisorNote($new)
{
$this->claimInfo['SupervisorNote'] = $new;
return $this;
}
/**
* @Serializer\VirtualProperty
* @Serializer\Groups({"supervisor"})
* @return string
*/
public function getSupervisorPrivateNote()
{
return $this->getClaimInfoIndex('SupervisorPrivateNote');
}
/**
* @param string $new
* @return self
*/
public function setSupervisorPrivateNote($new)
{
$this->claimInfo['SupervisorPrivateNote'] = $new;
return $this;
}
/**
* @Serializer\VirtualProperty
* @Assert\NotBlank
* @Serializer\SerializedName("providerName")
* @return string
*
*/
public function getProviderName()
{
return $this->claimInfo['ProviderOfService'];
}
/**
* @param string $new
* @return self
*/
public function setProviderName($new)
{
$this->claimInfo['ProviderOfService'] = $new;
return $this;
}
/**
* @Assert\NotBlank
* @return string
*/
public function getPeriod()
{
return $this->period;
}
/**
* @param string $new
* @return self
*/
public function setPeriod($new)
{
if (!in_array($new, self::$allFrequencies, true)) {
throw new \InvalidArgumentException("Invalid period '$new'");
}
$this->period = $new;
return $this;
}
/**
* @Assert\NotBlank
* @Serializer\VirtualProperty
* @Serializer\Type("DateTime<'Y-m-d'>")
* @Serializer\SerializedName("startDate")
* @return DateTime
*/
public function getStartDate()
{
return $this->claimInfo['StartDate'] ? new DateTime($this->claimInfo['StartDate']) : null;
}
/**
* @param DateTime $date
* @return self
*/
public function setStartDate(DateTime $date = null)
{
$this->claimInfo['StartDate'] = $date ? $date->format('Y-m-d') : null;
return $this;
}
/**
* @Serializer\VirtualProperty
* @return string
*/
public function getStartDateOption()
{
return $this->claimInfo['StartDateOption'];
}
/**
* @Serializer\VirtualProperty
* @Serializer\Type("DateTime<'Y-m-d'>")
* @return DateTime|null
*/
public function getEndDate()
{
$endDate = $this->getClaimInfoIndex('EndDate');
if ($endDate) {
return new DateTime($endDate);
}
return null;
}
/**
* @param DateTime $date
* @return self
*/
public function setEndDate(DateTime $date = null)
{
$this->claimInfo['EndDate'] = $date ? $date->format('Y-m-d') : null;
return $this;
}
/**
* @param string $new
* @return self
*/
public function setStartDateOption($new)
{
if ($new !== self::START_NOW && $new !== self::START_LATER) {
throw new \InvalidArgumentException('Invalid start date option');
}
$this->claimInfo['StartDateOption'] = $new;
return $this;
}
/**
* @Assert\NotBlank
* @Serializer\VirtualProperty
* @Serializer\Type("DateTime<'Y-m-d'>")
* @Serializer\SerializedName("dateOfService")
* @return DateTime
*/
public function getDateOfService()
{
return $this->claimInfo['DateOfService'] ? new DateTime($this->claimInfo['DateOfService']) : null;
}
/**
* @param DateTime $date
* @return self
*/
public function setDateOfService(DateTime $date = null)
{
$this->claimInfo['DateOfService'] = $date ? $date->format('Y-m-d') : null;
return $this;
}
/**
* @Serializer\VirtualProperty
* @Serializer\Type("DateTime<'Y-m-d'>")
* @return DateTime
*/
public function getEndDateOfService()
{
return empty($this->claimInfo['EndDateOfService']) ? null : new DateTime($this->claimInfo['EndDateOfService']);
}
/**
* @param DateTime $date
* @return self
*/
public function setEndDateOfService(DateTime $date = null)
{
$this->claimInfo['EndDateOfService'] = $date ? $date->format('Y-m-d') : null;
return $this;
}
/**
* @param ClaimDocument $document
* @return self
*/
public function addDocument(ClaimDocument $document)
{
$this->documents->add($document);
return $this;
}
/**
* @param ClaimDocument $document
* @return self
*/
public function removeDocument(ClaimDocument $document)
{
$this->documents->removeElement($document);
return $this;
}
/**
* @param string $imageId
* @return ClaimDocument|null
*/
public function getDocumentByImageId($imageId)
{
foreach ($this->documents as $doc) {
if ($doc->getImageId() === $imageId) {
return $doc;
}
}
return null;
}
/**
* @return RecurringClaim
*/
public function getReplacesClaim()
{
return $this->replacesClaim;
}
/**
* @param RecurringClaim $claim
* @return $this
*/
public function setReplacesClaim(RecurringClaim $claim=null)
{
$this->replacesClaim = $claim;
return $this;
}
/**
* @param User $user
* @return self
*/
public function setSubmittedBy(User $user)
{
$this->claimInfo['SubmittedByDependentId'] = $user instanceof Dependent ? $user->getId() : 0;
return $this;
}
/**
* @Serializer\VirtualProperty
* @Assert\NotBlank
* @return string
*/
public function getReceiptLocation()
{
return $this->claimInfo['ReceiptLocation'];
}
/**
* @param string $new
* @return self
*/
public function setReceiptLocation($new)
{
$this->claimInfo['ReceiptLocation'] = $new;
return $this;
}
/**
* @Serializer\VirtualProperty
* @Assert\NotBlank
* @Serializer\SerializedName("natureOfExpense")
* @return string
*/
public function getNatureOfExpense()
{
return $this->claimInfo['ClaimType'];
}
/**
* @param Claim $claim
* @return self
*/
public function addClaim(Claim $claim)
{
$this->claims->add($claim);
return $this;
}
/**
* @return Claim[]
*/
public function getClaims()
{
return $this->claims->toArray();
}
/**
* @return Claim|null
*/
public function getMostRecentClaim()
{
$mostRecent = null;
foreach ($this->claims as $claim) {
if (!$mostRecent || $claim->getDateOfService() > $mostRecent->getDateOfService()) {
$mostRecent = $claim;
}
}
return $mostRecent;
}
/**
* @return bool
*/
public function isAppliedToHSA()
{
return (bool) $this->claimInfo['IsHSA'];
}
/**
* @param bool $new
* @return self
*/
public function setIsAppliedToHSA($new)
{
$this->claimInfo['IsHSA'] = $new ? 1 : 0;
return $this;
}
/**
* @return int
*/
public function getLevel()
{
return $this->level;
}
/**
* @param int $level
* @return self
*/
public function setLevel($level)
{
$this->level = $level;
return $this;
}
/**
* @Serializer\SerializedName("dateCreated")
* @return DateTime
*/
public function getDateCreated()
{
return $this->dateCreated;
}
/**
* @return bool
*/
public function isApproved()
{
return (bool) $this->dateApproved;
}
/**
* @return bool
*/
public function isRejected()
{
return (bool) $this->dateRejected;
}
/**
* @return bool
*/
public function isCanceled()
{
return (bool) $this->dateCanceled;
}
/**
* @return bool
*/
public function isFinal()
{
return $this->dateApproved || $this->dateRejected || $this->dateCanceled;
}
/**
* @return DateTime
*/
public function getDateOfNextStep()
{
return $this->dateOfNextStep;
}
/**
* @param DateTime $dateOfNextStep
* @return self
*/
public function setDateOfNextStep(DateTime $dateOfNextStep = null)
{
$this->dateOfNextStep = $dateOfNextStep;
return $this;
}
/**
* @return DateTime
*/
public function getDateApproved()
{
return $this->dateApproved;
}
/**
* @param DateTime $dateApproved
* @return $this
*/
public function setDateApproved(DateTime $dateApproved = null)
{
$this->dateApproved = $dateApproved;
return $this;
}
/**
* @return DateTime
*/
public function getDateRejected()
{
return $this->dateRejected;
}
/**
* @param DateTime $dateRejected
* @return $this
*/
public function setDateRejected(DateTime $dateRejected = null)
{
$this->dateRejected = $dateRejected;
return $this;
}
/**
* @return DateTime
*/
public function getDateCanceled()
{
return $this->dateCanceled;
}
/**
* @param DateTime $dateCanceled
* @return $this
*/
public function setDateCanceled(DateTime $dateCanceled = null)
{
$this->dateCanceled = $dateCanceled;
return $this;
}
/**
* @return bool
*/
public function getApproveFirstClaim()
{
return $this->approveFirstClaim;
}
/**
* @param bool $value
* @return $this
*/
public function setApproveFirstClaim($value)
{
$this->approveFirstClaim = (bool) $value;
return $this;
}
/**
* @param string $index
* @return mixed
*/
protected function getClaimInfoIndex($index)
{
return array_key_exists($index, $this->claimInfo) ? $this->claimInfo[$index] : null;
}
}