PaymentRequest.php

PHOTO EMBED

Tue Oct 04 2022 17:06:33 GMT+0000 (Coordinated Universal Time)

Saved by @igor #drupal #mysql

<?php

namespace Drupal\cfp_payment_request\Entity;

use Drupal\cfp_payment_request\Event\PRTransitionEvent;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityChangedTrait;
use Drupal\Core\Entity\EntityPublishedTrait;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface;
use Drupal\halo_closable_entity\Entity\ClosableEntityTrait;
use Drupal\halo_entity_cfp\Entity\Cfp;
use Drupal\halo_entity_validator\Entity\HaloEntityValidationTrait;
use Drupal\halo_parent_entity\Entity\ChildEntityTrait;
use Drupal\halo_printer\Entity\HaloPrintableEntityTrait;
use Drupal\halo_printer\Entity\PrintTokenEntityInterface;
use Drupal\halo_transition_history_field\Plugin\Field\TransitionDateSearchItemList;
use Drupal\user\UserInterface;
use Drupal\halo_entity_cfp\Entity\CfpPaymentInterface;

/**
 * Defines the Payment request entity.
 *
 * @ingroup cfp_payment_request
 *
 * @ContentEntityType(
 *   id = "cfp_payment_request",
 *   label = @Translation("Payment request"),
 *   bundle_label = @Translation("Payment request type"),
 *   handlers = {
 *     "view_builder" = "Drupal\cfp_payment_request\PaymentRequestEntityViewBuilder",
 *     "list_builder" = "Drupal\cfp_payment_request\PaymentRequestListBuilder",
 *     "views_data" = "Drupal\cfp_payment_request\Entity\PaymentRequestViewsData",
 *
 *     "form" = {
 *       "default" = "Drupal\cfp_payment_request\Form\PaymentRequestForm",
 *       "add" = "Drupal\cfp_payment_request\Form\PaymentRequestForm",
 *       "edit" = "Drupal\cfp_payment_request\Form\PaymentRequestForm",
 *       "delete" = "Drupal\cfp_payment_request\Form\PaymentRequestDeleteForm",
 *       "suspended_documents" = "\Drupal\cfp_payment_request\Form\PaymentRequestSuspendedDocumentsForm",
 *     },
 *     "route_provider" = {
 *       "html" = "Drupal\cfp_payment_request\PaymentRequestHtmlRouteProvider",
 *     },
 *     "access" = "Drupal\cfp_payment_request\PaymentRequestAccessControlHandler",
 *   },
 *   base_table = "cfp_payment_request",
 *   translatable = FALSE,
 *   admin_permission = "administer payment request entities",
 *   entity_keys = {
 *     "id" = "id",
 *     "bundle" = "type",
 *     "label" = "name",
 *     "uuid" = "uuid",
 *     "uid" = "user_id",
 *     "langcode" = "langcode",
 *     "published" = "status",
 *   },
 *   links = {
 *     "canonical" = "/admin/structure/cfp_payment_request/{cfp_payment_request}",
 *     "add-page" = "/admin/structure/cfp_payment_request/add",
 *     "add-form" = "/admin/structure/cfp_payment_request/add/{cfp_payment_request_type}",
 *     "edit-form" = "/admin/structure/cfp_payment_request/{cfp_payment_request}/edit",
 *     "current-correction-form" = "/admin/structure/cfp_payment_request/{cfp_payment_request}/correction",
 *     "correction-submit-form" = "/admin/structure/cfp_payment_request/{cfp_payment_request}/correction_submit",
 *     "delete-form" = "/admin/structure/cfp_payment_request/{cfp_payment_request}/delete",
 *     "collection" = "/admin/structure/cfp_payment_request",
 *     "admin-view" = "/admin/structure/cfp_payment_request/{cfp_payment_request}/admin_view",
 *     "suspended-documents" = "/cfp_payment_request/{cfp_payment_request}/suspended_documents",
 *     "suspended-documents-submit" = "/cfp_payment_request/{cfp_payment_request}/suspended_documents_submit"
 *   },
 *   bundle_entity_type = "cfp_payment_request_type",
 *   field_ui_base_route = "entity.cfp_payment_request_type.edit_form"
 * )
 */
class PaymentRequest extends ContentEntityBase implements PaymentRequestInterface, CfpPaymentInterface, PrintTokenEntityInterface {

