1557492053 3 år sedan
förälder
incheckning
c2873f80d6

+ 1 - 1
.env

@@ -13,7 +13,7 @@ HOSTPORT = 3306
 CHARSET = utf8
 DEBUG = true
 prefix = erp_
-gg = 8.219.191.124WPDrmPREz36y6mMb
+
 [LANG]
 default_lang = zh-cn
 

+ 3 - 15
app/admin/controller/AuthGroup.php

@@ -16,18 +16,6 @@ class AuthGroup extends BaseController
     private $authService;
     private $departmentModel;
 
-    public $reception_rules = [
-        ["id" => 10001, "zh" => "客户资料", "en" => "Customer information", "icon" => ""],
-        ["id" => 10002, "zh" => "查询业绩", "en" => "Query performance", "icon" => ""],
-        ["id" => 10003, "zh" => "历史订单", "en" => "Historical Orders", "icon" => ""],
-        ["id" => 10004, "zh" => "定金订单", "en" => "Deposit order", "icon" => ""],
-        ["id" => 10005, "zh" => "退货", "en" => "Return goods", "icon" => ""],
-        ["id" => 10006, "zh" => "换货", "en" => "Exchange goods", "icon" => ""],
-        ["id" => 10007, "zh" => "年费管理", "en" => "Annual fee management", "icon" => ""],
-        ["id" => 10008, "zh" => "生成X-report", "en" => "生成X-report", "icon" => ""],
-        ["id" => 10009, "zh" => "生成Z-report", "en" => "生成Z-report", "icon" => ""]
-    ];
-
 
     public function __construct(App $app)
     {
@@ -63,7 +51,7 @@ class AuthGroup extends BaseController
             return $this->ok($res);
         }
         View::assign([
-            "reception_rules"    =>  $this->reception_rules,
+            "reception_rules"    =>  fetchReceptionRules(),
             "all_department"    =>  recursion($all_department, 0)
         ]);
         return view();
@@ -94,10 +82,10 @@ class AuthGroup extends BaseController
             return $this->ok($res);
         }
         $reception_rule_ids = $group->reception_rules ? explode(',',$group->reception_rules) : [];
-        $reception_rules = array_merge([],$this->reception_rules);
+        $reception_rules = array_merge([], fetchReceptionRules());
         foreach ($reception_rules as &$item) $item['isChecked'] = in_array($item['id'], $reception_rule_ids);
         $data_rule_ids = $group->data_rules ? explode(',', $group->data_rules) : [];
-        $data_rules = array_merge([], $this->reception_rules);
+        $data_rules = array_merge([], fetchReceptionRules());
         foreach ($data_rules as &$item) $item['isChecked'] = in_array($item['id'], $data_rule_ids);
         View::assign([
             'group' => $group,

+ 2 - 2
app/admin/controller/Product.php

@@ -71,7 +71,7 @@ class Product extends BaseController
                 'is_upload_numerology'  =>  $params['is_upload_numerology'],
                 'is_gather_annuity' =>  $params["is_gather_annuity"],
                 'annuity'   =>  $params["annuity"],
-                'tax_rate'  =>  $params['tax_rate']
+                'sales_tax_rate'  =>  $params['sales_tax_rate']
             ]);
             return $this->ok($res);
         }
@@ -107,7 +107,7 @@ class Product extends BaseController
                 'is_upload_numerology'  =>  $params['is_upload_numerology'],
                 'is_gather_annuity' =>  $params["is_gather_annuity"],
                 'annuity'   =>  $params["annuity"],
-                'tax_rate'  =>  $params['tax_rate'],
+                'sales_tax_rate'  =>  $params['sales_tax_rate'],
                 'update_time' => time()
             ]);
             return $this->ok($res);

+ 1 - 1
app/admin/view/config/index.html

@@ -15,7 +15,7 @@
                             <div class="layui-form-item">
                                 <label class="layui-form-label">{:lang("Tax rate")}</label>
                                 <div class="layui-input-block">
-                                    <input type="number" value="{$config.tax_rate}" name="tax_rate" lay-verify="required" lay-reqtext="{:lang('Please fill in')}" autocomplete="off" class="layui-input">
+                                    <input type="number" value="{$config.sales_tax_rate}" name="sales_tax_rate" lay-verify="required" lay-reqtext="{:lang('Please fill in')}" autocomplete="off" class="layui-input">
                                 </div>
                             </div>
 

+ 1 - 1
app/admin/view/product/add.html

@@ -101,7 +101,7 @@
                   <div class="layui-form-item">
                     <label class="layui-form-label">{:lang("Tax rate")}</label>
                     <div class="layui-input-block">
-                      <input type="number" value="0.00" name="tax_rate" lay-verify="required" lay-reqtext="{:lang('Please fill in')}" autocomplete="off" class="layui-input">
+                      <input type="number" value="0.00" name="sales_tax_rate" lay-verify="required" lay-reqtext="{:lang('Please fill in')}" autocomplete="off" class="layui-input">
                     </div>
                   </div>
 

+ 1 - 1
app/admin/view/product/edit.html

@@ -103,7 +103,7 @@
                   <div class="layui-form-item">
                       <label class="layui-form-label">{:lang("Tax rate")}</label>
                       <div class="layui-input-block">
-                          <input type="number" value="{$product.tax_rate}" name="tax_rate" lay-verify="required" lay-reqtext="{:lang('Please fill in')}" autocomplete="off" class="layui-input">
+                          <input type="number" value="{$product.sales_tax_rate}" name="sales_tax_rate" lay-verify="required" lay-reqtext="{:lang('Please fill in')}" autocomplete="off" class="layui-input">
                       </div>
                   </div>
 

+ 1 - 1
app/admin/view/product/index.html

@@ -116,7 +116,7 @@
                                 <td>{$item.purchase_price}</td>
                                 <td>{$item.real_price}</td>
                                 <td>{$item.lineate_price}</td>
-                                <td>{$item.tax_rate}</td>
+                                <td>{$item.sales_tax_rate}</td>
                                 <td>{if $item.is_upload_numerology == 1} {:lang("Yes")}{else /}{:lang("No")}{/if}</td>
                                 <td>{if $item.is_gather_annuity == 1} {:lang("Yes")}{else /}{:lang("No")}{/if}</td>
                                 <td>{if $item.is_gather_annuity == 1}{$item.annuity}{else /}/{/if}</td>

+ 5 - 0
app/api/controller/Admin.php

@@ -25,5 +25,10 @@ class Admin extends BaseController
         return $this->ok($res);
     }
 
+    public function fetchMenus(Request $request) {
+        $params = $request->param();
+        $res = $this->service->fetchMenus($params['admin_id']);
+        return $this->ok($res);
+    }
 
 }

+ 86 - 0
app/api/controller/Order.php

@@ -0,0 +1,86 @@
+<?php
+
+
+namespace app\api\controller;
+
+
+use app\api\service\OrderService;
+use app\api\validate\CreateOrderValidate;
+use app\exception\BaseException;
+use think\App;
+
+class Order extends \app\BaseController
+{
+    private $service;
+
+    public function __construct(App $app)
+    {
+        $this->service = new OrderService();
+        parent::__construct($app);
+    }
+
+    /**
+     * @return \think\response\Json
+     * @throws BaseException
+     */
+    public function create() {
+        $params = (new CreateOrderValidate())->message([
+            'store_id.require'  =>  lang("Stores do not exist"),
+            'customer_id.require'  =>  lang("Customer do not exist"),
+            'products.require'  =>  lang("Products do not exist"),
+        ])->requestBodyCheck($this->request);
+
+        $products = json_decode($params['products']);
+        predicate($products != null, 'products 解析错误');
+
+        for ($i = 0; $i < count($products); $i++) {
+            $product = $products[$i];
+            predicate(isset($product->store_product_id) && $product->store_product_id > 0, '商品ID错误!');
+            predicate($product->quantity > 0, '商品数量错误!');
+            predicate($product->adviser_1_id > 0, '销售顾问1必须存在!');
+            if(isset($product->adviser_2_id)) predicate($product->adviser_2_id > 0, '销售顾问2不符合规则!');
+            if(isset($product->teacher_id)) predicate($product->teacher_id > 0, '老师不符合规则!');
+        }
+        $res = $this->service->create($params, $products);
+        predicate($res->bool,$res->message);
+        return $this->ok($res->data);
+    }
+
+    /**
+     * @return \think\response\Json
+     * @throws BaseException
+     */
+    public function payment() {
+        $params = $this->request->param();
+        if(!isset($params['order_id'])) {
+            return $this->fail("订单ID不存在!");
+        }
+        if(!isset($params['channels'])) {
+            return $this->fail("支付记录不存在!");
+        }
+        $channels = json_decode($params['channels']);
+        predicate($channels != null, 'channels 解析错误');
+        for ($i = 0; $i < count($channels); $i++) {
+            $channel = $channels[$i];
+            predicate(isset($channel->channel_id) && $channel->channel_id > 0, '支付渠道错误!');
+            if (isset($channel->fee)) {
+                predicate($channel->fee > 0, '支付费用错误!');
+            }
+            if (isset($channel->credit_card)) {
+                predicate(is_array($channel->credit_card), 'credit_card 不符合规则!');
+                for ($j = 0; $j < count($channel->credit_card); $j++) {
+                    $credit_card = $channel->credit_card[$j];
+                    predicate(isset($credit_card->credit_card_id) && $credit_card->credit_card_id > 0, '信用卡配置id错误!');
+                    predicate($credit_card->fee > 0, '支付费用错误!');
+                    if (isset($credit_card->stage_num)) predicate(in_array($credit_card->stage_num,[6, 9, 12, 24, 36]), '分期数不符合规则!');
+                }
+            }
+        }
+        $res = $this->service->payment($params, $channels);
+        predicate($res->bool,$res->message);
+        return $this->ok($res->data);
+    }
+
+
+
+}

