trinion_mrp-1.0.x-dev/src/Form/MrpRecordCreatorForm.php

src/Form/MrpRecordCreatorForm.php
<?php

declare(strict_types=1);

namespace Drupal\trinion_mrp\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\node\Entity\Node;
use Drupal\trinion_mrp\Controller\SozdanieZakazaNaProizvodstvo;
use Drupal\trinion_mrp\Controller\SozdanieZakazaPostavshiku;

/**
 * Мастер создания MRP записей
 */
final class MrpRecordCreatorForm extends FormBase {

  /**
   * {@inheritdoc}
   */
  public function getFormId(): string {
    return 'trinion_mrp_record_creator';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state): array {
    $form['scenario'] = [
      '#type' => 'entity_autocomplete',
      '#title' => t('Scenario'),
      '#required' => TRUE,
      '#target_type' => 'node',
      '#selection_settings' => [
        'target_bundles' => ['mrp_scenario'],
      ],
    ];

    $tree = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadTree('sklad');
    $options = [];
    foreach ($tree as $item)
      $options[$item->tid] = $item->name;
    $form['sklad'] = [
      '#type' => 'select',
      '#title' => t('Warehouse'),
      '#multiple' => TRUE,
      '#required' => TRUE,
      '#options' => $options,
    ];

    $form['mps'] = [
      '#type' => 'entity_autocomplete',
      '#title' => t('MPS'),
      '#target_type' => 'node',
      '#required' => TRUE,
      '#selection_settings' => [
        'target_bundles' => ['mps'],
      ],
    ];

//    $form['show_table'] = [
//      '#type' => 'submit',
//      '#value' => t('Show table'),
//      '#submit' => ['::showTableSubmit'],
//    ];

    $form['actions']['submit'] = [
      '#type' => 'actions',
      'submit' => [
        '#type' => 'submit',
        '#value' => $this->t('Show MRP Records'),
        '#submit' => ['::showMrpRecordsSubmit']
      ],
    ];

//    if ($products = $form_state->get('products')) {
//      $form['table'] = [
//        '#type' => 'container',
//        '#custom_suggestion' => 'gross_requirements',
//        '#tree' => TRUE,
//      ];
//
//      foreach ($products as $key => $product) {
//        $form['table']['periods'][$key]['#product_data'] = $product;
//        foreach ($product['periods'] as $i => $count) {
//          $form['table']['periods'][$key][$i] = [
//            '#type' => 'number',
//            '#caption' => $i,
//            '#default_value' => $i == 1 ? $count : '',
//          ];
//        }
//      }
//
//      $form['table']['periods'] = array_values($form['table']['periods']);
//    }

    $records = $form_state->get('records');

    if ($records) {
      $form['tables'] = [
        '#type' => 'container',
        '#prefix' => '<hr><h2>' . t('MRP records preview') . '</h2>',
      ];
      foreach ($records as $record) {
        $form['tables'][] = self::tableElement($record);
      }

      $form['save_mrp_records_submit'] = [
        '#type' => 'submit',
        '#value' => t('Save MRP records, PuO, PrO'),
        '#submit' => ['::saveMrpRecordsSubmit'],
      ];
      if (!\Drupal::state()->get('trinion_mrp_proizvodstvenniy_kalendar')) {
        $form['save_mrp_records_submit']['#disabled'] = TRUE;
        $form['save_mrp_records_submit']['#suffix'] = t('The production calendar has not been formed');
      }
    }

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state): void {

  }

  public function showMrpRecordsSubmit(array &$form, FormStateInterface $form_state): void {
    $values = $form_state->getValues();

    $mps = Node::load($values['mps']);
    $product_periods = [];
    foreach ($mps->get('field_tp_stroki') as $stroka) {
      $stroka = $stroka->entity;
      $tovar = $stroka->get('field_tp_tovar')->first()->entity;
      $tovar_name = $tovar->get('field_tp_artikul')->getString();
      $key = $tovar->id();
      if ($harakteristika = $stroka->get('field_tp_kharakteristika_tovara')->first()) {
        $tovar_name .= ', ' . $harakteristika->entity->label();
        $key .= '_' . $harakteristika->id();
      }

      if (!isset($product_periods[$key])) {
        $product_periods[$key]['tovar'] = $tovar;
        $product_periods[$key]['unit'] = $stroka->get('field_tp_edinica_izmereniya')->first()->entity->id();
        $product_periods[$key]['harakteristika'] = $harakteristika ? $harakteristika : NULL;
        $product_periods[$key]['product_name'] = $tovar_name;
      }
      $product_periods[$key]['source'][] = $values['mps'];
      $product_periods[$key]['periods'] = $stroka->periods;
    }

    $product_periods = array_values($product_periods);

    $records = [];
    foreach ($product_periods as $key => $product) {
      $records = $this->generateMrpRecordData($product, $values['sklad'], $records, $product['periods'], $mps->get('field_mrp_period_length_days')->getString(), 1, TRUE);
    }

    $form_state->setRebuild(TRUE);
    $form_state->set('records', $records);
  }