  use EntityChangedTrait;
  use EntityPublishedTrait;
  use HaloEntityValidationTrait;
  use ClosableEntityTrait;
  use HaloPrintableEntityTrait;
  use ChildEntityTrait;

  const ADD_UP_FIELDS = [
    'item_pay_off',
    'item_support',
    'item_pay_off_computed',
    'item_support_computed',
    'item_net_amount',
    'item_vat',
    'item_bruto',
    'item_own_source',
  ];

  /**
   * {@inheritdoc}
   */
  public static function preCreate(EntityStorageInterface $storage_controller, array &$values) {
    parent::preCreate($storage_controller, $values);
    $values += [
      'user_id' => \Drupal::currentUser()->id(),
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function getName() {
    return $this->get('label')->value;
  }

  /**
   * {@inheritdoc}
   * @todo Refactor this in more functions.
   */
  public function preSave(EntityStorageInterface $storage) {
    parent::preSave($storage);
    /** @var \Drupal\cfp_payment_request\Entity\PaymentRequestType $payment_request_type */
    $payment_request_type = $this->get('type')->entity;
    $clear_reopen_instructions = FALSE;
    if (!$this->isNew()) {
      // On opening payment request.
      if ($this->getState() === 'open_state' && $this->getState() !== $this->original->getState()) {
        $this->set('validation_passed', FALSE);
        $this->set('closed', FALSE);
        $this->set('print', NULL);
        $this->set('print_confirmed', FALSE);
      }
      // On reopening payment request.
      if ($this->getState() === 'reopened' && $this->getState() !== $this->original->getState()) {
        /** @var \Drupal\file\Entity\File $old_print_file */
        $old_print_file = $this->get('print')->entity;
        if ($old_print_file) {
          $this->get('old_prints')->appendItem([
            'target_id' => $old_print_file->id(),
            'description' => DrupalDateTime::createFromTimestamp($old_print_file->getCreatedTime())->format('Y.m.d.') . ' - print',
          ]);
        }
        $reopen_instructions = $this->get('reopen_instructions')->value ?? '-';
        $this->get('previous_reopen_instructions')->appendItem(['value' => $reopen_instructions]);
        $clear_reopen_instructions = TRUE;
        $this->invalidate()->open()->clearPrintFile()->unconfirmPrint();
      }
      if ($this->isPrintConfirmed() === TRUE && $this->original->isPrintConfirmed() === FALSE) {
        $this->appendChecklist($this->getState() === 'reopened');
        $this->setState('sent');
        if ($this->get('first_submission_date')->isEmpty()) {
          $this->set('first_submission_date', \Drupal::time()->getCurrentTime());
        }
      }
      if (!$this->original->isClosed() && $this->isClosed()) {
        $datetime = new DrupalDateTime();
        $datetime->setTimezone(new \DateTimeZone('UTC'));
        $this->set('closed_date', $datetime->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT));
      }
      if ($this->getState() === 'correction_submitted' &&
        $this->original->getState() === 'correction'
      ) {
        $current_correction = (int) $this->get('current_correction')->value;
        $this->appendChecklist(TRUE);
        $this->set('current_correction', ($current_correction + 1));
      }
      if ($this->getState() === 'deadline_expired' &&
        $this->original->getState() === 'reopened') {
        // This function needs to accept one more optional argument (after_deadline).
        $this->appendChecklist(FALSE, TRUE);
      }
      if (($this->getState() === 'approved' || $this->getState() === 'accepted_with_reduction') && $this->stateHasChangedFromOriginal()) {
        $this->set('date_of_completion', \Drupal::time()->getCurrentTime());
      }
      // Flag that cfp has closing payment request.
      if ($this->stateHasChangedFromOriginal() && $this->hasField('pr_type') && $this->get('pr_type')->value === 'closing') {
        if (in_array($this->getState(), Cfp::getPaidStates())) {
          if ($this->hasParent() && !$this->getParent()->isFlagged('has_closing_payment_request')) {
            $this->getParent()->flag('has_closing_payment_request')->save();
          }
        }
        if (in_array($this->getState(), Cfp::getCompletionStates())) {
          if ($this->hasParent() && !$this->getParent()->isFlagged('has_approved_closing_pr')) {
            $this->getParent()->flag('has_approved_closing_pr')->save();
          }
        }
      }
      if ($this->getState() !== $this->original->getState()) {
        $event = new PRTransitionEvent(
          $this,
          $this->original->getState(),
          $this->getState()
        );
        \Drupal::service('event_dispatcher')->dispatch(PRTransitionEvent::TRANSITION_EVENT, $event);
        $this->appendTransition($this->getState());
        $this->set('correction_deadline', NULL);
      }
      if ($this->stateHasChangedFromOriginal() && in_array($this->getState(), Cfp::getCompletionInvalidationStates())) {
        $this->setAmountDedicatedToAp(NULL);
        $this->set('date_of_completion', NULL);
      }
    }
    if ($this->get('label')->isEmpty() && $this->hasParent()) {
      $parent = $this->getParent();
      $order = $parent->get('payment_request')->count() + 1;
      $this->set('label', $parent->label() . '/' . $payment_request_type->get('order_prefix') . $order);
    }
    if ($this->hasParent()) {
      $this->setOwnerId($this->getParent()->getOwnerId());
    }
    if ($clear_reopen_instructions) {
      $this->set('reopen_instructions', NULL);
    }
    $items = $this->getItems(TRUE);
    $this->calculateTotals($items);
    $this->constructItemLabels($items);
    $this->setInvoiceOrdering();
  }

  /**
   * Calculates totals.
   */
  public function calculateTotals($items = NULL) {
    if (!isset($items)) {
      $items = $this->getItems(TRUE);
    }
    foreach (self::ADD_UP_FIELDS as $add_up_field) {
      $total = 0;
      foreach ($items as $item) {
        $total += $item->get($add_up_field)->value ?? 0;
      }
      $this->set("{$add_up_field}_total", $total);
    }

    if (($this->getState() === 'approved' || $this->getState() === 'accepted_with_reduction') && isset($this->original) && $this->original->getState() !== $this->getState()) {
      /** @var \Drupal\halo_entity_cfp\Entity\Cfp $cfp */
      $cfp = $this->getParent();
      $not_covered_ap = $cfp->getNotCoveredApAmount();
      if ($not_covered_ap > $this->getTotalSupport()) {
        $this->setAmountDedicatedToAp($this->getTotalSupport());
      }
      else {
        $this->setAmountDedicatedToAp($not_covered_ap);
      }
    }
  }

  /**
   * Has state changed since original.
   *
   * @return bool
   *   Has state changed.
   */
  protected function stateHasChangedFromOriginal() {
    if (!isset($this->original)) {
      return FALSE;
    }
    return $this->original->getState() !== $this->getState();
  }

  /**
   * Constructs labels based on order from parent payment request(this entity).
   *
   * @param \Drupal\cfp_payment_request\Entity\PaymentRequestItem[] $items
   *   Payment request items.
   */
  public function constructItemLabels($items) {
    foreach ($items as $delta => $item) {
      $label = $this->label() . '-' . str_pad(($delta + 1), 3, '0', STR_PAD_LEFT);
      if ($item->getName() != $label) {
        $item->setName($label);
        $item->save();
      }
    }
  }

  public function setInvoiceOrdering() {
    foreach ($this->getInvoices() as $order => $invoice) {
      if (((int) ($order + 1)) !== ((int) $invoice->get('invoice_order')->value)) {
        $invoice->set('invoice_order', $order + 1);
        $invoice->save();
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function setName($name) {
    $this->set('label', $name);
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getCreatedTime() {
    return $this->get('created')->value;
  }

  /**
   * {@inheritdoc}
   */
  public function setCreatedTime($timestamp) {
    $this->set('created', $timestamp);
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getOwner() {
    return $this->get('user_id')->entity;
  }

  /**
   * {@inheritdoc}
   */
  public function getOwnerId() {
    return $this->get('user_id')->target_id;
  }

  /**
   * {@inheritdoc}
   */
  public function setOwnerId($uid) {
    $this->set('user_id', $uid);
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function setOwner(UserInterface $account) {
    $this->set('user_id', $account->id());
    return $this;
  }

  /**
   * Item type for this payment request.
   *
   * @return string
   *   Item type for this payment request.
   */
  public function getPaymentRequestItemType() {
    return \Drupal::entityTypeManager()
      ->getStorage('cfp_payment_request_type')
      ->load($this->bundle())
      ->get('payment_request_item_type');
  }

  /**
   * @return \Drupal\cfp_payment_request\Entity\PaymentRequestItem[]
   */
  public function getItems($with_invoice = FALSE) {
    $items = [];
    foreach ($this->get('items') as $field_item) {
      if ($item = $field_item->entity) {
        $items[] = $item;
      }
    }
    if ($with_invoice) {
      foreach ($this->getInvoices() as $invoice) {
        foreach ($invoice->getItems() as $item) {
          $items[] = $item;
        }
      }
    }
    return $items;
  }

  /**
   * @return \Drupal\cfp_payment_request\Entity\PrInvoice[]
   */
  public function getInvoices() {
    $invoices = [];
    foreach ($this->get('invoices') as $field_item) {
      if ($invoice = $field_item->entity) {
        $invoices[] = $invoice;
      }
    }
    return $invoices;
  }

  /**
   * Returns active state.
   *
   * @return string
   *   Active state.
   */
  public function getState() {
    return $this->get('state')->value ?: 'open_state';
  }

  /**
   * Returns active state.
   *
   * @return string
   *   Active state.
   */
  public function getStateId(): string {
    return $this->getState();
  }

  /**
   * {@inheritDoc}
   */
  public function getCompletionTimestamp(): int|string|null {
    return $this->get('date_of_completion')->value;
  }

  /**
   * Payment request state.
   *
   * @param string $state
   *   Payment request state.
   *
   * @return static
   *   Returns
   */
  public function setState($state) {
    $this->set('state', $state);
    return $this;
  }

  /**
   * Returns user friendly state value.
   *
   * @return string
   *   User friendly value.
   */
  public function getStateLabel() {
    return $this->get('state')->first()->getLabel();
  }

  /**
   * {@inheritdoc}
   */
  public function inheritsParentAccess() {
    return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function label() {
    return $this->get('label')->value;
  }

  /**
   * Is item approvement closed.
   *
   * @return bool
   *
   */
  public function isItemApprovementClosed() {
    return (bool) $this->get('items_approvement_closed')->value;
  }

  /**
   * {@inheritDoc}
   */
  public function appendChecklist($during_correction = FALSE, $after_deadline = FALSE) {
    /** @var \Drupal\cfp_payment_request\Entity\PaymentRequestType $payment_request_type */
    $payment_request_type = $this->get('type')->entity;
    if (!$during_correction) {
      if ($after_deadline) {
        $payment_request_checklist = $this->generateDuplicateChecklist($during_correction, $after_deadline);
      }
      else {
        $payment_request_checklist = \Drupal::entityTypeManager()
          ->getStorage('cfp_payment_request_checklist')
          ->create([
            'bundle' => $payment_request_type->get('payment_request_checklist_type'),
            'created_during_correction' => $during_correction,
            'created_after_deadline' => $after_deadline,
          ]);
      }
    } else {
      $payment_request_checklist = $this->generateDuplicateChecklist($during_correction, $after_deadline);
    }
    $payment_request_checklist->save();
    $this->get('checklist')->appendItem($payment_request_checklist->id());
  }

  /**
   * Generates new checklist.
   *
   * @param $correction
   * @param $deadline
   *
   * @return \Drupal\cfp_payment_request\Entity\CfpPaymentRequestChecklist
   */
  private function generateDuplicateChecklist($correction, $deadline): CfpPaymentRequestChecklist {
    $last_checklist = $this->getLastChecklist();
    $payment_request_checklist = $last_checklist->createDuplicate();
    $payment_request_checklist->set('closed', FALSE);
    $payment_request_checklist->set('validation_passed', FALSE);
    $payment_request_checklist->set('created_during_correction', $correction);
    $payment_request_checklist->set('created_after_deadline', $deadline);

    return $payment_request_checklist;
  }

  /**
   * Returns last checklist.
   *
   * @return \Drupal\cfp_payment_request\Entity\CfpPaymentRequestChecklist
   */
  public function getLastChecklist() {
    if ($this->get('checklist')->isEmpty()) {
      return FALSE;
    }
    /** @var \Drupal\cfp_payment_request\Entity\CfpPaymentRequestChecklist $checklist */
    $checklist = $this->get('checklist')->get(($this->get('checklist')->count() - 1))->entity;
    return $checklist;
  }

  /**
   * @return \Drupal\cfp_payment_request\Entity\PrCorrectionData
   */
  public function getCurrentCorrectionData() {
    $current_correction = $this->get('current_correction')->value;
    if ($item = $this->get('correction_data')->get($current_correction)) {
      if ($correction_data = $item->entity) {
        return $correction_data;
      }
    }
    return FALSE;
  }

  /**
   * @param $to_state
   */
  public function appendTransition($to_state) {
    $this->get('transition_history')->appendItem([
      'to' => $to_state,
      'timestamp' => \Drupal::time()->getCurrentTime(),
      'user_id' => \Drupal::currentUser()->id(),
      'user_email' => \Drupal::currentUser()->getEmail(),
      'user_display_name' => \Drupal::currentUser()->getDisplayName(),
      'deadline' => $this->get('correction_deadline')->value,
    ]);
  }

  /**
   * Total support.
   *
   * @return int
   *   Total support.
   */
  public function getTotalSupport() {
    // TODO: Check every call.
    return (int) $this->get('item_support_computed_total')->value;
  }

  /**
   * Amount to pay.
   *
   * @return int
   *   Amount to pay.
   */
  public function getAmountToPay() {
    return (int) $this->get('amount_to_pay')->value;
  }

  /**
   * Amount dedicated to advance payment.
   *
   * @return int
   *   Amount dedicated to advance payment.
   */
  public function getAmountDedicatedToAp() {
    return (int) $this->get('computed_amount_dedicated_to_ap')->value;
  }

  /**
   * Returns pr type.
   *
   * @return string
   *   Returns value of config field pr type.
   */
  public function getPaymentRequestType() {
    return $this->hasField('pr_type') ? $this->get('pr_type')->value : NULL;
  }

  /**
   * @return string
   */
  public function getPaymentRequestTypeLabel() {
    if ($type = $this->getPaymentRequestType()) {
      $allowed_values = $this->get('pr_type')->getFieldDefinition()->getSetting('allowed_values');
      return $allowed_values[$type];
    }
  }

  /**
   * Set amount dedicated to advance payment coverage.
   *
   * @param $amount
   *   Amount dedicated to advance payment.
   */
  public function setAmountDedicatedToAp($amount) {
    $this->set('amount_dedicated_to_ap', $amount);
    return $this;
  }

  /**
   * @return string
   *   Last reopening instructions.
   */
  public function getLastReopeningInstructions() {
    if (!$this->get('previous_reopen_instructions')->isEmpty()) {
      return $this->get('previous_reopen_instructions')->get($this->get('previous_reopen_instructions')->count() - 1)->value;
    }
  }

  public function getSignatureToken() {
    /** @var \Drupal\halo_entity_cfp\Entity\Cfp $cfp */
    $cfp = $this->getParent();
    return $cfp->getApplicantEntity()->label();
  }

  public static function bundleFieldDefinitions(EntityTypeInterface $entity_type, $bundle, array $base_field_definitions) {
    $fields = [];
    $pr_type = \Drupal::entityTypeManager()->getStorage('cfp_payment_request_type')->load($bundle);
    if ($pr_type) {
      $settings = $base_field_definitions['items']->getSettings();
      $fields['items'] = clone $base_field_definitions['items'];
      $settings['handler_settings']['target_bundles'] = [$pr_type->get('payment_request_item_type') => $pr_type->get('payment_request_item_type')];
      $fields['items']->setSettings($settings);

      $settings = $base_field_definitions['invoices']->getSettings();
      $fields['invoices'] = clone $base_field_definitions['invoices'];
      $settings['handler_settings']['target_bundles'] = [$pr_type->get('payment_request_invoice_type') => $pr_type->get('payment_request_invoice_type')];
      $fields['invoices']->setSettings($settings);
    }
    return $fields;
  }

  /**
   * Returns checklist that was before given checklist.
   *
   * @param \Drupal\cfp_payment_request\Entity\CfpPaymentRequestChecklist $payment_request_checklist
   */
  public function getPreviousChecklist(CfpPaymentRequestChecklist $payment_request_checklist) {
    $current_entity = NULL;
    foreach ($this->get('checklist') as $item) {
      if ($looping_payment_request_checklist = $item->entity) {
        if ($looping_payment_request_checklist->id() == $payment_request_checklist->id()) {
          return $current_entity;
        }
        $current_entity = $looping_payment_request_checklist;
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
    $fields = parent::baseFieldDefinitions($entity_type);

    // Add the published field.
    $fields += static::publishedBaseFieldDefinitions($entity_type);

    $fields['user_id'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('Authored by'))
      ->setDescription(t('The user ID of author of the Payment request entity.'))
      ->setSetting('target_type', 'user')
      ->setSetting('handler', 'default')
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['label'] = BaseFieldDefinition::create('string')
      ->setLabel(t('Kifizetési Igénylés sorszáma'))
      ->setDescription(t('The name of the Payment request entity.'))
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['item_pay_off_total'] = BaseFieldDefinition::create('integer')
      ->setLabel('Igényelt elszámolási összeg (Ft)')
      ->setSetting('size', 'big')
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['item_support_total'] = BaseFieldDefinition::create('integer')
      ->setLabel('Igényelt támogatási összeg (Ft)')
      ->setSetting('size', 'big')
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields_definitions = isolate_numeric_field_types('cfp_payment_request_item');
    foreach (static::ADD_UP_FIELDS as $add_up_field) {
      $field_name = $add_up_field . '_total';
      if (!isset($fields[$field_name])) {
        $fields[$field_name] = self::createAddUpFieldFromFieldDefinition($fields_definitions[$add_up_field]);
      }
    }

    $fields['item_pay_off_computed_total']->setInitialValueFromField('item_pay_off_total');
    $fields['item_support_computed_total']->setInitialValueFromField('item_support_total');

    $fields['computed_amount_dedicated_to_ap'] = BaseFieldDefinition::create('integer')
      ->setLabel(t('Amount dedicated to advance payment'))
      ->setClass('\Drupal\cfp_payment_request\Plugin\Field\AmountDedicatedToAP')
      ->setComputed(TRUE)
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['amount_dedicated_to_ap'] = BaseFieldDefinition::create('integer')
      ->setLabel(t('Amount dedicated to advance payment'))
      ->setSetting('size', 'big')
      ->setReadOnly(TRUE);

    $fields['amount_to_pay'] = BaseFieldDefinition::create('integer')
      ->setLabel(t('Amount to pay'))
      ->setComputed(TRUE)
      ->setClass('\Drupal\cfp_payment_request\Plugin\Field\PrAmountToPayItemList')
      ->setSetting('size', 'big')
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['items'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('Items'))
      ->setSetting('target_type', 'cfp_payment_request_item')
      ->setSetting('handler', 'default')
      ->setSetting('handler_settings', [
        'target_bundles' => [],
      ])
      ->setClass('\Drupal\cfp_payment_request\Plugin\Field\FieldType\PRFieldItemList')
      ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED)
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['items_approvement_closed'] = BaseFieldDefinition::create('boolean')
      ->setLabel(t('Items approvement closed'))
      ->setReadOnly(TRUE);

    $fields['invoices'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('Invoices'))
      ->setSetting('target_type', 'pr_invoice')
      ->setSetting('handler', 'default')
      ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED)
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['checklist'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('Checklist'))
      ->setSetting('target_type', 'cfp_payment_request_checklist')
      ->setSetting('handler', 'default')
      ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED)
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['state'] = BaseFieldDefinition::create('state')
      ->setLabel(t('State'))
      ->setSetting('max_length', 255)
      ->setDefaultValue('open_state')
      ->setSetting('workflow', 'payment_request')
      ->setDisplayConfigurable('view', TRUE);

    $fields['comment'] = BaseFieldDefinition::create('string_long')
      ->setLabel(t('Comment'))
      ->setDisplayConfigurable('view', TRUE);

    $fields['justification'] = BaseFieldDefinition::create('string_long')
      ->setLabel(t('Justification'))
      ->setDisplayConfigurable('view', TRUE);

    $fields['reopen_instructions'] = BaseFieldDefinition::create('string_long')
      ->setLabel(t('Reopen instructions'))
      ->setDisplayConfigurable('view', TRUE);

    $fields['previous_reopen_instructions'] = BaseFieldDefinition::create('string_long')
      ->setLabel(t('Previous reopening instructions'))
      ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED)
      ->setDisplayConfigurable('view', TRUE);

    $fields['closed_date'] = BaseFieldDefinition::create('datetime')
      ->setLabel(t('Closed date'))
      ->setDisplayConfigurable('view', TRUE);

    $fields['submission_date'] = BaseFieldDefinition::create('datetime')
      ->setLabel(t('Last submission date'))
      ->setComputed(TRUE)
      ->setSettings([
        'state' => 'sent',
        'search_for' => TransitionDateSearchItemList::SEARCH_LAST,
        'field_name' => 'transition_history',
      ])
      ->setClass('\Drupal\halo_transition_history_field\Plugin\Field\TransitionDateSearchItemList')
      ->setDisplayConfigurable('view', TRUE);

    $fields['first_submission_date'] = BaseFieldDefinition::create('timestamp')
      ->setLabel(t('First submission date'))
      ->setReadOnly(TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['current_correction'] = BaseFieldDefinition::create('integer')
      ->setLabel(t('Current correction'))
      ->setDefaultValue(0)
      ->setReadOnly(TRUE);

    $fields['correction_data'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel('Correction data')
      ->setSetting('target_type', 'correction_data')
      ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED)
      ->setDisplayConfigurable('view', TRUE);

    $fields['old_prints'] = BaseFieldDefinition::create('file')
      ->setLabel(t('Older prints'))
      ->setSettings([
        'file_directory' => 'payment_request/new/print_files',
        'max_filesize' => '100 MB',
        'file_extensions' => 'pdf',
        'description_field' => TRUE,
        'uri_scheme' => 'public',
      ])
      ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED)
      ->setDisplayConfigurable('view', TRUE);

    $fields['date_of_completion'] = BaseFieldDefinition::create('timestamp')
      ->setLabel(t('Date of completion'))
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayConfigurable('form', TRUE);

    $fields['statements_accepted'] = BaseFieldDefinition::create('boolean')
      ->setLabel(t('Statements'))
      ->setReadOnly(TRUE)
      ->setDefaultValue(FALSE);

    $fields['attached_documents'] = BaseFieldDefinition::create('file')
      ->setLabel(t('Documents attached by an administrator'))
      ->setSettings([
        'file_directory' => 'pr_attached_files',
        'max_filesize' => '100 MB',
        'file_extensions' => 'pdf png jpg doc docx xls xlsx',
        'description_field' => TRUE,
        'uri_scheme' => 'public',
      ])
      ->setDisplayConfigurable('view', TRUE);

    $fields['suspended_documents'] = BaseFieldDefinition::create('file')
      ->setLabel(t('Suspended documents'))
      ->setSettings([
        'file_directory' => 'payment_request/suspended_documents',
        'max_filesize' => '100 MB',
        'file_extensions' => 'doc docx jpeg jpg png pdf',
        'description_field' => TRUE,
        'uri_scheme' => 'public',
      ])
      ->setDescription(t('Documents attached during suspension'))
      ->setDisplayConfigurable('view', TRUE)
      ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED);

    $fields['transition_history'] = BaseFieldDefinition::create('transition_history')
      ->setLabel(t('Transition History'))
      ->setSetting('state_field', 'state')
      ->setReadOnly(TRUE)
      ->setDisplayConfigurable('view', TRUE)
      ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED);

    $fields['status']->setDescription(t('A boolean indicating whether the Payment request is published.'));

    $fields['created'] = BaseFieldDefinition::create('created')
      ->setLabel(t('Created'))
      ->setDescription(t('The time that the entity was created.'));

    $fields['changed'] = BaseFieldDefinition::create('changed')
      ->setLabel(t('Changed'))
      ->setDescription(t('The time that the entity was last edited.'));

    $fields['correction_deadline'] = BaseFieldDefinition::create('timestamp')
      ->setLabel(t('Correction deadline'))
      ->setDescription(t('Deadline for submitting PR correction'))
      ->setDisplayConfigurable('view', TRUE);

    return $fields;
  }

  /**
   * Create add up field form definition.
   */
  protected static function createAddUpFieldFromFieldDefinition(FieldDefinitionInterface $field_definition) {
    return BaseFieldDefinition::create($field_definition->getType())
      ->setLabel($field_definition->getLabel() . ' ' . t('total'))
      ->setSettings($field_definition->getSettings())
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);
  }

}
content_copyCOPY