use Yii;
use yii\base\DynamicModel;
+use yii\db\Exception;
use yii\helpers\ArrayHelper;
+use yii\helpers\Json;
use yii\web\Controller;
use yii\web\Response;
+use yii_app\records\CategoryPlan;
use yii_app\records\CityStore;
use yii_app\records\CityStoreParams;
use yii_app\records\ExportImportTable;
$model->load(Yii::$app->request->get());
+ $isEditable = date($model->year . '-' . $model->month . '-d') > date('Y-m-d') && (
+ (date('d') < 25) || (date('Y-m-d', strtotime('-1 month', date($model->year . '-' . $model->month . '-d'))) > date('Y-m-d')));
+
+ $categoryPlan = CategoryPlan::find()->where(['year' => $model->year, 'month' => $model->month, 'store_id' => $model->store_id])->indexBy('category')->asArray()->all();
+
/////////////////////////// CHAT GPT STUFF ///////////////////////////////////
$currentDate = new \DateTime();
$types = array_keys($types);
/////////////////////////////////////////////////////////////////////////////////////
+ foreach ($types as $type) {
+ if (!isset($categoryPlan[$type])) {
+ $categoryPlanNew = new CategoryPlan;
+ $categoryPlanNew->year = $model->year;
+ $categoryPlanNew->month = $model->month;
+ $categoryPlanNew->store_id = $model->store_id;
+ $categoryPlanNew->category = $type;
+ $categoryPlanNew->offline = $table[$model->store_id][$type] ?? 0;
+ $categoryPlanNew->internet_shop = $tableOnline[$model->store_id][$type] ?? 0;
+ $categoryPlanNew->marketplace = 0;
+ $categoryPlanNew->write_offs = $tableWriteOffs[$type] ?? 0;
+ $categoryPlanNew->created_at = date('Y-m-d HH:i:s');
+ $categoryPlanNew->updated_at = date('Y-m-d HH:i:s');
+ $categoryPlanNew->created_by = Yii::$app->user->id;
+ $categoryPlanNew->updated_by = Yii::$app->user->id;
+ $categoryPlanNew->save();
+ if ($categoryPlanNew->getErrors()) {
+ throw new Exception(Json::encode($categoryPlanNew->getErrors()));
+ }
+ }
+ }
+
+ $categoryPlan = CategoryPlan::find()->where(['year' => $model->year, 'month' => $model->month, 'store_id' => $model->store_id])->indexBy('category')->asArray()->all();
+
$salesWriteOffsPlan = SalesWriteOffsPlan::find()->where(['year' => $model->year, 'month' => $model->month, 'store_id' => $model->store_id])->one();
$years = [];
$stores = ArrayHelper::map(CityStore::find()->andWhere(['visible' => '1'])->all(), 'id', 'name');
return $this->render('index', compact('model', 'years', 'stores', 'table', 'tableOnline',
- 'tableWriteOffs', 'types', 'salesWriteOffsPlan'));
+ 'tableWriteOffs', 'types', 'salesWriteOffsPlan', 'isEditable', 'categoryPlan'));
}
public function actionGetStores() {
return ArrayHelper::map($stores, 'id', 'name');
}
+
+ public function actionSaveFields() {
+ $data = Yii::$app->request->post();
+ $year = $data['year'];
+ $month = $data['month'];
+ $storeId = $data['store_id'];
+ $productType = $data['type'];
+ $offline = $data['offline'];
+ $internet_shop = $data['internet_shop'];
+ $write_offs = $data['write_offs'];
+
+ $categoryPlan = CategoryPlan::find()->where(['year' => $year, 'month' => $month, 'store_id' => $storeId, 'category' => $productType])->one();
+ if (!$categoryPlan) {
+ $categoryPlan = new CategoryPlan;
+ $categoryPlan->year = $year;
+ $categoryPlan->month = $month;
+ $categoryPlan->store_id = $storeId;
+ $categoryPlan->category = $productType;
+ $categoryPlan->created_by = Yii::$app->user->id;
+ $categoryPlan->created_at = date('Y-m-d H:i:s');
+ }
+ $categoryPlan->offline = $offline;
+ $categoryPlan->internet_shop = $internet_shop;
+ $categoryPlan->write_offs = $write_offs;
+ $categoryPlan->updated_by = Yii::$app->user->id;
+ $categoryPlan->updated_at = date('Y-m-d H:i:s');
+ $categoryPlan->save();
+ if ($categoryPlan->getErrors()) {
+ throw new \Exception(Json::encode($categoryPlan->getErrors()));
+ }
+ return 'ok';
+ }
}
(date('d') < 25) ||
(date('Y-m-d', strtotime('-1 month', date($model->year . '-' . $model->month . '-d'))) > date('Y-m-d')
));
-//var_dump($isEditable); die;
$prevPrevMonthStart = date("Y-m-01", strtotime("-2 month", strtotime($model->year . "-" . $model->month . "-01")));
$prevPrevMonthEnd = date("Y-m-t", strtotime("-2 month", strtotime($model->year . "-" . $model->month . "-01")));
--- /dev/null
+<?php
+
+namespace yii_app\records;
+
+use Yii;
+use yii\behaviors\BlameableBehavior;
+use yii\behaviors\TimestampBehavior;
+use yii\db\Expression;
+
+/**
+ * This is the model class for table "category_plan".
+ *
+ * @property int $id
+ * @property int $year Год создания отчёта
+ * @property int $month Месяц создания отчёта
+ * @property int $store_id id магазина в ERP
+ * @property string $category Название категории: срезка, горшечные, сопутствующие товары
+ * @property float|null $offline Оффлайн план процент
+ * @property float|null $internet_shop Интернет-магазин план процент
+ * @property float|null $marketplace Маркетплейс план процент
+ * @property float|null $write_offs Списания план процент
+ * @property string $created_at Дата создания
+ * @property string $updated_at Дата обновления
+ * @property int $created_by ID создателя записи
+ * @property int $updated_by ID обновителя записи
+ */
+class CategoryPlan extends \yii\db\ActiveRecord
+{
+ /**
+ * {@inheritdoc}
+ */
+ public static function tableName()
+ {
+ return 'category_plan';
+ }
+
+ public function behaviors() {
+ return [
+ [
+ 'class' => TimestampBehavior::class,
+ 'createdAtAttribute' => 'created_at',
+ 'updatedAtAttribute' => 'updated_at',
+ 'value' => new Expression('NOW()'),
+ ],
+ [
+ 'class' => BlameableBehavior::class,
+ 'createdByAttribute' => 'created_by',
+ 'updatedByAttribute' => 'updated_by',
+ ],
+ ];
+ }
+
+
+ /**
+ * {@inheritdoc}
+ */
+ public function rules()
+ {
+ return [
+ [['year', 'month', 'store_id', 'category', 'created_at', 'updated_at', 'created_by', 'updated_by'], 'required'],
+ [['year', 'month', 'store_id', 'created_by', 'updated_by'], 'default', 'value' => null],
+ [['year', 'month', 'store_id', 'created_by', 'updated_by'], 'integer'],
+ [['offline', 'internet_shop', 'marketplace', 'write_offs'], 'number'],
+ [['created_at', 'updated_at'], 'safe'],
+ [['category'], 'string', 'max' => 100],
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function attributeLabels()
+ {
+ return [
+ 'id' => 'ID',
+ 'year' => 'Year',
+ 'month' => 'Month',
+ 'store_id' => 'Store ID',
+ 'category' => 'Category',
+ 'offline' => 'Offline',
+ 'internet_shop' => 'Internet Shop',
+ 'marketplace' => 'Marketplace',
+ 'write_offs' => 'Write Offs',
+ 'created_at' => 'Created At',
+ 'updated_at' => 'Updated At',
+ 'created_by' => 'Created By',
+ 'updated_by' => 'Updated By',
+ ];
+ }
+}
/* @var $types array */
/* @var $tableWriteOffs array */
/* @var $salesWriteOffsPlan SalesWriteOffsPlan */
+/* @var $isEditable boolean */
+/* @var $categoryPlan array */
$this->registerJsFile('/js/category-plan/index.js', ['position' => \yii\web\View::POS_END]);
+$this->registerCss('
+input[readonly] {
+ background: lightgray;
+}
+');
+
?>
<div class="categoryPlanIndex m-5">
])->label(false) ?>
</div>
</div>
- <?php
- // widget(Select2::class, [
- // 'data' => $stores,
- // 'language' => 'ru',
- // 'options' => ['placeholder' => 'Магазин...'],
- // 'pluginOptions' => [
- // 'allowClear' => true
- // ],
- // 'pluginEvents' => [
- // 'change' => 'function(e) {
- // $("#filter-form").get(0).submit();
- // }'
- // ]
- // ])->label(false)
- ?>
<div class="row mt-1">
<div class="col-4">
<?= $form->field($model, 'month')->dropDownList(HtmlHelper::getMonthNames(), ['onchange' => '//this.form.submit();'])->label(false) ?>
?>
<thead>
<tr><th rowspan="4" class="text-center align-middle border">Категории</th><th colspan="4" class="text-center border">План продаж</th><th colspan="2" class="text-center border">Списания</th></tr>
- <tr><th colspan="2" class="text-center border">Оффлайн</th><th colspan="2" class="text-center border">Интернет-Магазин</th><!--th colspan="2" class="text-center border">Маркетплейс</th--><th colspan="2" class="text-center border">Списания</th></tr>
- <tr><th colspan="2" class="text-center border"><?= number_format($offline_sale, 0, '.', ' ') ?></th>
- <th colspan="2" class="text-center border"><?= number_format($online_sale, 0, '.', ' ') ?></th><!--th colspan="2" class="text-center border">0</th-->
- <th colspan="2" class="text-center border"><?= number_format($write_offs, 0, '.', ' ') ?></th></tr>
- <tr><th class="text-center border">%</th><th class="text-center border">Сумма</th><th class="text-center border">%</th><th class="text-center border">Cумма</th><!--th class="text-center border">%</th><th class="text-center border">Cумма</th--><th class="text-center border">%</th><th class="text-center border">Cумма</th></tr>
+ <tr><th colspan="2" class="text-center border">Оффлайн</th><th colspan="2" class="text-center border">Интернет-Магазин</th><th colspan="2" class="text-center border">Списания</th></tr>
+ <tr><th colspan="2" class="text-center border" data-value="<?= $offline_sale ?>"><?= number_format($offline_sale, 0, '.', ' ') ?></th>
+ <th colspan="2" class="text-center border" data-value="<?= $online_sale ?>"><?= number_format($online_sale, 0, '.', ' ') ?></th>
+ <th colspan="2" class="text-center border" data-value="<?= $write_offs ?>"><?= number_format($write_offs, 0, '.', ' ') ?></th></tr>
+ <tr><th class="text-center border">%</th><th class="text-center border">Сумма</th><th class="text-center border">%</th><th class="text-center border">Cумма</th><th class="text-center border">%</th><th class="text-center border">Cумма</th></tr>
</thead>
<tbody>
<?php foreach ($types as $type): ?>
- <?php $data = $table[$model->store_id][$type] ?? 0; ?>
<tr>
- <th><?= $type ?></th>
- <td><?= number_format($offline_sale <= 0 ? 0 : $data / $offline_sale * 100, 0, '.', ' ') ?>%</td>
- <td><?= number_format($data, 0, '.', ' ') ?></td>
- <?php $data2 = $tableOnline[$model->store_id][$type] ?? 0; ?>
- <td><?= number_format($online_sale <= 0 ? 0 : $data2 / $online_sale * 100, 0, '.', ' ') ?>%</td>
- <td><?= number_format($data2, 0, '.', ' ') ?></td>
- <!--td></td>
- <td></td-->
- <?php $data4 = $tableWriteOffs[$type] ?? 0; ?>
- <td><?= number_format($write_offs <= 0 ? 0 : $data4 / $write_offs * 100, 0, '.', ' ') ?>%</td>
- <td><?= number_format($data4, 0, '.', ' ') ?></td>
+ <th data-type><?= $type ?></th>
+ <?php
+ $data = $categoryPlan[$type]['offline'];
+ $p1 = $offline_sale <= 0 ? 0 : 1.0 * $data / $offline_sale * 100;
+ ?>
+ <td data-p1 data-offline="<?= $offline_sale ?>"><?= number_format($p1, 0, '.', ' ') ?>%</td>
+ <td><?= Html::textInput('offline', number_format($categoryPlan[$type]['offline'], 0, '.', ''), ['type' => 'number', 'readonly' => !$isEditable, 'onchange' => 'editField(this);']) ?></td>
+ <?php
+ $data2 = $categoryPlan[$type]['internet_shop'];
+ $p2 = $online_sale <= 0 ? 0 : $data2 / $online_sale * 100;
+ ?>
+ <td data-p2 data-online="<?= $online_sale ?>"><?= number_format($p2, 0, '.', ' ') ?>%</td>
+ <td><?= Html::textInput('internet_shop', number_format($categoryPlan[$type]['internet_shop'], 0, '.', ''), ['type' => 'number', 'readonly' => !$isEditable, 'onchange' => 'editField(this);']) ?></td>
+ <?php //<td></td><td></td> ?>
+ <?php
+ $data4 = $categoryPlan[$type]['write_offs'];
+ $p3 = $write_offs <= 0 ? 0 : $data4 / $write_offs * 100;
+ ?>
+ <td data-p3 data-writeoffs="<?= $write_offs ?>"><?= number_format($p3, 0, '.', ' ') ?>%</td>
+ <td><?= Html::textInput('write_offs', number_format($categoryPlan[$type]['write_offs'], 0, '.', ''), ['type' => 'number', 'readonly' => !$isEditable, 'onchange' => 'editField(this);']) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
const param26 = $('meta[name=csrf-param]').attr('content');
const token26 = $('meta[name=csrf-token]').attr('content');
+function isNumeric(value) {
+ return /^-?\d+\.?\d*$/.test(value);
+}
+
function updateStores() {
const city_id = $('#dynamicmodel-city_id').val();
const region_id = $('#dynamicmodel-region_id').val();
});
}
+function editField(zis) {
+ const tr = zis.parentNode.parentNode;
+ const store_id = document.querySelector("#selected-store").value;
+ const type = tr.querySelector("[data-type]").textContent;
+ const offline = tr.querySelector("input[name=offline]").value;
+ const internet_shop = tr.querySelector("input[name=internet_shop]").value;
+ const write_offs = tr.querySelector("input[name=write_offs]").value;
+
+ const editFields = [
+ offline,
+ internet_shop,
+ write_offs
+ ];
+
+ let succ = true;
+ editFields.forEach((el) => {
+ if (!isNumeric(el)) {
+ succ = false;
+ alert(el + " не число");
+ console.log(el);
+ }
+ });
+
+ if (succ) {
+ const p1 = tr.querySelector("[data-p1]");
+ const p2 = tr.querySelector("[data-p2]");
+ const p3 = tr.querySelector("[data-p3]");
+ p1.textContent = (p1.dataset.offline > 0 ? Math.round(100.0 * offline / +p1.dataset.offline) : 0) + '%';
+ p2.textContent = (p2.dataset.online > 0 ? Math.round(100.0 * internet_shop / +p2.dataset.online) : 0) + '%';
+ p3.textContent = (p3.dataset.writeoffs > 0 ? Math.round(100.0 * write_offs / +p3.dataset.writeoffs) : 0) + '%';
+
+ $.ajax({
+ method: "POST",
+ url: '/category-plan/save-fields',
+ data: {
+ year: document.querySelector('#dynamicmodel-year').value,
+ month: document.querySelector('#dynamicmodel-month').value,
+ store_id,
+ type,
+ offline,
+ internet_shop,
+ write_offs,
+ [param26]: token26
+ },
+ dataType: "text",
+ success: function(data) {
+ console.log(data);
+ },
+ });
+ }
+
+ return;
+ /*
+ if (succ) {
+ total_sales_plan.value = +offline_sales_plan.value + (+online_sales_shop_plan.value) + (+online_sales_marketplace_plan.value);
+ ////////////////////////////////////////////////
+ const p1 = tr.querySelector('.p1');
+ const p1Value = total_sales_fact.value > 0 ? total_sales_plan.value / total_sales_fact.value : 0;
+ p1.innerHTML = new Intl.NumberFormat().format(Number((p1Value * 100).toFixed(0)));
+ p1.style.color = colorScheme1(p1Value);
+
+ const p2 = tr.querySelector('.p2');
+ const p2Value = total_sales_plan.value > 0 ? write_offs_plan.value / total_sales_plan.value : 0;
+ p2.innerHTML = new Intl.NumberFormat().format(Number((p2Value * 100).toFixed(1)));
+ p2.style.color = colorScheme2(p2Value);
+
+ const p3 = tr.querySelector('.p3');
+ const p3Value = total_sales_fact.value > 0 ? offline_sales_plan.value / total_sales_fact.value : 0;
+ p3.innerHTML = new Intl.NumberFormat().format(Number((p3Value * 100).toFixed(0)));
+ p3.style.color = colorScheme1(p3Value);
+
+ const p4 = tr.querySelector('.p4');
+ const p4Value = total_sales_fact.value > 0 ? online_sales_shop_plan.value / total_sales_fact.value : 0;
+ p4.innerHTML = new Intl.NumberFormat().format(Number((p4Value * 100).toFixed(0)));
+ p4.style.color = colorScheme1(p4Value);
+
+ const p5 = tr.querySelector('.p5');
+ const p5Value = total_sales_fact.value > 0 ? online_sales_marketplace_plan.value / total_sales_fact.value : 0;
+ p5.innerHTML = new Intl.NumberFormat().format(Number((p5Value * 100).toFixed(0)));
+ p5.style.color = colorScheme1(p5Value);
+ ////////////////////////////////////////////////
+ $.ajax({
+ method: "POST",
+ url: '/sales-write-offs-plan/save-fields',
+ data: {
+ year: document.querySelector('#dynamicmodel-year').value,
+ month: document.querySelector('#dynamicmodel-month').value,
+ store_id,
+ total_sales_plan : total_sales_plan.value,
+ total_sales_fact : total_sales_fact.value,
+ write_offs_plan : write_offs_plan.value,
+ offline_sales_plan : offline_sales_plan.value,
+ online_sales_shop_plan : online_sales_shop_plan.value,
+ online_sales_marketplace_plan : online_sales_marketplace_plan.value,
+ [param25]: token25
+ },
+ dataType: "text",
+ success: function(data) {
+ console.log(data);
+ },
+ });
+ }
+ */
+}
+
$(document).ready(() => {
$('#categoryPlan').DataTable({
sorting: false,