  public function generateMrpRecordData($product, $skladi, $records, $planed_order_receipts, $periods_length, $level, $recursive) {
    static $sklad_kolichestvo = [];
    $has_error = FALSE;
    $tovar = $product['tovar'];
    $record = $product;
    $record['harakteristika_tid'] = $harakteristika_tid = $product['harakteristika'] ? $product['harakteristika']->id() : NULL;

    $record['part'] = $product['product_name'];
    $record['source'] = $product['source'];
    $record['tovar'] = $tovar;
    $record['level'] = $level;
    $record['kolichestvo'] = $product['kolichestvo'] ?? 1;
    $edinica_izmereniya_tid = $product['unit'];

    $record['leadtime'] = $tovar->get('field_mrp_lead_time')->getString();
    $lot_size = $tovar->get('field_mrp_lot_size')->getString();
    if ($lot_size == '') {
      $has_error = TRUE;
      \Drupal::messenger()->addError(t('Part %part. Lot Size is not specified.', ['%part' => $record['part']]));
    }
    else {
      $mrp_lot_size_spisok_znacheniy = $tovar->field_mrp_lot_size->getSetting('allowed_values');
      $record['lotsize'] = $mrp_lot_size_spisok_znacheniy[$tovar->get('field_mrp_lot_size')->getString()];
      if ($record['lotsize'])
        $record['lotsize_value'] = $tovar->get('field_mrp_lotsize_value')->getString();
    }
    $tovar_id = $tovar->id();
    if (isset($sklad_kolichestvo[$tovar_id][$harakteristika_tid][$edinica_izmereniya_tid])) {
      $available_balance = $sklad_kolichestvo[$tovar_id][$harakteristika_tid][$edinica_izmereniya_tid];
      if ($available_balance < 0)
        $available_balance = 0;
    }
    else {
      $available_balance = 0;
      foreach ($skladi as $sklad_tid) {
        $available_balance += \Drupal::service('trinion_tp.helper')->getLiveOstatok($tovar_id, $sklad_tid, $harakteristika_tid, $edinica_izmereniya_tid);
      }
    }

    $record['available_balance_start'] = $available_balance;

    $record['gross_requirements'] = $planed_order_receipts;

    foreach ($record['gross_requirements'] as $period => $count) {
      $record['planned_order_released'][$period] = '';
      $record['planed_order_receipts'][$period] = '';
      if ($count) {
        if ($available_balance < 0) {
          $record['planed_order_receipts'][$period] = $count;
          $available_balance -= $count;
        }
        else {
          $available_balance -= $count;
          if ($available_balance < 0) {
            $record['planed_order_receipts'][$period] = -1 * $available_balance;
          }
        }
        $record['available_balance'][$period] = $available_balance;
      }
      else
        $record['available_balance'][$period] = '';
      $sklad_kolichestvo[$tovar_id][$harakteristika_tid][$edinica_izmereniya_tid] = $available_balance;


    }

    $available_balance =  $record['available_balance_start'];

    foreach ($record['planed_order_receipts'] as $period => $count) {
      if (!$count) {
        continue;
      }

      if (is_numeric($record['leadtime'])) {
        $lead_period_number = $period - $record['leadtime'];
        if ($lead_period_number <= 0) {
          \Drupal::messenger()->addError(t('Part %part. Planned order releases is out of range.', ['%part' => $record['part']]));
          $has_error = TRUE;
        }
        else {
          if ($record['lotsize_value']) {
            if ($available_balance >= $count) {
              $record['available_balance'][$period] = $available_balance - $count;
              $available_balance -= $count;
            }
            else {
              $i = 0;
              do {
                $i++;
                $release_value = $record['lotsize_value'] * $i;
              } while ($release_value < $count);
              $record['planned_order_released'][$lead_period_number] = $release_value;
              $record['available_balance'][$period] += $release_value;
              $available_balance += $release_value;
              $available_balance -= $count;
            }
          }
          else
            $record['planned_order_released'][$lead_period_number] = $count;
        }
      }
      else {
        $has_error = TRUE;
        \Drupal::messenger()->addError(t('Part %part. Lead Time is not specified.', ['%part' => $record['part']]));
      }
    }

    $prev_count = $record['available_balance_start'];
    foreach ($record['gross_requirements'] as $period => $count) {
      if ($count != '') {
        $prev_count = $record['available_balance'][$period];
        continue;
      }
      $record['available_balance'][$period] = $prev_count;
    }

    if (!$has_error) {
      $records[] = $record;

      if ($recursive) {
        $specificatiya = \Drupal::service('trinion_tp.helper')->getSpecificatsiyaTovara($tovar->id(), $harakteristika_tid, TRUE);
        $istochnik_popolneniya = $tovar->get('field_tp_istochnik_popolneniya')->getString();
        if ($specificatiya) {
          foreach ($specificatiya->get('field_tp_stroki') as $stroka) {
            $planned_order_released = $record['planned_order_released'];
            $tovar = $stroka->entity->get('field_tp_tovar')->first()->entity;
            $product_name = $tovar->get('field_tp_artikul')->getString();
            if ($harakteristika = $stroka->entity->get('field_tp_kharakteristika_tovara')->first()) {
              $harakteristika = $harakteristika->entity;
              $product_name .= ', ' . $harakteristika->label();
            }
            if (($kolichestvo = $stroka->entity->get('field_tp_kolichestvo')->getString()) > 0) {
              foreach ($planned_order_released as $key => $value)
                if ($planned_order_released[$key])
                  $planned_order_released[$key] *= $kolichestvo;
            }
            $product = [
              'tovar' => $tovar,
              'unit' => $stroka->entity->get('field_tp_edinica_izmereniya')->getString(),
              'harakteristika' => $harakteristika,
              'product_name' => $product_name,
              'source' => [],
              'kolichestvo' => $kolichestvo,
            ];
            $records = $this->generateMrpRecordData($product, $skladi, $records, $planned_order_released, $periods_length, $level + 1, TRUE);
          }
        }
        elseif ($istochnik_popolneniya == 2)
          \Drupal::messenger()->addError(t('Part %part. Has no specification.', ['%part' => $record['part']]));
      }
    }

    return $records;
  }