+ 28 - 0
app/api/controller/Payment.php

@@ -0,0 +1,28 @@
+<?php
+
+
+namespace app\api\controller;
+
+
+use app\api\service\PaymentService;
+use app\exception\BaseException;
+use think\App;
+
+class Payment extends \app\BaseController
+{
+    private $service;
+
+    public function __construct(App $app)
+    {
+        $this->service = new PaymentService();
+        parent::__construct($app);
+    }
+
+    /**
+     * @return \think\response\Json
+     * @throws BaseException
+     */
+    public function channels() {
+       return $this->ok($this->service->channels());
+    }
+}

+ 4 - 0
app/api/lang/zh-cn.php

@@ -40,6 +40,10 @@ return [
     'The sun_calendar does not comply with the rule'       =>  "阳历不符合规则",
     'The lunar_calendar does not comply with the rule'       =>  "阴历不符合规则",
     "Please enter the Zue Coin expiration time" =>  "请填写御龙币失效时间",
+    "The role Product does not exist" => "商品不存在",
+    "The store does not exist"  =>  "门店不存在",
+    "The Adviser|Teacher does not exist"    =>  "顾问或者老师不存在!",
+    "Stores do not exist"           =>  "门店不存在",
 ];
 
 

+ 52 - 0
app/api/route/app.php

@@ -18,5 +18,57 @@ Route::group('api/customer', function () {
 
 Route::group('api/user', function () {
     Route::rule('search', 'api/admin/search');
+    Route::rule('fetchMenus', 'api/admin/fetchMenus');
 })->middleware(\app\common\middleware\VerifySessionToken::class);
 
+
+Route::group('api/order', function () {
+    Route::rule('create', 'api/order/create');
+    Route::rule('payment', 'api/order/payment');
+})->middleware(\app\common\middleware\VerifySessionToken::class);
+
+Route::group('api/payment', function () {
+    Route::rule('channels', 'api/payment/channels');
+})->middleware(\app\common\middleware\VerifySessionToken::class);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 43 - 1
app/api/service/AdminService.php

@@ -4,7 +4,9 @@
 namespace app\api\service;
 
 
+use app\admin\controller\AuthGroup;
 use app\common\model\AdminModel;
+use app\common\model\AuthGroupModel;
 use app\common\model\StoreModel;
 
 class AdminService extends \app\BaseService
@@ -44,4 +46,44 @@ class AdminService extends \app\BaseService
     }
 
 
-}
+    public function fetchMenus($admin_id) {
+        $admin = $this->adminModel->findById($admin_id);
+        $group = $admin['access']['group'];
+        $fmt_reception_rules = [];
+        foreach (fetchReceptionRules() as $rule) {
+            $fmt_reception_rules[$rule['id']] = $rule;
+        }
+        $reception_rule_ids = $group->reception_rules ? explode(',', $group->reception_rules) : [];
+        return array_map(function ($id) use($fmt_reception_rules) {
+            return $fmt_reception_rules[$id];
+        },$reception_rule_ids);
+
+
+
+
+    }
+
+
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 375 - 0
app/api/service/OrderService.php

