]> gitweb.erp-flowers.ru Git - erp24_rep/yii-erp24/.git/commitdiff
[ERP-195] Добавлена загрузка производственного календаря с сайта xmlcalendar.ru и...
authorAlexander Smirnov <fredeom@mail.ru>
Wed, 25 Sep 2024 09:47:44 +0000 (12:47 +0300)
committerAlexander Smirnov <fredeom@mail.ru>
Wed, 25 Sep 2024 09:47:44 +0000 (12:47 +0300)
docker/php/Dockerfile
erp24/composer.json
erp24/controllers/ProductionCalendarController.php [new file with mode: 0644]
erp24/migrations/m240925_063026_create_table_production_calendar.php [new file with mode: 0755]
erp24/records/ProductionCalendar.php [new file with mode: 0644]
erp24/views/production-calendar/index.php [new file with mode: 0644]
erp24/web/css/production-calendar/style.css [new file with mode: 0644]

index 2de2f1f105183566c37cd6e7530c230f8cbd7a1b..1215d6f1e64680f76b9de0677b0f34a0d0fac112 100644 (file)
@@ -12,7 +12,7 @@ RUN apk add --no-cache zlib libpng icu zip libzip-dev \
   && apk del .deps
 
 RUN apk --no-cache --update --repository http://dl-cdn.alpinelinux.org/alpine/v$ALPINE_VERSION/main/ add \
-    postgresql-dev
+    autoconf dpkg-dev dpkg file g++ gcc libc-dev make pkgconf re2c postgresql-dev
 RUN docker-php-ext-install pdo_pgsql
 
 #add composer
index 4cef58387bddb3d7ed53bcf56536ae1bf1005738..d1f2c033e66453b8916c6e06ed61603f1c342d21 100644 (file)
@@ -30,7 +30,8 @@
         "kartik-v/yii2-bootstrap5-dropdown": "@dev",
         "kartik-v/yii2-grid": "@dev",
         "kartik-v/yii2-widget-datepicker": "dev-master",