  public function saveMrpRecordsSubmit(array &$form, FormStateInterface $form_state): void {
    $records = $form_state->get('records');
    $values = $form_state->getValues();
    $mrp_report_data = [];
    $i = 0;
    $mps = Node::load($values['mps']);
    foreach ($records as $record) {
      if ($record['level'] == 1) {
        $i++;
        $mrp_report_data[$i]['source'] = $record['source'];
      }
      $mrp_report_data[$i]['tables'][] = [
        'tovar_id' => $record['tovar']->id(),
        'unit' => $record['unit'],
        'harakteristika_tid' => $record['harakteristika_tid'],
        'level' => $record['level'],
        'leadtime' => $record['leadtime'],
        'lotsize' => $record['lotsize'],
        'kolichestvo' => $record['kolichestvo'],
        'part' => $record['part'],
        'available_balance_start' => $record['available_balance_start'],
        'gross_requirements' => $record['gross_requirements'],
        'planed_order_receipts' => $record['planed_order_receipts'],
        'available_balance' => $record['available_balance'],
        'planned_order_released' => $record['planned_order_released'],
      ];
    }

    $uid = \Drupal::currentUser()->id();
    foreach ($mrp_report_data as $report) {
      foreach ($report['tables'] as $table)
      $tables[] = json_encode($table);
      $node = Node::create([
        'type' => 'zapis_mrp',
        'uid' => $uid,
        'title' => '',
        'status' => 1,
        'field_mrp_scenario' => $values['scenario'],
        'field_mrp_source_document' => $report['source'],
        'field_mrp_table' => $tables,
        'field_mrp_period_length_days' => $mps->get('field_mrp_period_length_days')->getString(),
        'field_mrp_kolichestvo_periodov' => $mps->get('field_mrp_kolichestvo_periodov')->getString(),
        'field_tp_data' => date('Y-m-d\T00:00:00', strtotime($mps->get('field_tp_data')->getString())),
      ]);
      $node->save();
      \Drupal::messenger()->addStatus(t('MRP records %num has been created.', ['%num' => $node->label()]));

      $pro = new SozdanieZakazaNaProizvodstvo();
      $pro->build($node);
      $puo = new SozdanieZakazaPostavshiku();
      $puo->build($node);
    }
  }

  public static function tableElement($record) {
    for ($i = 1; $i <= count($record['gross_requirements']); $i++)
      $periods[] = $i;
    $rows = [];

    foreach ($record['available_balance'] as $key => $val)
      if ($val < 0)
        $record['available_balance'][$key] = [
          'data' => ['#markup' => '<span title="' . $val . '">0</span>'],
        ];
    $rows[] = [['data' => '', 'colspan' => 2], ['data' => t('Periods'), 'colspan' => count($record['gross_requirements'])]];
    $rows[] = array_merge([['data' => ['#markup' => "<span title='" . t('Lead Time') . ": {$record['leadtime']}; " . t('Lot Size') . ": {$record['lotsize']}; " . t('Qty per unit') . " {$record['kolichestvo']}'>{$record['part']} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" . t('level') . " {$record['level']}</span>"], 'colspan' => 2]], $periods);
    $rows[] = array_merge([['data' => t('Gross requirements'), 'colspan' => 2]], $record['gross_requirements']);
    $rows[] = array_merge([['data' => t('Scheduled receipts'), 'colspan' => 2]], $record['planed_order_receipts']);
    $rows[] = array_merge([t('On hand'), $record['available_balance_start']], $record['available_balance']);
    $rows[] = array_merge([['data' => t('Planned-order release'), 'colspan' => 2]], $record['planned_order_released']);

    return [
      '#theme' => 'table',
      '#rows' => $rows,
      '#prefix' => '<br>',
      '#suffix' => '<br>',
      '#attributes' => [
        'class' => ['mrp-report-table'],
        'data-mrp-report-table' => '1',
      ],
    ];
  }
}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc