创建订单

This commit is contained in:
邓皓元 2019-02-26 21:36:49 +08:00
parent e94efbd8fe
commit cf4d708d57
16 changed files with 347 additions and 95 deletions

View File

@ -36,7 +36,7 @@ class FetchController extends Controller
public function packages(PackageRepository $packageRepository)
{
$type = $this->request->ids('type');
return res($this->search($packageRepository->whereIn('type', $type)), '', 201);
return res($this->search($packageRepository->whereIn('type', $type), ['name', 'carrier_operator']), '', 201);
}
/**
@ -53,7 +53,10 @@ class FetchController extends Controller
$search = $this->request->get('search');
$limit = $this->request->get('limit', 0);
$results = $repository->select([$primaryKey, $field, 'status'])->get();
$field = array_wrap($field);
$field = array_merge([$primaryKey, 'status'], $field);
$results = $repository->select($field)->get();
if ($search) {
$results = $results->filter(function ($item) use ($search, $field) {

View File

@ -107,6 +107,20 @@ class OrderController extends Controller
return res($order, '订单详情', 201);
}
/**
* 下单
*/
public function create()
{
$attributes = $this->request->all();
$attributes['source'] = 1;
$res = $this->orderService->store($attributes);
return res($res, '下单成功');
}
/**
* 编辑.
*

View File

@ -67,6 +67,14 @@ class ProductRepository extends Repository
$query->where('company_id', $conditions['company_id']);
}
if (isset($conditions['package_id'])) {
$query->where('package_id', $conditions['package_id']);
}
if (isset($conditions['price'])) {
$query->where('price', $conditions['price']);
}
if (isset($conditions['status'])) {
$query->where('status', $conditions['status']);
}

View File

@ -96,7 +96,21 @@ class OrderService extends Service
{
$attributes['sn'] = $attributes['sn'] ?: $this->generateSn();
if ($attributes['company_id'] && $attributes['package_id'] && isset($attributes['unit_price'])) {
$attributes['unit_price'] = intval($attributes['unit_price'] * 100);
$product = ProductService::getProduct($attributes['company_id'], $attributes['package_id'], $attributes['unit_price']);
} elseif ($attributes['product_id']) {
$product = app(ProductRepository::class)->find($attributes['product_id']);
}
if (!$product) {
throw new NotExistException('请选择套餐');
}
$attributes['product_id'] = $product->id;
$rule = [
'type' => ['required', 'in:0,1,2,3'],
'company_id' => ['exists:virtual_companies,id'],
'product_id' => [],
'counts' => [],
@ -123,18 +137,17 @@ class OrderService extends Service
$rule['product_id'][] = 'required';
$rule['counts'][] = 'required';
$rule['pay_channel'][] = 'required';
$rule['contacts'][] = 'required';
$rule['mobile'][] = 'required';
$rule['address'][] = 'required';
if (!$attributes['source']) {
$rule['contacts'][] = 'required';
$rule['mobile'][] = 'required';
$rule['address'][] = 'required';
}
}
Validator::validate($attributes, $rule, $message);
if (!$attributes['id']) {
if (!$product = app(ProductRepository::class)->withConditions(['id' => $attributes['product_id']])->first()) {
throw new NotExistException('套餐不存在或已删除');
}
if ($product->company_id != $attributes['company_id']) {
throw new NotAllowedException('非法操作');
}

View File

@ -151,7 +151,7 @@ class PackageService extends Service
public static function load($id)
{
if (!self::$packages) {
self::$packages = app(PackageRepository::class)->select(['id', 'name', 'carrier_operator', 'flows', 'service_months', 'status'])->withTrashed()->get()->keyBy('id');
self::$packages = app(PackageRepository::class)->select(['id', 'sn', 'name', 'carrier_operator', 'flows', 'service_months', 'status'])->withTrashed()->get()->keyBy('id');
}
return self::$packages[$id];

View File

@ -151,4 +151,32 @@ class ProductService extends Service
{
return strtoupper($packageSn . '_' . $companyId . '_' . $price);
}
/**
* 获取定价
*
* @param string $sn
* @return void
*/
public static function getProduct($companyId, $packageId, $price)
{
$package = PackageService::load($packageId);
$product = app(ProductRepository::class)->withConditions([
'company_id' => $companyId,
'package_id' => $packageId,
'price' => $price,
])->first();
if (!$product) {
$product = app(ProductService::class)->store([
'name' => $package['name'] . ' ' . $price,
'company_id' => $companyId,
'package_id' => $package['id'],
'price' => $price/100,
]);
}
return $product;
}
}