-        "phpoffice/phpspreadsheet": "^2.2"
+        "phpoffice/phpspreadsheet": "^2.2",
+        "ext-xmlreader": "*"
     },
     "require-dev": {
         "yiisoft/yii2-debug": "~2.1.0",
diff --git a/erp24/controllers/ProductionCalendarController.php b/erp24/controllers/ProductionCalendarController.php
new file mode 100644 (file)
index 0000000..9ec3a12
--- /dev/null
@@ -0,0 +1,97 @@
+<?php
+
+namespace app\controllers;
+
+use Yii;
+use yii\helpers\ArrayHelper;
+use yii\helpers\Json;
+use yii\web\Controller;
+use yii\web\UploadedFile;
+use XMLReader;
+use yii_app\records\ProductionCalendar;
+
+class ProductionCalendarController extends Controller
+{
+    public function setCalendarValue($date, $work = null) {
+        $date = date("Y-m-d", strtotime($date));
+        $weekDay = date("N", strtotime($date));
+
+        $productionCalendar = ProductionCalendar::findOne(['date' => $date]);
+        if (!$productionCalendar) {
+            $productionCalendar = new ProductionCalendar;
+            $productionCalendar->date = $date;
+        }
+        $productionCalendar->work = $work ?? ($weekDay < 6 ? 1 : 0);
+        $productionCalendar->save();
+        if ($productionCalendar->getErrors()) {
+            throw new \Exception(Json::encode($productionCalendar->getErrors()));
+        }
+    }
+
+    public function parseXml($xml) {
+        $s = date("Y-01-01 00:00:00");
+        $f = date("Y-12-31 00:00:00");
+        while ($s < $f) {
+            $this->setCalendarValue($s);
+            $s = date("Y-m-d 00:00:00", strtotime("+1 day", strtotime($s)));
+        }
+        $calendarYear = '';
+        while ($xml->read()) {
+            if ($xml->nodeType == XMLReader::ELEMENT && $xml->localName == 'calendar') {
+                $calendarYear = $xml->getAttribute('year');
+            }
+            if ($xml->nodeType == XMLReader::ELEMENT && $xml->localName == 'day') {
+                $date1 = date($calendarYear . '-' . str_replace('.', '-', $xml->getAttribute('d')));
+                $work = $xml->getAttribute('t') > 1 ? 1 : 0;
+                $this->setCalendarValue($date1, $work);
+            }
+        }
+    }
+
+    public function actionIndex($viewYear = null) {
+        if (Yii::$app->request->isPost) {
+            $xml = UploadedFile::getInstanceByName('xmlFile');
+            $path = Yii::getAlias("@uploads") . '/' . $xml->getBaseName() . '.' . $xml->getExtension();
+            $xml->saveAs($path);
+
+            $xml = new XMLReader;
+            $xml->open($path);
+
+            $this->parseXml($xml);
+
+            Yii::$app->session->setFlash('success', 'Календарь успешно загружен.');
+        }
+
+        $months = ['Январь',' Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'];
+        $daysInWeek = ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс'];
+
+        $workDaysMap = ArrayHelper::map(ProductionCalendar::find()->where(['between', 'date', '2024-01-01', '2024-12-31'])->all(), 'date', 'work');
+
+        if (!$viewYear) {
+            $viewYear = date('Y');
+        }
+
+        $workDaysInMonthCountMap = [];
+        foreach (range(1,12) as $monthIndex) {
+            if ($monthIndex < 10) {
+                $monthIndex = '0' . $monthIndex;
+            }
+            $date1 = date($viewYear . '-' . $monthIndex . '-01');
+            $date2 = date($viewYear . '-' . $monthIndex . '-t', strtotime($date1));
+            $cnt = 0;
+            while ($date1 <= $date2) {
+                $cnt += $workDaysMap[$date1];
+                $date1 = date('Y-m-d', strtotime('+1 day', strtotime($date1)));
+            }
+            $workDaysInMonthCountMap[$monthIndex] = $cnt;
+        }
+
+        $years = [];
+        foreach (range(2023, date('Y')) as $y) {
+            $years[$y] = $y;
+        }
+
+        return $this->render('index',
+            compact('months', 'daysInWeek', 'workDaysMap', 'viewYear', 'years', 'workDaysInMonthCountMap'));
+    }
+}
\ No newline at end of file
diff --git a/erp24/migrations/m240925_063026_create_table_production_calendar.php b/erp24/migrations/m240925_063026_create_table_production_calendar.php
new file mode 100755 (executable)
index 0000000..8cdd982
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+
+use yii\db\Migration;
+
+/**
+ * Class m240925_063026_create_table_production_calendar
+ */
+class m240925_063026_create_table_production_calendar extends Migration
+{
+    const TABLE_NAME = 'erp24.production_calendar';
+    /**
+     * {@inheritdoc}
+     */
+    public function safeUp()
+    {
+        $this->createTable(self::TABLE_NAME, [
+            'id' => $this->primaryKey(),
+            'date' => $this->string(10)->notNull()->comment('День определяющих рабочее состояние'),
+            'work' => $this->tinyInteger()->notNull()->comment('1 - будни, 0 - выходной или праздник'),
+        ]);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function safeDown()
+    {
+        $this->dropTable(self::TABLE_NAME);
+    }
+}
diff --git a/erp24/records/ProductionCalendar.php b/erp24/records/ProductionCalendar.php
new file mode 100644 (file)
index 0000000..67b733f
--- /dev/null
@@ -0,0 +1,48 @@
+<?php
+
+namespace yii_app\records;
+
+use Yii;
+
+/**
+ * This is the model class for table "production_calendar".
+ *
+ * @property int $id
+ * @property string $date День определяющих рабочее состояние
+ * @property int $work 1 - будни, 0 - выходной или праздник
+ */
+class ProductionCalendar extends \yii\db\ActiveRecord
+{
+    /**
+     * {@inheritdoc}
+     */
+    public static function tableName()
+    {
+        return 'production_calendar';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function rules()
+    {
+        return [
+            [['date', 'work'], 'required'],
+            [['work'], 'default', 'value' => null],
+            [['work'], 'integer'],
+            [['date'], 'string', 'max' => 10],
+        ];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function attributeLabels()
+    {
+        return [
+            'id' => 'ID',
+            'date' => 'Date',
+            'work' => 'Work',
+        ];
+    }
+}
diff --git a/erp24/views/production-calendar/index.php b/erp24/views/production-calendar/index.php
new file mode 100644 (file)
index 0000000..4efedee
--- /dev/null
@@ -0,0 +1,72 @@
+<?php
+
+use yii\helpers\Html;
+use yii\widgets\ActiveForm;
+
+/** @var $months array */
+/** @var $daysInWeek array */
+/** @var $workDaysMap array */
+/** @var $years array */
+/** @var $viewYear string */
+/** @var $workDaysInMonthCountMap array */
+
+$this->registerCssFile('/css/production-calendar/style.css');
+
+?>
+
+<div class="productionCalendarIndex m-5">
+
+    <?php if (Yii::$app->session->hasFlash('success')): ?>
+        <div class="alert alert-success alert-dismissable">
+            <button aria-hidden="true" data-dismiss="alert" class="close" type="button">×</button>
+            <?= Yii::$app->session->getFlash('success') ?>
+        </div>
+    <?php endif; ?>
+
+    <?php ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>
+
+    <?= Html::fileInput('xmlFile', null, ['class' => 'btn btn-success', 'onchange' => 'this.form.submit()', 'accept' => '.xml']) ?>
+
+    Отобразить календарь за <?= Html::dropDownList('year', $viewYear, $years,
+        ['onchange' => 'window.location = "/production-calendar/index?viewYear=" + this.value;']) ?> год.
+    Текущий просматриваемый год: <b><?= $viewYear ?></b>.
+
+    <?php Activeform::end() ?>
+
+
+    <div class="pcal-month-container" style="max-width: 1230px;">
+        <?php foreach ($months as $monthIndex => $month): ?>
+            <div class="pcal-month w-20" style="max-width: 250px;">
+                <div class="pcal-month-name"><?= $month; ?></div>
+                <div class="pcal-days">
+                    <table>
+                        <tbody>
+                            <tr>
+                                <?php foreach ($daysInWeek as $dayName): ?>
+                                    <td class="pcal-day-of-week1"><?= $dayName; ?></td>
+                                <?php endforeach; ?>
+                            </tr>
+                            <?php $padMonth = ($monthIndex + 1) < 10 ? '0' . ($monthIndex + 1) : ($monthIndex + 1); ?>
+                            <?php $num = 1 - date('N', strtotime(date($viewYear . "-" . $padMonth . "-01"))); ?>
+                            <?php $numMonth =  date('t', strtotime(date($viewYear . "-" . $padMonth . "-01"))); ?>
+                            <?php foreach (range(1, 6) as $weekNum): ?>
+                                <tr>
+                                    <?php foreach ($daysInWeek as $dayIndexInWeek => $dayName): ?>
+                                        <?php $num++; ?>
+                                        <?php $date = $viewYear . '-' . $padMonth . '-' . ($num < 10 ? '0' . $num : $num); ?>
+                                        <td class="text-center pcal-day <?= ($workDaysMap[$date] ?? -1) == 0 ? 'pcal-day-holiday' : ''?>">
+                                            <?= $num > 0 && $num <= $numMonth ? $num : '&nbsp;' ?></td>
+                                    <?php endforeach; ?>
+                                </tr>
+                            <?php endforeach; ?>
+                            <tr>
+                                <td colspan="7" style="font-size: 1rem;">Число рабочих дней: <?= $workDaysInMonthCountMap[$padMonth] ?></td>
+                            </tr>
+                        </tbody>
+                    </table>
+                </div>
+            </div>
+        <?php endforeach; ?>
+    </div>
+
+</div>
diff --git a/erp24/web/css/production-calendar/style.css b/erp24/web/css/production-calendar/style.css
new file mode 100644 (file)
index 0000000..fb301bb
--- /dev/null
@@ -0,0 +1,71 @@
+h1 {
+    text-align: center;
+}
+h2 {
+    text-align: center;
+}
+.text-right {
+    text-align: right;
+}
+.text-left {
+    text-align: left;
+}
+.text-center {
+    text-align: center;
+}
+/*.pcal-month-container, .pcal-norm-container {*/
+/*    clear:both;*/
+/*    display: block;*/
+/*}*/
+.pcal-norm-container table {
+    width: 100%;
+}
+.pcal-norm-container thead, .pcal-norm-container tfoot {
+    font-weight: bold;
+}
+.pcal-month div, .pcal-month td, thead {
+    font-size: 22px;
+}
+.pcal-month td , td {
+    padding: 3px;
+}
+.pcal-month {
+    width: 230px;
+    float: left;
+    margin: 5px;
+}
+.pcal-day-of-week1 {
+    font-size: 1rem !important;
+}
+.pcal-day-of-week, td.pcal-norm-month, .pcal-norm-container tfoot td{
+    background-color: #DAE8F3;
+    font-weight: bold;
+}
+.pcal-month-name {
+    font-weight: bold;
+    text-align: center;
+}
+.pcal-day {
+    cursor: pointer;
+}
+.pcal-day-hover {
+    background-color: #ffff99;
+}
+.pcal-day-short {
+    font-weight: bold;
+    color: #8EBC51;
+}
+.pcal-day-holiday {
+    font-weight: bold;
+    color: #e20000;
+}
+.pcal-current {
+    /*border: 2px solid red;*/
+    background-color: #FFD4D4;
+}
+.pcal-footer {
+    margin: 20px 5px 5px 5px;
+}
+.pcal-footer-ital {
+    font-style: italic;
+}