]> gitweb.erp-flowers.ru Git - erp24_rep/yii-erp24/.git/commitdiff
[ERP-381] inputed cost
authorAlexander Smirnov <fredeom@mail.ru>
Wed, 26 Mar 2025 13:52:45 +0000 (16:52 +0300)
committerAlexander Smirnov <fredeom@mail.ru>
Wed, 26 Mar 2025 13:52:45 +0000 (16:52 +0300)
erp24/controllers/BouquetController.php
erp24/records/BouquetComposition.php
erp24/records/PricesDynamic.php
erp24/views/bouquet/_product_edit.php
erp24/views/bouquet/_product_list.php
erp24/views/bouquet/index.php
erp24/views/bouquet/update.php
erp24/web/js/bouquet/bouquet.js

index a3c31f76054ce516e1d225591c72452f07f258ff..40862fc60c4b90ca0c35da28172a8ec70db8449f 100644 (file)
@@ -65,6 +65,8 @@ class BouquetController extends Controller
         $model = BouquetComposition::findModel($id);
 
         if (Yii::$app->request->isPost && $products = Yii::$app->request->post('products_quantity')) {
+            $cost = Yii::$app->request->post('cost-value');
+            $model->setCost($cost);
             BouquetCompositionProducts::updateProducts($model->id, $products);
             return $this->redirect(['view', 'id' => $id]);
         }
@@ -140,16 +142,16 @@ class BouquetController extends Controller
         ]);
     }
 
-    public function actionGetCalculates()
+    public function actionDefaultCalculates()
     {
         Yii::$app->response->format = Response::FORMAT_JSON;
         $data = json_decode(Yii::$app->request->getRawBody(), true);
-        $model = new BouquetComposition();
+        $model = BouquetComposition::findOne($data['bouquetId']);
 
         return [
             'selfcost' => round($model->getSelfCost($data), 2),
-            'cost' => round($model->getCost($data), 2),
-            'markup' => $model->getMarkUp($data),
+            'cost' => round($model->getBouquetCost($data), 2),
+            'markup' => round($model->getBouquetCostMarkup($data), 2),
         ];
     }
 
@@ -207,4 +209,4 @@ class BouquetController extends Controller
 
         return $this->redirect(Yii::$app->request->referrer);
     }
-}
\ No newline at end of file
+}
index 4b9ba74f64bd731bbc856a8c96b46e5274642c63..c168cca571a71603e9a788319bc10aad3fc0967a 100644 (file)
@@ -317,63 +317,97 @@ class BouquetComposition extends ActiveRecord
         return $this->hasMany(BouquetForecast::class, ['bouquet_id' => 'id']);
     }
 
-    /**
-     * Рассчитывает стоимость букета.
-     *
-     * @param array|null $data Данные продуктов (опционально)
-     * @return float Стоимость
-     */
-    public function getCost(?array $data = null): float
-    {
-        $cost = 0;
-        $compositionProducts = $this->bouquetCompositionProducts;
-
-        if (!$compositionProducts) {
-            $compositionProducts = $data;
-            if (empty($data)) {
-                return $cost;
-            }
-        }
-
-        foreach ($compositionProducts as $item) {
-            if (!$item || !isset($item['product_guid'])) {
-                continue;
-            }
-
-            $priceModel = PricesDynamic::find()
-                ->where(['product_id' => $item['product_guid']])
-                ->andWhere(['=', 'active', PricesDynamic::ACTIVE])
-                ->one();
-
-            if ($priceModel) {
-                $cost += $priceModel->price * $item['count'];
-            }
+//    /**
+//     * Рассчитывает стоимость букета.
+//     *
+//     * @param array|null $data Данные продуктов (опционально)
+//     * @return float Стоимость
+//     */
+//    public function getCost(?array $data = null): float
+//    {
+//        $cost = 0;
+//        $compositionProducts = $this->bouquetCompositionProducts;
+//
+//        if (!$compositionProducts) {
+//            $compositionProducts = $data;
+//            if (empty($data)) {
+//                return $cost;
+//            }
+//        }
+//
+//        foreach ($compositionProducts as $item) {
+//            if (!$item || !isset($item['product_guid'])) {
+//                continue;
+//            }
+//
+//            $priceModel = PricesDynamic::find()
+//                ->where(['product_id' => $item['product_guid']])
+//                ->andWhere(['=', 'active', PricesDynamic::ACTIVE])
+//                ->one();
+//
+//            if ($priceModel) {
+//                $cost += $priceModel->price * $item['count'];
+//            }
+//        }
+//
+//        return $cost;
+//    }
+
+    public function setCost($cost) {
+        $priceModel = PricesDynamic::find()
+            ->where(['product_id' => $this->guid])
+            ->andWhere(['=', 'active', PricesDynamic::ACTIVE])
+            ->one();
+        /* @var PricesDynamic $priceModel */
+        if ($priceModel) {
+            $priceModel->date_to = date('Y-m-d H:i:s');
+            $priceModel->active = PricesDynamic::NOT_ACTIVE;
+            $priceModel->save();
         }
+        $newPriceDynamic = new PricesDynamic;
+        $newPriceDynamic->product_id = $this->guid;
+        $newPriceDynamic->active = PricesDynamic::ACTIVE;
+        $newPriceDynamic->date_from = date('Y-m-d H:i:s');
+        $newPriceDynamic->date_to = date('2100-01-01 00:00:00');
+        $newPriceDynamic->price = $cost;
+        $newPriceDynamic->save();
+    }
 
-        return $cost;
+    public function getBouquetCost($data = null) {
+        $priceModel = PricesDynamic::find()
+            ->where(['product_id' => $this->guid])
+            ->andWhere(['=', 'active', PricesDynamic::ACTIVE])
+            ->one();
+        /* @var PricesDynamic $priceModel */
+        return $priceModel ? $priceModel->price : $this->getSelfCost($data) * 1.3 * 1.15;
     }
 
-    /**
-     * Рассчитывает наценку на букет.
-     *
-     * @param array|null $data Данные продуктов (опционально)
-     * @return string Наценка в формате "+X.XX% / +X.XX"
-     */
-    public function getMarkUp(?array $data = null): string
-    {
+    public function getBouquetCostMarkup($data = null) {
         $selfCost = $this->getSelfCost($data);
-        $cost = $this->getCost($data);
-
-        if ($selfCost == 0 || $cost == 0) {
-            return '0';
-        }
-
-        return sprintf("+%.2f%% / +%.2f",
-            ($cost / $selfCost - 1) * 100,
-            $cost - $selfCost
-        );
+        return $selfCost > 0 ? ($this->getBouquetCost($data) / (1.3 * $selfCost) - 1) * 100 : 0;
     }
 
+//    /**
+//     * Рассчитывает наценку на букет.
+//     *
+//     * @param array|null $data Данные продуктов (опционально)
+//     * @return string Наценка в формате "+X.XX% / +X.XX"
+//     */
+//    public function getMarkUp(?array $data = null): string
+//    {
+//        $selfCost = $this->getSelfCost($data);
+//        $cost = $this->getCost($data);
+//
+//        if ($selfCost == 0 || $cost == 0) {
+//            return '0';
+//        }
+//
+//        return sprintf("+%.2f%% / +%.2f",
+//            ($cost / $selfCost - 1) * 100,
+//            $cost - $selfCost
+//        );
+//    }
+
     /**
      * Рассчитывает себестоимость букета.
      *
index 87386ce6855ad4c280eb0335b0b8daef531ae7d5..43139a582e8dd2b1813279a8a5530ee725f5f606 100755 (executable)
@@ -18,6 +18,7 @@ use Yii;
 class PricesDynamic extends \yii\db\ActiveRecord
 {
     public const ACTIVE = 1;
+    public const NOT_ACTIVE = 0;
     /**
      * {@inheritdoc}
      */
index 3f7d9bf0ba14b053b5740f048eda23a0125106ff..284541a42cbccb84c3d5fe85fcefdbc40e9c2ed5 100644 (file)
@@ -2,6 +2,8 @@
 use yii\helpers\Html;
 use yii_app\records\BouquetComposition;
 
+$this->registerCSS('.cost-value {max-width: 75px}');
+
 ?>
 <?= DualList::widget([
     'name' => 'products',
@@ -25,8 +27,9 @@ use yii_app\records\BouquetComposition;
                 <div class="spinner-border text-primary" role="status"></div>
             </div>
             <p class="mb-1"><strong>Себестоимость:</strong> <span class="selfcost-value"><?= $selfCost ?? 0 ?></span> ₽</p>
-            <p class="mb-1"><strong>Наценка:</strong> <span class="markup-value"><?= $markUp ?? 0 ?></span></p>
-            <p class="mb-0"><strong>Цена:</strong> <span class="cost-value"><?= $cost ?? 0 ?></span> ₽</p>
+            <p class="mb-1"><strong>Наценка:</strong> +30% / +<span class="markup-value"><?= 0.3 * ($selfCost ?? 0) ?></span>₽</p>
+            <p class="mb-0"><strong>Цена:</strong> <input type="number" name="cost-value" class="cost-value" value="<?= $cost ?>"
+                                                          min="<?= 1.3 * ($selfCost ?? 0) ?>" />₽. +<span class="markup-cost-value"><?= $markUp ?></span>%</p>
         </div>
     </div>
 
index d044e165be523401a6c414b2b6d4f42bea3e18b8..3354d6ddba9bfe7e65fb44ffe042c979fa31a2e0 100644 (file)
@@ -31,9 +31,9 @@
     <div class="col-md-8">
         <strong>Нижегородская область</strong>
         <div class='self-cost pt-3' style='display: flex; gap: 10px;'>
-            Себестоимость: <?= $model->getSelfCost() ?> <br>
-            Наценка: <?= $model->getMarkUp() ?> <br>
-            Цена: <?= $model->getCost() ?><br>
+            Себестоимость: <?= $model->getSelfCost() ?><br>
+            Наценка: +30% / +<?= (0.3 * $model->getSelfCost()) ?><br>
+            Цена: <?= $model->getBouquetCost() ?>р. +<?= $model->getBouquetCostMarkup() ?>%<br>
         </div>
     </div>
     <div class="col-md-4">
index 675475e1730818b1315e553619c313ef229450b7..72b7b22433299bc9f12991c8125da54f00a326ee 100644 (file)
@@ -111,8 +111,8 @@ $this->title = 'Содержание матрицы';
                                 </div>
                                 <div class='self-cost pt-3' style='display: flex; gap: 10px;'>
                                     Себестоимость: " . $model->getSelfCost() . "<br>
-                                    Наценка: " . $model->getMarkUp() . "<br>
-                                    Цена: " . $model->getCost() . "<br>
+                                    Наценка: +30% / +" . (0.3 * $model->getSelfCost()) . "<br>
+                                    Цена: " . $model->getBouquetCost() . "р. +" . $model->getBouquetCostMarkup() . "%<br>
                                 </div>
                             </div>
 
index 6fc7ae1eb170ad83ea93dd2d8c88d88cc7067497..0e404d7b444e38f098454a845d50fa325c1d457b 100644 (file)
@@ -17,6 +17,7 @@ $this->title = $model->name;
 $this->params['breadcrumbs'][] = ['label' => 'Букеты', 'url' => ['index']];
 $this->params['breadcrumbs'][] = $this->title;
 
+$this->registerJSVar('bouquetId', $model->id);
 $this->registerJsFile('/js/bouquet/bouquet.js', ['position' => \yii\web\View::POS_END]);
 ?>
 
@@ -60,8 +61,8 @@ $this->registerJsFile('/js/bouquet/bouquet.js', ['position' => \yii\web\View::PO
                 'isCreate' => false,
                 'listContainerSize' => [],
                 'selfCost' => $model->getSelfCost(),
-                'cost' => $model->getCost(),
-                'markUp' => $model->getMarkUp(),
+                'cost' => $model->getBouquetCost(),
+                'markUp' => $model->getBouquetCostMarkup(),
             ]); ?>
             <?php ActiveForm::end(); ?>
         </div>
\ No newline at end of file
index 4d74d0ac6d16584e4dad978505a0052105cec48d..7b39edf8dd67c01b8c5e1313bf263f32a020291a 100644 (file)
@@ -1,3 +1,5 @@
+/* jshint esversion: 6 */
+
 document.addEventListener('DOMContentLoaded', function () {
     document.querySelectorAll('.video-preview').forEach(video => {
         video.addEventListener('click', function () {
@@ -56,7 +58,7 @@ $(document).ready(function () {
 });
 
 $(document).on('click', '.calculate-btn, .btn-add-item, .btn-remove-item', function () {
-    $('.cost-value, .selfcost-value, .markup-value').text('');
+    $('.cost-value, .selfcost-value, .markup-value, .markup-cost-value').text('');
 });
 
 $(document).on('input change', '.quantity-input', function () {
@@ -64,6 +66,11 @@ $(document).on('input change', '.quantity-input', function () {
 });
 
 
+$('.cost-value').on('change', function () {
+    const selfCost = $('.selfcost-value');
+    $('.markup-cost-value').text(+selfCost.text() > 0 ? Math.round((this.value / (1.3 * (+selfCost.text())) - 1)*10000) / 100 : 0);
+});
+
 $('.calculate-btn').on('click', function () {
     let data = [];
 
@@ -84,21 +91,23 @@ $('.calculate-btn').on('click', function () {
     $(".content-wrapper").addClass("position-relative");
 
     $.ajax({
-        url: '/bouquet/get-calculates',
+        url: '/bouquet/default-calculates',
         type: 'POST',
         contentType: 'application/json',
-        data: JSON.stringify(data),
+        data: JSON.stringify({ data, bouquetId }),
         dataType: 'json',
         success: function (response) {
             if (response) {
                 if (response.cost !== undefined) {
-                    $('.cost-value').text(response.cost);
+                    $('.cost-value').val(+response.cost);
                 }
                 if (response.selfcost !== undefined) {
                     $('.selfcost-value').text(response.selfcost);
+                    $('.markup-value').text(0.3 * (+response.selfcost));
+                    $('.cost-value').attr('min', 1.3 * (+response.selfcost));
                 }
                 if (response.markup !== undefined) {
-                    $('.markup-value').text(response.markup);
+                    $('.markup-cost-value').text(+response.markup);
                 }
             }
         },