View File

@ -90,6 +90,34 @@ class Order extends Model
'extends' => 'array',
];
protected $fillable = [
'id',
'sn',
'source',
'type',
'company_id',
'package_id',
'product_id',
'transaction_no',
'pay_channel',
'unit_price',
'counts',
'total_price',
'custom_price',
'order_at',
'area',
'address',
'contacts',
'mobile',
'logistics_company',
'logistics_no',
'order_status',
'transaction_status',
'logistics_remark',
'remark',
'extends',
];
public function company()
{
return $this->belongsTo(Company::class, 'company_id', 'id');

View File

@ -14,6 +14,7 @@
"blueimp-md5": "^2.10.0",
"file-saver": "^1.3.8",
"iview": "^3.0.1",
"iview-area": "^1.6.0",
"jquery": "^3.3.1",
"js-cookie": "^2.2.0",
"moment": "^2.22.2",

View File

@ -796,7 +796,6 @@ table {
page-break-after: left;
margin-left: 120px;
word-break: break-all;
line-height: 32px;
}
}

View File

@ -2,9 +2,9 @@ import 'iview/dist/styles/iview.css';
import 'css/common.less';
import 'css/layout.less';
import '@riophae/vue-treeselect/dist/vue-treeselect.css';
import Vue from 'vue';
import iView from 'iview';
import iviewArea from 'iview-area';
import Cookies from 'js-cookie';
import Treeselect from '@riophae/vue-treeselect';
import { service, serviceForm } from 'service/service';
@ -29,6 +29,7 @@ Vue.prototype.moment = moment;
Vue.config.productionTip = false;
Vue.use(iView);
Vue.use(iviewArea);
Vue.mixin(mixins);
Vue.mixin(complete);
Vue.use(base);

View File

@ -8,7 +8,7 @@
>
<ui-loading :show="page_loading.show"></ui-loading>
<div class="page-edit-wrap" v-if="flowPool">
<div class="page-detail-wrap" v-if="flowPool">
<Row>
<Divider>基础信息</Divider>
<Col span="12">

View File

@ -13,7 +13,7 @@
<ul>
<li class="ui-list">
<div class="ui-list-title">流量池名称</div>
<div class="ui-list-content">{{data.pool_name}}</div>
<div class="ui-list-content lh-32">{{data.pool_name}}</div>
</li>
<li class="ui-list">
@ -21,21 +21,19 @@
<span class="title-require">*</span>设置年月
</div>
<div class="ui-list-content">
<p>
<DatePicker
type="month"
placeholder="请选择月份"
v-model.trim="params.month"
@on-change="index"
></DatePicker>
</p>
<DatePicker
type="month"
placeholder="请选择月份"
v-model.trim="params.month"
@on-change="index"
></DatePicker>
</div>
</li>
<div v-if="flowPool.setting_status">
<li class="ui-list">
<div class="ui-list-title">月计费总卡数</div>
<div class="ui-list-content">{{data.total}}</div>
<div class="ui-list-content lh-32">{{data.total}}</div>
</li>
<li class="ui-list">
@ -43,9 +41,7 @@
<span class="title-require">*</span>总使用流量
</div>
<div class="ui-list-content">
<p>
<InputNumber :max="99999999" :min="0" v-model="params.total_flows"></InputNumber>M
</p>
<InputNumber :max="99999999" :min="0" v-model="params.total_flows"></InputNumber>M
</div>
</li>
@ -66,7 +62,7 @@
<Col span="4"></Col>
</Row>
<Row v-for="(obj, objIndex) in params.settings" :key="objIndex">
<Row v-for="(item, index) in obj.cards" :key="index">
<Row v-for="(item, index) in obj.cards" :key="index" class="umar-tb5">
<Col span="4">{{!index ? obj.product_name : '&nbsp;'}}</Col>
<Col span="4">
{{!index ? obj.total : '&nbsp;'}}
@ -119,7 +115,13 @@
</div>
<div class="ta-c">
<Button @click="clear" class="w-80 umar-r5" ghost type="primary">取消</Button>
<Button v-if="flowPool.setting_status" :loading="loading" @click="ok" class="w-80" type="primary">提交</Button>
<Button
v-if="flowPool.setting_status"
:loading="loading"
@click="ok"
class="w-80"
type="primary"
>提交</Button>
</div>
</Drawer>
</template>