@@ -0,0 +1,375 @@
+<?php
+
+
+namespace app\api\service;
+
+
+use app\common\model\ActivityProductModel;
+use app\common\model\AdminModel;
+use app\common\model\ConfigModel;
+use app\common\model\CreditCardConfigModel;
+use app\common\model\CustomerModel;
+use app\common\model\OrderAnnualFeeModel;
+use app\common\model\OrderModel;
+use app\common\model\OrderPaymentModel;
+use app\common\model\OrderProceedsModel;
+use app\common\model\OrderProductModel;
+use app\common\model\PaymentChannelModel;
+use app\common\model\ProductModel;
+use app\common\model\StoreModel;
+use app\common\model\StoreProductModel;
+use think\facade\Db;
+
+class OrderService extends \app\BaseService
+{
+    private $storeModel;
+    private $orderModel;
+    private $productModel;
+    private $orderAnnualFeeModel;
+    private $orderPaymentModel;
+    private $orderProductModel;
+    private $orderProceedsModel;
+    private $activityProductModel;
+    private $storeProductModel;
+    private $configModel;
+    private $adminModel;
+    private $customerModel;
+    private $paymentChannelModel;
+    private $creditCardModel;
+
+    public function __construct()
+    {
+        $this->storeModel = new StoreModel();
+        $this->orderModel = new OrderModel();
+        $this->productModel = new ProductModel();
+        $this->configModel = new ConfigModel();
+        $this->storeProductModel = new StoreProductModel();
+        $this->orderAnnualFeeModel = new OrderAnnualFeeModel();
+        $this->orderPaymentModel = new OrderPaymentModel();
+        $this->orderProductModel = new OrderProductModel();
+        $this->orderProceedsModel = new OrderProceedsModel();
+        $this->activityProductModel = new ActivityProductModel();
+        $this->adminModel = new AdminModel();
+        $this->customerModel = new CustomerModel();
+        $this->paymentChannelModel = new PaymentChannelModel();
+        $this->creditCardModel = new CreditCardConfigModel();
+    }
+
+    /**
+     * @param $params
+     * @param array $store_products_params
+     * @return \SResult
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     */
+    public function create($params, array $store_products_params) {
+        // 客户
+        $customer = $this->customerModel->findById($params['customer_id']);
+        if (!$customer)
+            return $this->fail(lang("The Customer does not exist"));
+        // 门店
+        $store = $this->storeModel->findById($params['store_id']);
+        if (!$store)
+            return $this->fail(lang("The store does not exist"));
+        // 顾问 or 老师 ids
+        $user_ids = [];
+        // 门店商品ids
+        $store_product_ids = [];
+        for ($i = 0; $i < count($store_products_params); $i++) {
+            $store_products_param = $store_products_params[$i];
+            $ids = [];
+            if(isset($store_products_param->adviser_1_id)) array_push($ids, $store_products_param->adviser_1_id);
+            if(isset($store_products_param->adviser_2_id)) array_push($ids, $store_products_param->adviser_2_id);
+            if(isset($store_products_param->teacher_id)) array_push($ids, $store_products_param->teacher_id);
+            $user_ids = array_unique(array_merge($user_ids, $ids));
+            array_push($store_product_ids, $store_products_param->store_product_id);
+        }
+        // Adviser|Teacher
+        $users = $this->adminModel->findByIds($user_ids)->toArray();
+        if(count($users) != count($user_ids))
+            return $this->fail(lang("The Adviser|Teacher does not exist"));
+        $fmt_users = array_reduce($users, function ($result, $item) {
+            $result[$item['id']] = $item;
+            return $result;
+        }, []);
+        // 门店商品
+        $store_products = $this->storeProductModel->fetchRelationsByOrder($store_product_ids)->toArray();
+        if(count($store_products) != count($store_product_ids))
+            return $this->fail(lang("The Product does not exist"));
+        // 商品信息
+        $products = array_map(function ($p) {
+            return $p['product'] ? $p['product'] : null;
+        }, $store_products);
+        if(in_array(null, $products))
+            return $this->fail(lang("The Product does not exist"));
+
+        $config = $this->configModel->findConfig();
+        $activityProducts = $this->activityProductModel->fetchByProductIds(array_map(function ($data) {
+            return $data['id'];
+        }, $products))->toArray();
+        $fmt_store_products = [];
+        foreach ($store_products as &$item) {
+            $aProducts = array_filter($activityProducts, function ($aProduct) use ($item) {
+                return $aProduct['product_id'] == $item['product_id'];
+            });
+            $res = compare($item['product']['real_price'] ?? 0, $aProducts);
+            $item['activity'] = $res['item'];
+            $item['product']['origin_price'] = $item['product']['real_price'];
+            $item['product']['real_price'] = fixed2Float($res['min_num'] > 0 ? $res['min_num'] : 0);
+            $sales_tax_rate = $item['product']['sales_tax_rate'] > 0 ? $item['product']['sales_tax_rate'] : $config->sales_tax_rate;
+            $sales_tax = fixed2Float($sales_tax_rate > 0 && $item['product']['real_price'] > 0 ? ($item['product']['real_price'] * ($sales_tax_rate / 100)) : 0);
+            $item['product']['sales_tax_rate'] = $sales_tax_rate;
+            $item['product']['sales_tax'] = $sales_tax;
+            $fmt_store_products[$item['id']] = $item;
+        }
+        $order_products = [];
+        //项目总额
+        $rental_amount = 0;
+        // 总消费税
+        $total_sales_tax = 0;
+        $advisor_1_ids = [];
+        for ($i = 0; $i < count($store_products_params); $i++) {
+            $store_products_param = $store_products_params[$i];
+            $store_product = $fmt_store_products[$store_products_param->store_product_id];
+            array_push($advisor_1_ids, $store_products_param->adviser_1_id);
+            for ($j = 0; $j < $store_products_param->quantity; $j++) {
+                array_push($order_products, [
+                    'order_id' => 0,
+                    'product_id' => $store_product['product']['id'],
+                    'product_name' => $store_product['product']['name'],
+                    'adviser_1_id' => isset($store_products_param->adviser_1_id) ?? null,
+                    'adviser_1_name'  => isset($store_products_param->adviser_1_id) ? $fmt_users[$store_products_param->adviser_1_id]['nickname'] : null,
+                    'adviser_2_id' => isset($store_products_param->adviser_2_id) ?? null,
+                    'adviser_2_name'  => isset($store_products_param->adviser_2_id) ? $fmt_users[$store_products_param->adviser_2_id]['nickname'] : null,
+                    'teacher_id' => isset($store_products_param->teacher_id) ?? null,
+                    'teacher_name'  => isset($store_products_param->teacher_id) ? $fmt_users[$store_products_param->teacher_id]['nickname'] : null,
+                    'report'    => null,
+                    'real_price'    =>  $store_product['product']['real_price'],
+                    'service_charge'    => 0,
+                    'reduce_price'    => $store_product['activity'] ? $store_product['product']['origin_price'] - $store_product['product']['real_price'] : 0,
+                    'reduce_type'    => $store_product['activity'] ? $store_product['activity']['type'] : 0,
+                    'sales_tax_rate' => $store_product['product']['sales_tax_rate'],
+                    'sales_tax' => $store_product['product']['sales_tax'],
+                    'create_time' => time(),
+                    'update_time' => time(),
+                ]);
+                $rental_amount += $store_product['product']['real_price'];
+                $total_sales_tax += $store_product['product']['sales_tax'];
+            }
+        }
+        $order = $this->orderModel->create([
+            'no' => $this->orderModel->genOrderNo($store->id, $store->abbr),
+            'customer_id' => $customer->id,
+            'customer_name' => $customer->name_en,
+            'rental_amount' => $rental_amount,
+            'receivable_amount' =>  $rental_amount,
+            'receive_amount'    =>  0,
+            'imposed_amount'    =>  $rental_amount,
+            'total_sales_tax'   =>  $total_sales_tax,
+            'type'  =>  2,
+            'store_id'  =>  $store->id,
+            'advisor_ids' => join(',', $advisor_1_ids),
+            'create_time' => time(),
+            'update_time' => time()
+        ]);
+        foreach ($order_products as &$order_product) $order_product['order_id'] = $order->id;
+        Db::startTrans();
+        try {
+            Db::table('erp_order_product')->insertAll($order_products);
+            Db::commit();
+        } catch (\Exception $e) {
+            Db::rollback();
+            Db::table('erp_order')->delete($order->id);
+            return $this->fail(lang($e->getMessage()));
+        }
+        return $this->ok($order);
+    }
+
+
+    /**
+     * @param $params
+     * @param $channels
+     * @return \SResult
+     * @throws \app\exception\BaseException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     */
+    public function payment($params, $channels) {
+        $order = $this->orderModel->findById($params);
+        if(!$order)
+            return $this->fail('订单不存在!');
+        if($order->type == 1)
+            return $this->fail('订单状态为历史订单!不支持付款');
+
+        $pay_channels = $this->paymentChannelModel->where('is_delete', 0)->select()->toArray();
+        $fmt_pay_channels = array_reduce($pay_channels, function ($result, $item) {
+            $result[$item['id']] = $item;
+            return $result;
+        },[]);
+        $credit_card_configs = $this->creditCardModel->findAll()->toArray();
+        $fmt_credit_card_configs = array_reduce($credit_card_configs, function ($result, $item) {
+            $result[$item['id']] = $item;
+            return $result;
+        },[]);
+
+
+        // 总计支付费用
+        $total_fee = 0;
+        // 信用卡支付手续费
+        $service_charge = 0;
+        // 御龙币
+        $zue_coin = 0;
+        $order_payments = [];
+        $record_channel_names = [];
+        for ($i = 0; $i < count($channels); $i++) {
+            $channel = $channels[$i];
+            $fmt_pay_channel = $fmt_pay_channels[$channel->channel_id];
+            if (!$fmt_pay_channel)
+                return $this->fail("支付渠道错误!");
+            array_push($record_channel_names, '['.$fmt_pay_channel['name'].']');
+            $item = [
+                'order_id' => $order->id,
+                'channel_id' => $channel->channel_id,
+                'create_time' => time(),
+                'update_time' => time(),
+            ];
+            if ($fmt_pay_channel['type'] == 1) { // 正常支付
+                predicate(isset($channel->fee) && $channel->fee > 0, '支付费用未填写');
+                $item['fee'] = $channel->fee;
+                $total_fee += $channel->fee;
+                if ($fmt_pay_channel['is_upload_code']) {
+                    predicate(isset($channel->code),'必须上传付款编号');
+                    $item['code'] = $channel->code;
+                }
+                array_push($order_payments, $item);
+
+            } else if($fmt_pay_channel['type'] == 2) { // 御龙币支付
+                predicate(isset($channel->fee) && $channel->fee > 0, '支付费用未填写');
+                $item['fee'] = $channel->fee;
+                // TODO: 御龙币需求未明确
+                array_push($order_payments, $item);
+            } else {
+                for ($j = 0; $j < count($channel->credit_card); $j++) {
+                    $credit_card = $channel->credit_card[$j];
+                    $fmt_credit_card_config = $fmt_credit_card_configs[$credit_card->credit_card_id];
+                    if (!$fmt_credit_card_config)
+                        return $this->fail("信用卡支付渠道错误!");
+                    predicate(isset($credit_card->fee) && $credit_card->fee > 0, '支付费用未填写');
+                    $total_fee += $credit_card->fee;
+                    $el = [
+                        'order_id' => $order->id,
+                        'channel_id' => $channel->channel_id,
+                        'fee'   => $credit_card->fee,
+                        'credit_card_id' => $credit_card->credit_card_id,
+                        'credit_card_name' => $fmt_credit_card_config['bank'],
+                        'create_time' => time(),
+                        'update_time' => time(),
+                    ];
+                    if ($fmt_pay_channel['is_upload_code']) {
+                        predicate(isset($credit_card->code),'必须填写付款编号');
+                        $el['code'] = $credit_card->code;
+                    }
+                    if ($fmt_credit_card_config['is_stage'] == 1) {
+                        predicate(isset($credit_card->stage_num),'必须选择分期数');
+                        $el['stage_num'] = $credit_card->stage_num;
+                        $config = [
+                            '6' => $fmt_credit_card_config['stage_6'],
+                            '9' => $fmt_credit_card_config['stage_9'],
+                            '12' => $fmt_credit_card_config['stage_12'],
+                            '24' => $fmt_credit_card_config['stage_24'],
+                            '36' => $fmt_credit_card_config['stage_36'],
+                        ];
+                        $now_config = $config[$credit_card->stage_num];
+                        predicate($now_config[0] == 1,'该分期未启用!');
+                        if ($now_config[1] > 0) { // 收取手续费
+                            $el['service_charge_rate'] = $now_config[1];
+                            $now_service_charge = $el['fee'] * ($now_config[1] / 100);
+                            $el['service_charge'] = $now_service_charge;
+                            $service_charge += $now_service_charge;
+                        }
+                    }
+                    array_push($order_payments, $el);
+                }
+            }
+        }
+
+        // 总共需要收取这么多费用;
+        $imposed_amount = fixed2Float($order->imposed_amount + $service_charge + $order->total_sales_tax);
+        $total_fee = fixed2Float($total_fee);
+        if (round($total_fee) > round($imposed_amount)) return $this->fail("实收金额大于待收金额! 应该支付 {$imposed_amount}");
+        return $this->ok($total_fee);
+        Db::startTrans();
+        try {
+            Db::table('erp_order_payment')->insertAll($order_payments);
+            Db::table('erp_order_proceeds')->save([
+                'order_id' => $order->id,
+                'channels' => join(' ',$record_channel_names),
+                'fee'   =>  $total_fee,
+                'admin_id' => $params['admin_id'],
+                'admin_name' => $params['admin_name'],
+                'create_time' => time(),
+                'update_time' => time(),
+            ]);
+            $update_order = [
+                'service_charge_amount' => $service_charge,
+                'receive_amount' => $order->receive_amount + $total_fee,
+                'imposed_amount' => $order->imposed_amount - $total_fee,
+            ];
+            if (round($total_fee) < round($imposed_amount)) { // 未支付满
+//                DOTO:
+            } else {
+                $update_order['type'] = 2;
+            }
+            Db::table('erp_order')->where('id',$order->id)->update($update_order);
+            Db::commit();
+        } catch (\Exception $e) {
+            Db::rollback();
+            return $this->fail(lang($e->getMessage()));
+        }
+        return $this->ok(true);
+    }
+
+
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 72 - 0
app/api/service/PaymentService.php

@@ -0,0 +1,72 @@
+<?php
+
+
+namespace app\api\service;
+
+
+use app\common\model\PaymentChannelModel;
+
+class PaymentService extends \app\BaseService
+{
+    private $paymentChannel;
+
+
+    public function __construct()
+    {
+        $this->paymentChannel = new PaymentChannelModel();
+    }
+
+    public function channels() {
+        $channels = $this->paymentChannel->findAll()->toArray();
+        return array_map(function ($channel) {
+            $fmt = [
+                "id" => $channel['id'],
+                'name' => $channel['name'],
+                'icon' => $channel['icon'],
+                'type' => $channel['type'],
+                'is_upload_code' => $channel['is_upload_code'],
+                'credit_card_config' => [],
+            ];
+            if($channel['type'] == 2) {
+                $fmt['zue_coin_exchange_rate'] = $channel['zue_coin_exchange_rate'];
+                $fmt['zue_coin_consume_rate'] = $channel['zue_coin_consume_rate'];
+            } else if($channel['type'] == 3) {
+                $disposables = [];
+                $stages = [];
+               foreach ($channel['relation'] as $item) {
+                   $credit_config = [
+                       'id' => $item['id'],
+                       'bank' => $item['bank'],
+                   ];
+                   if($item['is_stage'] == 1) {
+                       $credit_config['periods'] = [];
+                       if($item['stage_6'][0]  == 1) {
+                           array_push($credit_config['periods'], ['nper' => 6, 'service_charge_rate' => (int)$item['stage_6'][1]]);
+                       }
+                       if($item['stage_9'][0]  == 1) {
+                           array_push($credit_config['periods'], ['nper' => 9, 'service_charge_rate' => (int)$item['stage_9'][1]]);
+                       }
+                       if($item['stage_12'][0]  == 1) {
+                           array_push($credit_config['periods'], ['nper' => 12, 'service_charge_rate' => (int)$item['stage_12'][1]]);
+                       }
+                       if($item['stage_24'][0]  == 1) {
+                           array_push($credit_config['periods'], ['nper' => 24, 'service_charge_rate' => (int)$item['stage_24'][1]]);
+                       }
+                       if($item['stage_36'][0]  == 1) {
+                           array_push($credit_config['periods'], ['nper' => 36, 'service_charge_rate' => (int)$item['stage_36'][1]]);
+                       }
+                       array_push($stages, $credit_config);
+                   } else {
+                       array_push($disposables, $credit_config);
+                   }
+               }
+               $fmt['relation'] = ['disposables' =>$disposables, "stages" => $stages ];
+            }
+            return $fmt;
+        }, $channels);
+    }
+
+
+
+
+}

+ 5 - 28
app/api/service/ProductService.php

@@ -45,39 +45,16 @@ class ProductService extends BaseService
             $aProducts = array_filter($activityProducts, function ($aProduct) use ($item) {
                 return $aProduct['product_id'] == $item['product_id'];
             });
-            $res = $this->compare($item['product']['real_price'] ?? 0, $aProducts);
+            $res = compare($item['product']['real_price'] ?? 0, $aProducts);
             $item['product']['real_price'] = fixed2Float($res['min_num']);
             $item['activity'] = $res['item'];
-            $item['product']['tax_rate'] = $item['product']['tax_rate'] > 0 ? $item['product']['tax_rate'] : $config->tax_rate;
+            $sales_tax_rate = $item['product']['sales_tax_rate'] > 0 ? $item['product']['sales_tax_rate'] : $config->sales_tax_rate;
+            $sales_tax = fixed2Float($sales_tax_rate > 0 && $item['product']['real_price'] > 0 ? ($item['product']['real_price'] * ($sales_tax_rate / 100)) : 0);
+            $item['product']['sales_tax_rate'] = $sales_tax_rate;
+            $item['product']['sales_tax'] = $sales_tax;
         }
         return [$items, $storeProducts->total()];
     }
 
 