View File

@ -1,5 +1,12 @@
<template>
<Modal :closable="false" :mask-closable="false" :title="data?'编辑企业':'添加企业'" @on-visible-change="visibleChange" v-model="my_show">
<Drawer
:closable="false"
:mask-closable="false"
:title="data ? '编辑订单' : '创建订单'"
@on-visible-change="visibleChange"
v-model="my_show"
width="500"
>
<div class="page-edit-wrap uinn-lr20">
<ui-loading :show="page_loading.show"></ui-loading>
@ -9,87 +16,125 @@
<span class="title-require">*</span>企业名称:
</div>
<div class="ui-list-content">
<p>
<Input :disabled="data?true:false" v-model.trim="params.name"></Input>
</p>
<ul class="common-tips-wraper umar-t5">
<li class="t-title">提示</li>
<li class="t-content">长度在2-32之间</li>
</ul>
<Select filterable placeholder="企业名称" v-model.trim="params.company_id">
<Option :value="item.id" :key="item.id" v-for="item in companies">{{ item.name }}</Option>
</Select>
</div>
</li>
<li class="ui-list">
<div class="ui-list-title">联系人</div>
<div class="ui-list-title">运营商:</div>
<div class="ui-list-content">
<p>
<Input :maxlength="32" v-model.trim="params.contacts"></Input>
</p>
<ul class="common-tips-wraper umar-t5">
<li class="t-title">提示</li>
<li class="t-content">长度在2-32之间</li>
</ul>
<Select v-model="params.carrier_operator" @on-change="handleChange(1)">
<Option :value="0">联通</Option>
<Option :value="1">移动</Option>
<Option :value="2">电信</Option>
</Select>
</div>
</li>
<li class="ui-list">
<div class="ui-list-title">手机号</div>
<div class="ui-list-title">
<span class="title-require">*</span>选择套餐:
</div>
<div class="ui-list-content">
<Input v-model.trim="params.mobile"></Input>
<Select filterable v-model.trim="params.package_id" @on-change="handleChange(2)">
<Option
:key="item.id"
:value="item.id"
v-for="item in completePackagesFilter"
>{{ item.name }}</Option>
</Select>
</div>
</li>
<li class="ui-list">
<div class="ui-list-title">地址:</div>
<div class="ui-list-title">
<span class="title-require">*</span>支付方式:
</div>
<div class="ui-list-content">
<p>
<Input :maxlength="32" v-model.trim="params.address"></Input>
</p>
<Select placeholder="收款状态" v-model="params.pay_channel">
<Option :value="'bank'">银行转账</Option>
<Option :value="'wx'">微信支付</Option>
<Option :value="'alipay'">支付宝</Option>
</Select>
</div>
</li>
<li class="ui-list">
<div class="ui-list-title">备注:</div>
<div class="ui-list-title">套餐定价</div>
<div class="ui-list-content">
<p>
<Input :maxlength="32" v-model.trim="params.remark"></Input>
</p>
<InputNumber :max="100000" :min="0" :precision="2" v-model.trim="params.unit_price"></InputNumber>
</div>
</li>
<li class="ui-list">
<div class="ui-list-title">银行账号:</div>
<div class="ui-list-title">
<span class="title-require">*</span>订单卡量
</div>
<div class="ui-list-content">
<p>
<Input :maxlength="32" v-model.trim="params.extends.bank_account"></Input>
</p>
<InputNumber :max="100000" :min="1" :precision="0" v-model.trim="params.counts"></InputNumber>
</div>
</li>
<li class="ui-list">
<div class="ui-list-title">微信账号:</div>
<div class="ui-list-title">订单金额</div>
<div
class="ui-list-content lh-32"
>{{Number(params.unit_price * params.counts).toFixed(2)}} </div>
</li>
<li class="ui-list">
<div class="ui-list-title">
<span class="title-require">*</span>订单时间
</div>
<div class="ui-list-content">
<p>
<Input :maxlength="32" v-model.trim="params.extends.wechat_account"></Input>
</p>
<DatePicker type="datetime" placeholder="请选择时间" v-model.trim="params.order_at"></DatePicker>
</div>
</li>
<li class="ui-list">
<div class="ui-list-title">支付宝账号:</div>
<div class="ui-list-title">收货人</div>
<div class="ui-list-content">
<p>
<Input :maxlength="32" v-model.trim="params.extends.alipay_account"></Input>
</p>
<Input :maxlength="32" v-model.trim="params.contacts"></Input>
</div>
</li>
<li class="ui-list">
<div class="ui-list-title">联系电话</div>
<div class="ui-list-content">
<Input :maxlength="11" v-model.trim="params.mobile"></Input>
</div>
</li>
<li class="ui-list">
<div class="ui-list-title">收货区域</div>
<div class="ui-list-content">
<al-selector :data-type="'name'" :level="2" v-model="params.area"/>
</div>
</li>
<li class="ui-list">
<div class="ui-list-title">收货地址</div>
<div class="ui-list-content">
<Input :maxlength="255" v-model.trim="params.address"></Input>
</div>
</li>
<li class="ui-list">
<div class="ui-list-title">订单备注</div>
<div class="ui-list-content">
<Input v-model.trim="params.remark" type="textarea" placeholder="..."/>
</div>
</li>
</ul>
</div>
<footer class="ta-c" slot="footer">
<Button @click="clear" class="w-80" ghost type="primary">取消</Button>
<div class="ta-c">
<Button @click="clear" class="w-80 umar-r5" ghost type="primary">取消</Button>
<Button :loading="loading" @click="ok" class="w-80" type="primary">提交</Button>
</footer>
</Modal>
</div>
</Drawer>
</template>
<script src="./js/edit.js"></script>

View File

@ -10,9 +10,9 @@
</div>
</li>
<li class="f-r">
<!-- <div class="handle-item">
<Button @click="openEdit(true, null)" icon="md-add" type="primary" v-has="'create'">添加企业</Button>
</div>-->
<div class="handle-item">
<Button @click="openEdit(true, null)" icon="md-add" type="primary" v-has="'create'">创建订单</Button>
</div>
<div class="handle-item">
<Button @click="search.show=!search.show" ghost icon="ios-search" type="primary">搜索</Button>
</div>
@ -30,19 +30,43 @@
</li>
<li class="handle-item w-250">
<AutoComplete @on-search="handleCompleteCompanies" icon="ios-search" placeholder="企业名称" v-model.trim="params.company_name">
<Option :key="item.id" :value="item.name" v-for="item in completeHandledCompanies">{{ item.name }}</Option>
<AutoComplete
@on-search="handleCompleteCompanies"
icon="ios-search"
placeholder="企业名称"
v-model.trim="params.company_name"
>
<Option
:key="item.id"
:value="item.name"
v-for="item in completeHandledCompanies"
>{{ item.name }}</Option>
</AutoComplete>
</li>
<li class="handle-item w-250">
<AutoComplete @on-search="handleCompletePackages(type)" icon="ios-search" placeholder="套餐名称" v-model.trim="params.package_name">
<Option :key="item.id" :value="item.name" v-for="item in completeHandledPackages">{{ item.name }}</Option>
<AutoComplete
@on-search="handleCompletePackages(type)"
icon="ios-search"
placeholder="套餐名称"
v-model.trim="params.package_name"
>
<Option
:key="item.id"
:value="item.name"
v-for="item in completeHandledPackages"
>{{ item.name }}</Option>
</AutoComplete>
</li>
<li class="handle-item w-250">
<DatePicker :editable="false" placeholder="请选择时间" placement="bottom-start" type="daterange" v-model.trim="params.time"></DatePicker>
<DatePicker
:editable="false"
placeholder="请选择时间"
placement="bottom-start"
type="daterange"
v-model.trim="params.time"
></DatePicker>
</li>
</ul>
@ -90,10 +114,23 @@
</div>
<div class="page-turn-wrap" v-if="list_data">
<Page :current="Number(list_data.current_page)" :page-size="Number(list_data.per_page)" :total="Number(list_data.total)" @on-change="index" show-elevator show-total></Page>
<Page
:current="Number(list_data.current_page)"
:page-size="Number(list_data.per_page)"
:total="Number(list_data.total)"
@on-change="index"
show-elevator
show-total
></Page>
</div>
<ui-edit :data="editObj.data" :show.sync="editObj.show" @add-success="index" @update-success="index(list_data.current_page)"></ui-edit>
<ui-edit
:data="editObj.data"
:show.sync="editObj.show"
:type="type"
@add-success="index"
@update-success="index(list_data.current_page)"
></ui-edit>
<ui-detail :data="detailObj.data" :show.sync="detailObj.show"></ui-detail>
</div>

View File

@ -1,4 +1,7 @@
import * as API from 'api/virtual/orders';
import {
isPhone
} from 'validate';
export default {
props: {
@ -6,11 +9,13 @@ export default {
type: Boolean,
default: false
},
type: {
type: Number,
default: 0
},
data: {
type: Object,
default() {
return null;
}
default: {}
}
},
data() {
@ -18,17 +23,21 @@ export default {
my_show: false,
isUpdate: false,
loading: false,
companies: [],
completePackagesFilter: [],
params: {
name: '',
contacts: '',
mobile: '',
address: '',
company_id: '',
carrier_operator: '',
package_id: '',
unit_price: 0,
pay_channel: '',
counts: 0,
order_at: '',
remark: '',
extends: {
bank_account: '',
wechat_account: '',
alipay_account: ''
}
area: [],
address: '',
contacts: '',
mobile: ''
}
};
},
@ -36,6 +45,18 @@ export default {
show(bool) {
this.my_show = bool;
if (bool) {
this.initCompleteCompanies().then(companies => {
this.companies = companies.filter(item => {
return item.status === 0;
});
});
this.initCompletePackages(this.type).then(packages => {
this.completePackagesFilter = packages.filter(function(item) {
return item.status === 0;
});
});
if (this.data) {
for (let k in this.data) {
if (k in this.params) {
@ -48,16 +69,43 @@ export default {
},
methods: {
ok() {
if (!this.params.name) {
this.$Message.info('请填写企业名称');
this.params.type = this.type;
if (!this.params.company_id) {
this.$Message.info('请选择企业');
return;
}
if (!(/[\s\S]{2,32}/.test(this.params.contacts))) {
if (!this.params.package_id) {
this.$Message.info('请选择套餐');
return;
}
if (!this.params.pay_channel) {
this.$Message.info('请选择支付方式');
return;
}
if (!this.params.counts) {
this.$Message.info('请输入订单卡量');
return;
}
if (!this.params.order_at) {
this.$Message.info('请选择订单时间');
return;
}
if (this.params.contacts && !(/[\s\S]{2,32}/.test(this.params.contacts))) {
this.$Message.info('联系人长度在2-32之间');
return;
}
if (this.params.mobile && !isPhone(this.params.mobile)) {
this.$Message.info('手机号填写不正确');
return;
}
if (this.data) {
// 编辑
API.update(this.params, this.data.id).then(res => {
@ -97,6 +145,29 @@ export default {
}
this.my_show = false;
},
handleChange(type) {
if (type === 1) {
this.params.package_id = '';
this.initCompletePackages(this.type).then(packages => {
this.completePackagesFilter = packages.filter(item => {
return item.status === 0 && item.carrier_operator === this.params.carrier_operator;
});
});
}
if (type === 2) {
let selectPackage = this.completePackagesFilter.find(item => {
return item.id === this.params.package_id;
});
if (selectPackage) {
this.params.carrier_operator = selectPackage.carrier_operator;
}
}
console.log(type);
console.log(selectPackage);
}
}
};

View File

@ -17,6 +17,7 @@ export default {
carrier_operator: '',
time: []
},
type: 0,
list_data: null,
editObj: {
show: false,
@ -506,6 +507,7 @@ export default {
* @return {[type]} [description]
*/
index(page = 1) {
this.type = Number(this.$route.params.type);
this.params.type = Number(this.$route.params.type);
let data = this.searchDataHandle({}, { page }, this.params);
this.isShowLoading(true);