-    private function compare($num, $array) {
-        $min_num = $num;
-        $index = null;
-        if($num > 0) {
-            foreach ($array as $key => $el) {
-                $now_price = $num;
-                if($el['type'] == 1) {
-                    $now_price = $num - $el['reduced_price'];
-                } else {
-                    if($el['discount'] > 0) {
-                        $now_price = $num - ($num * ($el['discount'] / 100));
-                    }
-                }
-                if($min_num == null) {
-                    $min_num = $now_price;
-                } else {
-                    if($now_price < $min_num) {
-                        $min_num = $now_price;
-                        $index = $key;
-                    }
-                }
-            }
-        }
-        return ['min_num' => $min_num, 'item' => $index == null ? null : $array[$index]];
-    }
-
 }

+ 14 - 0
app/api/validate/CreateOrderValidate.php

@@ -0,0 +1,14 @@
+<?php
+
+
+namespace app\api\validate;
+
+
+class CreateOrderValidate extends \app\common\validate\BaseValidate
+{
+    protected $rule = [
+        'store_id'   =>  'require|between:1,19999999999',
+        'customer_id'   =>  'require|between:1,19999999999',
+        'products'    =>  'require'
+    ];
+}

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 39 - 2
app/common.php


+ 5 - 0
app/common/model/CreditCardConfigModel.php

@@ -34,4 +34,9 @@ class CreditCardConfigModel extends BaseModel
         return json_decode($value);
     }
 
+    public function findAll() {
+        return $this->where('is_delete', 0)
+            ->select();
+    }
+
 }

+ 8 - 0
app/common/model/OrderModel.php

@@ -12,6 +12,14 @@ class OrderModel extends BaseModel
         // TODO: Implement genSchema() method.
     }
 
+    public function genOrderNo($store_id, $store_abbr) {
+        $order = $this->where('store_id', $store_id)->order('id','desc')->find();
+        if(!$order)
+            return "{$store_abbr}10000001";
+        $code = (int)str_ireplace($store_abbr, '', $order->no) + 1;
+        return "{$store_abbr}{$code}";
+    }
+
     public function products() {
         return $this->hasMany(OrderProductModel::class, 'order_id','id')->where('is_delete',0);
     }

+ 4 - 1
app/common/model/PaymentChannelModel.php

@@ -18,7 +18,10 @@ class PaymentChannelModel extends BaseModel
     }
 
     public function findAll() {
-        return $this->where('is_delete', 0)->order("id", "desc")->select();
+        return $this->where('is_delete', 0)
+            ->with('relation')
+            ->order("id", "Asc")
+            ->select();
     }
 
     public function findById($id)

+ 10 - 0
app/common/model/StoreProductModel.php

@@ -82,6 +82,16 @@ class StoreProductModel extends BaseModel
             ->paginate($params['size'] ?? 10);
     }
 
+    public function fetchRelationsByOrder($ids = []) {
+        $where = [
+            ['id', 'in', $ids],
+            ['is_delete', '=', 0]
+        ];
+        return $this->where($where)
+            ->with('product')
+            ->select();
+    }
+
 
 
 }

+ 40 - 1
public/static/js/common.js

@@ -162,4 +162,43 @@ function deepTraversal(tree = []){
         })
     }
     return nodes;
-}
+}
+
+
+function f() {
+    const channels = [
+        {
+            "channel_id": "1",
+            "fee": 100,
+            "code": "编号",
+            "credit_card": [
+                {
+                    "credit_card_id": 1,
+                    "fee": 0,
+                    "code": "编号",
+                    "stage_num": 6,
+                }
+            ]
+        }
+    ]
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

BIN
public/storage/icon/1.png


BIN
public/storage/icon/10.png


BIN
public/storage/icon/11.png


BIN
public/storage/icon/2.png


BIN
public/storage/icon/3.png


BIN
public/storage/icon/4.png


BIN
public/storage/icon/5.png


BIN
public/storage/icon/6.png


BIN
public/storage/icon/7.png


BIN
public/storage/icon/8.png


BIN
public/storage/icon/9.png