Quellcode durchsuchen

主动报价

git-svn-id: svn+ssh://10.10.101.21/source/platform/platform-b2b@1157 f3bf4e98-0cf0-11e4-a00c-a99a8b9d557d
suntg vor 10 Jahren
Ursprung
Commit
faf9605a5c

+ 325 - 2
src/main/webapp/resources/js/index/app.js

@@ -69,6 +69,10 @@ define([ 'toaster', 'charts', 'ngTable', 'common/services', 'service/Purc', 'ser
 			url : "/customer",
 			templateUrl : "static/tpl/index/sale/customer.html",
 			controller: 'CustomerCtrl'
+		}).state('sale.customerProduct', {
+			url : "/customerProduct",
+			templateUrl : "static/tpl/index/sale/customer.html",
+			controller: 'CustomerCtrl'
 		}).state('sale.inquiry', {
 			url : "/inquiry",
 			templateUrl : "static/tpl/index/sale/inquiry.html",
@@ -79,8 +83,19 @@ define([ 'toaster', 'charts', 'ngTable', 'common/services', 'service/Purc', 'ser
 			controller: 'SaleInquiryDetailCtrl'
 		}).state('sale.quotation', {
 			url : "/quotation",
-			templateUrl : "static/tpl/index/sale/quotation.html",
-			controller: 'SaleInquiryCtrl'
+			templateUrl : "static/tpl/index/sale/quotation.html"
+		}).state('sale.quotation.new', {
+			url : "/new",
+			templateUrl : "static/tpl/index/sale/quotation_new.html",
+			controller: 'SaleQuotationNewCtrl'
+		}).state('sale.quotation.list', {
+			url : "/list",
+			templateUrl : "static/tpl/index/sale/quotation_list.html",
+			controller: 'SaleQuotationListCtrl'
+		}).state('sale.quotation.item', {
+			url : "/:id",
+			templateUrl : "static/tpl/index/sale/quotation_new.html",
+			controller: 'SaleQuotationNewCtrl'
 		}).state('sale.order', {
 			url : "/order",
 			templateUrl : "static/tpl/index/sale/order.html",
@@ -1128,6 +1143,8 @@ define([ 'toaster', 'charts', 'ngTable', 'common/services', 'service/Purc', 'ser
 			$scope.tableParams.reload();
 		};
 	}]);
+	
+	// 询价单明细
 	app.controller('SaleInquiryDetailCtrl', ['$scope', '$stateParams', 'PurcInquiry', 'toaster', function($scope, $stateParams, PurcInquiry, toaster){
 		var loadData = function() {
 			PurcInquiry.getAll({id: $stateParams.id}, function(data){
@@ -1213,6 +1230,312 @@ define([ 'toaster', 'charts', 'ngTable', 'common/services', 'service/Purc', 'ser
 			}
 		};
 	}]);
+	
+	// 主动报价 - 列表
+	app.controller('SaleQuotationListCtrl', ['$scope', '$filter', 'Quotation', 'PurcInquiry', 'ngTableParams', 'toaster', 'BaseService', function($scope, $filter, Quotation, PurcInquiry, ngTableParams, toaster, BaseService){
+		$scope.active = 'todo';
+		$scope.agreedText = '全部';
+		$scope.dateZoneText = '一个月内';
+		$scope.condition = {dateZone: 1};
+		$scope.changeDateZone = function(zone) {
+			$scope.condition.dateZone = zone;
+			$scope.dateZoneText = typeof zone == 'undefined' ? '半年前' : (zone == 1 ? '一个月内' : '半年内');
+			$scope.condition.$dateZoneOpen = false;
+		};
+		$scope.setActive = function(state) {
+			if($scope.active != state) {
+				$scope.active = state;
+				if($scope.tableParams.page() == 1)
+					$scope.tableParams.reload();
+				else
+					$scope.tableParams.page(1);
+			}
+		};
+		var getService = function() {
+			return Quotation;
+		};
+		$scope.tableParams = new ngTableParams({
+			page : 1, 
+			count : 5,
+			sorting: {
+                'quotation.date': 'desc'
+            }
+		}, {
+			total : 0, 
+			counts: [5, 10, 25, 50],
+			getData : function($defer, params) {
+				$scope.loading = true;
+				var pageParams = params.url();
+				pageParams.keyword = $scope.keyword;
+				getService()[getState($scope.active)].call(null, BaseService.parseParams(pageParams), function(page){
+					$scope.loading = false;
+					if(page) {
+						params.total(page.totalElements);
+						$defer.resolve(page.content);
+						$scope.keywordXls = angular.copy($scope.keyword);//保存当前取值的关键词
+					}
+				}, function(response){
+					$scope.loading = false;
+					toaster.pop('error', '数据加载失败', response.data);
+				});
+			}
+		});
+		
+		$scope.getHistory = function(item) {
+			if(!item.history) {
+				PurcInquiry.getHistory({itemId: item.id}, function(data){
+					item.history = data;
+				});
+			}
+		};
+		
+		$scope.isValid = function(item, withSteps) {
+			var bool = item.leadtime && item.replies && item.replies[0].price > 0;
+			if(!withSteps || !bool)
+				return bool;
+			angular.forEach(item.replies, function(r, i){
+				bool = (i > 0 ? r.lapQty : 1) && r.price;
+			});
+			return bool;
+		};
+		
+		// 搜索框回车
+		$scope.onSearch = function() {
+			$scope.tableParams.reload();
+		};
+	}]);
+	
+	// Controller 主动报价 - 新增
+	app.controller('SaleQuotationNewCtrl', ['$scope', '$stateParams', '$filter', 'ngTableParams', 'toaster', 'BaseService', '$modal', 'Quotation', function($scope, $stateParams, $filter, ngTableParams, toaster, BaseService, $modal, Quotation){
+		var staticItem = null;
+		
+		if( ! angular.isUndefined($stateParams.id)) {// 查看模式
+			$scope.loading  = true;
+			Quotation.getItem({id: $stateParams.id}, function(data){
+				data.$editing = false;
+				$scope.item = data;
+				staticItem = angular.copy(data);
+				$scope.loading  = false;
+			}, function(response){
+				$scope.loading  = false;
+				toaster.pop('error', '数据加载失败', response.data);
+			});
+		} else {// 新增模式
+			$scope.item = {
+				quotation: {
+					currency: 'RMB',
+					taxrate: 17,
+					date: new Date()
+				},
+				product: {},
+				prices: [{lapQty: 0}],
+				minOrderQty: 1,
+				minPackQty: 1,
+				$endDateOpen: false,
+				$editing: true
+			};
+		}
+		
+		$scope.getMinDate = function(item) {
+			return $filter('date')(new Date, 'yyyy-MM-dd');
+		};
+		
+		$scope.openDatePicker = function($event, openParam) {
+			$event.preventDefault();
+		    $event.stopPropagation();
+		    $scope.item.$endDateOpen = !openParam;
+		};
+		
+		// 增加一个分段
+		$scope.addPrice = function(){
+			if($scope.item.prices.length >= 10) {
+				toaster.pop('warning', '提示', '最多支持10个分段!');
+			} else
+				$scope.item.prices.push({});
+		};
+		
+		// 删除一个分段
+		$scope.removePrice = function(index) {
+			$scope.item.prices.splice(index, 1);
+		};
+		
+		// 查找客户
+		$scope.dbfindCust = function(){
+			if($scope.item.$editing) {
+				var modalInstance = $modal.open({
+					templateUrl: 'static/tpl/index/sale/quotation_new_cust.html',
+					controller: 'DbfindCustCtrl',
+					size: 'lg',
+					resolve: {
+						
+					}
+				});
+				
+				modalInstance.result.then(function(data){
+					$scope.item.quotation.cust = data.myEnterprise;
+					$scope.item.quotation.custUser = data.myUser;
+					$scope.item.product = null;
+				}, function(){
+					
+				});
+			}
+		};
+		
+		// 查找客户物料
+		$scope.dbfindCustProd = function(){
+			if($scope.item.$editing) {
+				if($scope.item.quotation.cust.uu) {
+					var modalInstance = $modal.open({
+						templateUrl: 'static/tpl/index/sale/quotation_new_custProd.html',
+						controller: 'DbfindCustProdCtrl',
+						size: 'lg',
+						resolve: {
+							custUU: function(){return $scope.item.quotation.cust.uu}
+						}
+					});
+					
+					modalInstance.result.then(function(data){
+						$scope.item.product = data;
+					}, function(){
+						
+					});
+				} else {
+					toaster.pop('error', '错误', '请先选择客户');
+				}
+			}
+		};
+		
+		// 保存
+		$scope.save = function(){
+			$scope.loading = true;
+			if(!$scope.item.quotation.code) //新增,设单号
+				$scope.item.quotation.code = 'BJ' + $filter('date')(new Date(), 'yyMMddHHmmss_sss');
+			$scope.item.quotation.custUU = $scope.item.quotation.cust.uu;
+			$scope.item.quotation.custUserUU = $scope.item.quotation.custUser.userUU;
+			$scope.item.productId = $scope.item.product.id;
+			$scope.item.quotation.status = 100;//在录入
+			if($scope.item.quotation.date instanceof Date) {
+				$scope.item.quotation.date = $scope.item.quotation.date.getTime();
+			}
+			if($scope.item.quotation.endDate instanceof Date) {
+				$scope.item.quotation.endDate = $scope.item.quotation.endDate.getTime();
+			}
+			Quotation.save({}, $scope.item, function(data){
+				$scope.loading = false;
+				toaster.pop('success', '成功', '保存成功');
+				if($stateParams.id)
+					window.location.reload();
+				else 
+					window.location.hash = '#/sale/quotation/' + data.id;
+			}, function(response){
+				$scope.loading = false;
+				toaster.pop('error', '保存失败', response.data);
+			});
+		};
+		
+		// 更新
+		$scope.update = function(){
+			$scope.item.$editing = true;
+		};
+		
+		// 取消
+		$scope.cancel = function(){
+			$scope.item.$editing = false;
+			$scope.item = angular.copy(staticItem);
+		};
+		
+		// 提交
+		$scope.submit = function(){
+			$scope.loading = true;
+			$scope.item.quotation.status = 101;//在录入
+			Quotation.save({}, $scope.item, function(data){
+				$scope.loading = false;
+				toaster.pop('success', '成功', '提交成功');
+				window.location.hash = '#/sale/quotation/' + data.id;
+			}, function(response){
+				$scope.loading = false;
+				toaster.pop('error', '保存失败', response.data);
+			});
+		};
+	}]);
+	
+	// 查找客户
+	app.controller('DbfindCustCtrl', ['$scope', 'Customer', 'BaseService', 'ngTableParams', 'toaster', '$modalInstance', function($scope, Customer, BaseService, ngTableParams, toaster, $modalInstance){
+		$scope.customerParams = new ngTableParams({
+			page : 1, 
+			count : 10
+		}, {
+			total : 0, 
+			counts: [5, 10, 25, 50],
+			getData : function($defer, params) {
+				$scope.loading = true;
+				Customer.get(BaseService.parseParams(params.url()), function(page){
+					$scope.loading = false;
+					if(page) {
+						params.total(page.totalElements);
+						$defer.resolve(page.content);
+					}
+					$scope.totalCount = page.totalElements;
+				}, function(response){
+					$scope.loading = false;
+					toaster.pop('error', '数据加载失败', response.data);
+				});
+			}
+		});
+		
+  		$scope.cancel = function() {
+    		$modalInstance.dismiss();
+  		};
+  		
+  		$scope.check = function(cust){
+  			$modalInstance.close(cust);
+  		};
+	}]);
+	
+	// 查找客户物料
+	app.controller('DbfindCustProdCtrl', ['$scope', 'Product', 'BaseService', 'ngTableParams', 'toaster', '$modalInstance', 'custUU', function($scope, Product, BaseService, ngTableParams, toaster, $modalInstance, custUU){
+		$scope.customerParams = new ngTableParams({
+			page : 1, 
+			count : 10
+		}, {
+			total : 0, 
+			counts: [5, 10, 25, 50],
+			getData : function($defer, params) {
+				$scope.loading = true;
+				var pageParams = params.url();
+				pageParams.keyword = $scope.keyword;
+				pageParams.custUU = custUU;
+				Product.get.call(null, BaseService.parseParams(pageParams), function(page){
+					$scope.loading = false;
+					if(page) {
+						params.total(page.totalElements);
+						$defer.resolve(page.content);
+						$scope.keywordXls = angular.copy($scope.keyword);//保存当前取值的关键词
+					}
+				}, function(response){
+					$scope.loading = false;
+					toaster.pop('error', '数据加载失败', response.data);
+				});
+			}
+		});
+		
+		// 取消
+  		$scope.cancel = function() {
+    		$modalInstance.dismiss();
+  		};
+  		
+  		// 选择
+  		$scope.check = function(cust){
+  			$modalInstance.close(cust);
+  		};
+  		
+  		// 搜索框回车
+		$scope.onSearch = function() {
+			$scope.customerParams.reload();
+		};
+	}]);
+	
+	// 发货提醒
 	app.controller('SaleNoticeCtrl', ['$scope', '$rootScope', '$filter', 'PurcNotice', 'ngTableParams', 'toaster', 'BaseService', 'PurcNoticeHis', '$modal', 'SaleTruck', 'Symbol', function($scope, $rootScope, $filter, PurcNotice, ngTableParams, toaster, BaseService, PurcNoticeHis, $modal, SaleTruck, Symbol){
 		$scope.active = 'todo';
 		$scope.dateZoneText = '一个月内';

+ 28 - 0
src/main/webapp/resources/js/index/services/Purc.js

@@ -346,5 +346,33 @@ define([ 'ngResource'], function() {
 				isArray: true
 			}
 		});
+	}]).factory('Customer', ['$resource', function($resource){
+		return $resource('vendor/customer/:id', {}, {});
+	}]).factory('Product', ['$resource', function($resource){
+		return $resource('product', {}, {});
+	}]).factory('Quotation', ['$resource', function($resource){
+		return $resource('sale/quotation', {}, {
+			getTodo: {
+				params: {
+					_state: 'todo'
+				}
+			},
+			getDone: {
+				params: {
+					_state: 'done'
+				}
+			},
+			save: {
+				method: 'POST',
+				isArray: false,
+				headers: {
+					'Content-Type' : 'application/text;charset=UTF-8'
+				}
+			},
+			getItem: {
+				isArray: false,
+				url: 'sale/quotation/item/:id'
+			}
+		});
 	}]);
 });

+ 1 - 1
src/main/webapp/resources/tpl/index/sale/inquiry.html

@@ -292,7 +292,7 @@
 					</div>
 					<div class="form-group" ng-if="inquiryItem.$editing" style="width: 220px;">
 						<input type="number" class="form-control input-xs"
-							ng-model="inquiryItem.leadtime" placeholder="交货周期" style="display: inline-block;width: 180px;">
+							ng-model="inquiryItem.leadtime" placeholder="交货周期(确切天数)" style="display: inline-block;width: 180px;">
 						<span ng-if="!inquiryItem.leadtime" class="text-inverse"> 必填*</span>
 					</div>
 				</td>

+ 1 - 1
src/main/webapp/resources/tpl/index/sale/inquiry_detail.html

@@ -97,7 +97,7 @@
 							<div class="form-group" ng-if="inquiryItem.$editing"
 								style="width: 220px;">
 								<input type="number" class="form-control input-xs"
-									ng-model="inquiryItem.leadtime" placeholder="交货周期(天数)"
+									ng-model="inquiryItem.leadtime" placeholder="交货周期(确切天数)"
 									style="display: inline-block; width: 180px;"> <span
 									ng-if="!inquiryItem.leadtime" class="text-inverse"> 必填*</span>
 							</div>

+ 1 - 1
src/main/webapp/resources/tpl/index/sale/left.html

@@ -48,7 +48,7 @@
 	</div>
 	<ul class="list-unstyled">
 		<li ui-sref-active="active"><a ui-sref="sale.inquiry">客户询价管理</a></li>
-		<!-- <li ng-class="{'active': active=='quotation'}"><a ui-sref="sale.quotation">主动报价</a></li> -->
+		<li ui-sref-active="active"><a ui-sref="sale.quotation.list">主动报价</a></li>
 	</ul>
 </div>
 <div class="left-nav">

+ 1 - 1
src/main/webapp/resources/tpl/index/sale/notice.html

@@ -471,7 +471,7 @@
 		<form class="sampleSend" name="sampleSendForm" ng-submit="ok(sampleSendForm)">
         	<div class="modal-body">
 				<div class="row" style="margin-bottom:10px;line-height:30px;">
-					<label class="col-md-3 col-sm-3 text-right">发货单号:</label>
+					<label class="col-md-3 col-sm-3 text-right"><span class="text-inverse">*</span> 发货单号:</label>
 					<div class="col-md-6 col-sm-6">
 					<input class="form-control input-sm" ng-model="saleSend.code" required type="text" placeholder="请输入发货单号"></div>
 				</div>

+ 138 - 0
src/main/webapp/resources/tpl/index/sale/quotation.html

@@ -0,0 +1,138 @@
+<style>
+.order-table .header>th {
+	height: 38px;
+	text-align: center;
+	background: #f5f5f5;
+	border-top: 1px solid #e8e8e8;
+	border-bottom: 1px solid #e8e8e8;
+}
+
+.order-table .sep-row {
+	height: 10px;
+}
+
+.order-table .selector {
+	vertical-align: middle;
+	margin: 0 0 2px 0;
+}
+
+.toolbar label {
+	margin-right: 10px;
+	margin-bottom: 0;
+}
+
+.toolbar .select_all {
+	margin: 0 6px 0 10px;
+	line-height: 20px;
+}
+
+.toolbar .btn {
+	-moz-border-radius: 2px;
+	margin-right: 5px;
+	border: 1px solid #dcdcdc;
+	border-radius: 2px;
+	-webkit-border-radius: 2px;
+}
+
+.order-table .order-hd {
+	background: #f5f5f5;
+	height: 40px;
+	line-height: 40px;
+}
+
+.order-table .order-hd td.first {
+	padding-left: 20px;
+}
+
+.order-table .order-hd .order-main span {
+	margin-right: 8px;
+}
+
+.order-table .order-hd .order-code {
+	font-style: normal;
+	font-family: verdana;
+}
+
+.order-table .order-hd .order-sum {
+	padding: 0 5px;
+}
+
+.order-table>tbody {
+	border: 1px solid transparent;
+}
+
+.order-table>tbody:hover {
+	border-color: #56a022;
+	border-width: 2px;
+}
+
+.order-table .operates {
+	display: none;
+}
+
+.order-table>tbody:hover .operates {
+	display: block;
+}
+
+.order-table .order-bd {
+	border-bottom: 1px solid #e6e6e6;
+}
+
+.order-table .order-bd>td {
+	padding: 10px 5px;
+	vertical-align: top;
+	position: relative;
+}
+
+.order-table .order-bd .product {
+	padding-left: 20px;
+}
+
+.input-xs,.input-group-xs>.form-control,.input-group-xs>.input-group-addon,.input-group-xs>.input-group-btn>.btn
+	{
+	height: 26px;
+	padding: 0 5px;
+	font-size: 12px;
+	line-height: 1.5;
+	border-radius: 3px;
+}
+
+.input-group-xs .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn {
+	border-top-left-radius: 0;
+	border-bottom-left-radius: 0;
+}
+
+.input-dbfind {
+	cursor: pointer;
+}
+
+@media ( min-width : 768px) {
+	.form-horizontal .form-group-xs .control-label {
+		padding-top: 5px;
+	}
+}
+
+</style>
+<div class="block">
+	<div class="condition block">
+		<div class="row">
+			<div class="col-xs-offset-10 col-xs-2">
+				<div class="btn-group btn-group-sm btn-group-justified">
+					<div class="btn-group btn-group-sm">
+						<a class="btn btn-default btn-line"
+							ui-sref-active="btn-info" ui-sref="sale.quotation.new">
+							<i class="fa fa-plus-square-o"></i> 新增
+						</a>
+					</div>
+					<div class="btn-group btn-group-sm">
+						<a class="btn btn-default btn-line"
+							ui-sref-active="btn-info" ui-sref="sale.quotation.list">
+							<i class="fa fa-list"></i> 列表
+						</a>
+					</div>
+				</div>
+			</div>
+		</div>
+	</div>
+	<div ui-view></div>
+</div>

+ 269 - 0
src/main/webapp/resources/tpl/index/sale/quotation_list.html

@@ -0,0 +1,269 @@
+<style>
+.list {
+	border-top: solid 1px #e8e8e8;
+}
+
+</style>
+<div class="loading in" ng-class="{'in': loading}">
+	<i></i>
+</div>
+<div class="condition block list">
+	<div class="row">
+		<div class="col-xs-4">
+			<div class="btn-group btn-group-sm btn-group-justified">
+				<div class="btn-group btn-group-sm">
+					<button type="button" class="btn btn-default btn-line"
+						ng-class="{'btn-info':active=='all'}" ng-click="setActive('all')">全部</button>
+				</div>
+				<div class="btn-group btn-group-sm">
+					<button type="button" class="btn btn-default btn-line"
+						ng-class="{'btn-info':active=='done'}" ng-click="setActive('done')">已提交</button>
+				</div>
+				<div class="btn-group btn-group-sm">
+					<button type="button" class="btn btn-default btn-line"
+						ng-class="{'btn-info':active=='todo'}" ng-click="setActive('todo')">未提交</button>
+				</div>
+			</div>
+		</div>
+		<div class="col-xs-6">
+			<div class="search">
+				<div class="form-group form-group-sm has-feedback">
+					<input type="search" class="form-control input-sm" ng-model="keyword" ng-search="onSearch()" placeholder="输入商品、客户名称或单据流水号搜索" /><span
+						class="form-control-feedback text-simple"><i
+						class="fa fa-search"></i></span>
+				</div>
+			</div>
+		</div>
+		<div class="col-xs-2 toggle" ng-if="false">
+			<a ng-click="condition.$open=!condition.$open" class="text-simple"><span ng-bind="condition.$open ? '简化筛选条件' : '更多筛选条件'"></span><i class="fa fa-fw" ng-class="{'fa-angle-up': condition.$open, 'fa-angle-down': !condition.$open}"></i></a>
+		</div>
+	</div>
+	<div class="more" ng-class="{'open': condition.$open}">
+		<form class="form-inline">
+		  <div class="form-group ">
+		    <label>日期:</label>
+		    <div class="btn-group btn-menu" dropdown is-open="condition.$dateZoneOpen">
+			  <button type="button" dropdown-toggle style="width: 85px;" class="btn btn-default btn-xs dropdown-toggle">
+			    	{{dateZoneText}}<i class="fa fa-fw fa-angle-down icon-right"></i></span>
+			  </button>
+			  <ul class="dropdown-menu">
+				<li><a ng-click="changeDateZone(1)">一个月内</a></li>
+			    <li><a ng-click="changeDateZone(6)">半年内</a></li>
+			    <li><a ng-click="changeDateZone()">半年前</a></li>
+			  </ul>
+			</div>
+		    <div class="form-group input-group input-group-xs input-trigger">
+					<input type="text" ng-model="condition.dateFrom"
+						class="form-control" placeholder="从"
+						datepicker-popup="yyyy-MM-dd" is-open="condition.$fromOpened"
+						ng-required="true"
+						current-text="今天" clear-text="清除" close-text="关闭"
+						datepicker-options="{formatDayTitle: 'yyyy年M月', formatMonth: 'M月', showWeeks: false}"
+						ng-focus="openDatePicker($event, condition, '$fromOpened')">
+					<span class="input-group-btn">
+						<button type="button" class="btn btn-default"
+							ng-click="openDatePicker($event, condition, '$fromOpened')">
+							<i class="fa fa-calendar"></i>
+						</button>
+					</span>
+				</div>
+				<div class="form-group input-group input-group-xs input-trigger">
+					<input type="text" ng-model="condition.dateTo"
+						class="form-control" placeholder="到"
+						datepicker-popup="yyyy-MM-dd" is-open="condition.$toOpened"
+						ng-required="true"
+						current-text="今天" clear-text="清除" close-text="关闭"
+						datepicker-options="{formatDayTitle: 'yyyy年M月', formatMonth: 'M月', showWeeks: false}"
+						ng-focus="openDatePicker($event, condition, '$toOpened')">
+					<span class="input-group-btn">
+						<button type="button" class="btn btn-default"
+							ng-click="openDatePicker($event, condition, '$toOpened')">
+							<i class="fa fa-calendar"></i>
+						</button>
+					</span>
+				</div>
+		  </div>
+		  <div class="form-group">
+		    <label>采纳结果:</label>
+		    <div class="btn-group btn-menu" dropdown is-open="condition.$agreedOpen">
+			  <button type="button" dropdown-toggle style="width: 70px;" class="btn btn-default btn-xs dropdown-toggle">
+			    	{{agreedText}}<i class="fa fa-fw fa-angle-down icon-right"></i></span>
+			  </button>
+			  <ul class="dropdown-menu">
+				<li><a ng-click="changeAgreed()">全部</a></li>
+			    <li><a ng-click="changeAgreed(1)">已采纳</a></li>
+			    <li><a ng-click="changeAgreed(0)">未采纳</a></li>
+			  </ul>
+			</div>
+		  </div>
+		</form>
+	</div>
+</div>
+<table class="order-table block" ng-table="tableParams" >
+	<thead>
+		<tr class="header">
+			<th>商品</th>
+			<th width="90"><span class="text-default">≥</span>分段数</th>
+			<th width="90">价格</th>
+			<th width="80">最小订购</th>
+			<th width="80">最小包装</th>
+			<th width="120">有效期</th>
+			<th width="75">操作</th>
+		</tr>
+		<tr class="sep-row">
+			<td colspan="7"></td>
+		</tr>
+		<tr class="toolbar toolbar-top">
+			<td colspan="6">
+				<div>
+					<label><input ng-disabled="true" type="checkbox" class="selector select_all"
+						ng-model="selectAll">全选</label>
+				</div> <!-- 分页 -->
+			</td>
+			<td class="text-center">
+				<a href="sale/quotation/xls?_state={{active}}&keyword={{keywordXls}}" target="_self" class="text-simple" title="导出Excel表格"><i class="fa fa-file-excel-o fa-fw"></i>导出</a>
+			</td>
+		</tr>
+		<tr class="sep-row">
+			<td colspan="7"></td>
+		</tr>
+	</thead>
+	<tbody ng-if="tableParams.total() == 0">
+		<tr>
+			<td class="text-center" colspan="7">
+				<br>
+				<div class="text-muted"><h3><i class="fa fa-spinner"></i> 当前没有对应的单据</h3></div>
+				<br>
+				<div>
+					<a ui-sref="sale.quotation.new">立即向客户主动报价</a>
+				</div>
+			</td>
+		</tr>
+	</tbody>
+	<tbody ng-repeat="quotationItem in $data track by quotationItem.id">
+		<tr class="order-hd">
+			<td class="first">
+				<div class="order-main">
+					<span> <input type="checkbox" class="selector"
+						ng-model="quotationItem.$selected">
+					</span> <span class="text-num text-bold"
+						title="{{quotationItem.quotation.date}}"
+						ng-bind="::quotationItem.quotation.date | date:'yyyy-MM-dd'"></span> <span>流水号:<a
+						class="text-num" ng-bind="::quotationItem.quotation.code" ui-sref="sale.quotation.item({id:quotationItem.quotation.id})" target="_self"></a></span>
+				</div>
+			</td>
+			<td colspan="2"><span
+				ng-bind="::quotationItem.quotation.cust.enName"></span></td>
+			<td>
+				币别:<span ng-bind="::quotationItem.quotation.currency"></span>
+			</td>
+			<td>
+				税率:<span ng-bind="::quotationItem.quotation.taxrate || 0"></span>%
+			</td>
+			<td class="text-right" colspan="1" class="order-sum">
+			</td>
+			<td class="text-center">
+				<div class="operates">
+					<!-- <a ng-click="print(quotationItem)" class="text-muted" title="打印"><i
+						class="fa fa-print fa-lg"></i></a> -->
+				</div>
+			</td>
+		</tr>
+		<tr class="order-bd">
+			<td class="product">
+				<div class="text-num text-bold" ng-bind="::quotationItem.product.code"></div>
+				<div ng-bind="::quotationItem.product.title"></div>
+				<div class="text-muted" ng-bind="::quotationItem.product.spec"></div>
+				<div ng-if="::quotationItem.brand && !quotationItem.$editing" class="text-muted">
+					品牌:<spans ng-bind="::quotationItem.brand"></span>
+				</div>
+				<div ng-if="::quotationItem.vendorprodcode && !quotationItem.$editing" class="text-muted">
+					供应商物料编号:<spans ng-bind="::quotationItem.vendorprodcode"></span>
+				</div>
+				<div ng-if="::quotationItem.leadtime && !quotationItem.$editing" class="text-muted">
+					交货周期:<spans ng-bind="::quotationItem.leadtime"></span>天
+				</div>
+			</td>
+			<td class="text-center">
+				<div ng-show="!quotationItem.$editing">
+					<div ng-repeat="price in quotationItem.prices">
+						<span ng-bind="price.lapQty"></span>
+					</div>
+				</div>
+			</td>
+			<td class="text-center br-l">
+				<div ng-show="!quotationItem.$editing">
+					<div ng-repeat="price in quotationItem.prices">
+						<span ng-bind="price.price | number:6"></span> <span
+							ng-show="price.price == null" class="text-muted">-</span>
+					</div>
+					<div class="dropdown">
+						<a href="javascript:void(0);" class="dropdown-toggle text-default"
+							ng-mouseover="getHistory(quotationItem)">历史报价<i
+							class="fa fa-fw fa-angle-down"></i></a>
+						<div class="dropdown-menu pane" style="width: 270px;">
+							<div class="pane-body">
+								<ul class="list-unstyled list-menu">
+									<li ng-repeat="historyItem in ::quotationItem.history">
+										<div ng-class="{'text-inverse': $index==0}">
+											<div class="row row-sm"
+												ng-repeat="historyReply in historyItem.replies">
+												<div class="col-xs-5">≥{{historyReply.lapQty}}</div>
+												<div class="col-xs-5">价格{{historyReply.price | number:6}}</div>
+											</div>
+										</div>
+										<div class="text-muted">{{historyItem.quotation.date |
+											date:'yyyy-MM-dd'}}{{historyItem.quotation.enterprise.enName}}
+										</div>
+									</li>
+								</ul>
+								<div ng-show="!quotationItem.history || quotationItem.history.length == 0"
+									class="text-center text-muted">暂无历史报价</div>
+							</div>
+						</div>
+					</div>
+				</div>
+			</td>
+			<td class="text-center br-l">
+				<div ng-show="!quotationItem.$editing">
+					<span ng-bind="quotationItem.minOrderQty"></span> <span
+						ng-show="quotationItem.minOrderQty == null" class="text-muted">-</span>
+				</div>
+			</td>
+			<td class="text-center br-l">
+				<div ng-show="!quotationItem.$editing">
+					<span ng-bind="quotationItem.minPackQty"></span> <span
+						ng-show="quotationItem.minPackQty == null" class="text-muted">-</span>
+				</div>
+			</td>
+			<td class="text-center br-l">
+				<div ng-show="!quotationItem.$editing"
+					ng-init="parseDate(quotationItem)">
+					<div ng-show="quotationItem.quotation.endDate">
+						<span class="text-muted">从 </span><span
+							ng-bind="quotationItem.quotation.date | date:'yyyy-MM-dd'"></span> <span
+							class="text-muted">到 </span><span
+							ng-bind="quotationItem.quotation.endDate | date:'yyyy-MM-dd'"></span>
+					</div>
+					<div ng-show="!quotationItem.quotation.endDate">
+						<span class="text-muted">-</span>
+					</div>
+				</div>
+			</td>
+			<td class="text-center br-l">
+				<div ng-if="quotationItem.quotation.status == 101 && quotationItem.quotation.agreed == null" class="block">
+					<span class="text-trans warning">已提交</span>
+				</div>
+				<div ng-if="quotationItem.quotation.status == 101 && quotationItem.quotation.agreed == 1" class="block">
+					<span class="text-trans success">报价已采纳</span>
+				</div>
+				<div ng-if="quotationItem.quotation.status == 101 && quotationItem.quotation.agreed == 0" class="block">
+					<span class="text-trans error">报价未采纳</span>
+				</div>
+				<div ng-if="quotationItem.quotation.status == 100">
+					<a ui-sref="sale.quotation.item({id:quotationItem.quotation.id})">详情>></a>
+				</div>
+			</td>
+		</tr>
+	</tbody>
+</table>

+ 284 - 0
src/main/webapp/resources/tpl/index/sale/quotation_new.html

@@ -0,0 +1,284 @@
+<style>
+.new {
+	padding: 0px 20px 20px 20px;
+}
+
+.new label {
+	font-size: 14px;
+	font-weight: normal;
+	font-family: "Microsoft YaHei" ! important;
+}
+
+.headerline {
+	font-size: 16px;
+  	font-family: Microsoft YaHei,SimHei,Verdana;
+  	font-weight: 500;
+  	line-height: 22px;
+  	margin: 25px 0;
+  	clear: both;
+  	zoom: 1;
+  	border-top: 1px solid #eee;
+  	position: relative;
+}
+
+.headerline .content {
+	position: absolute;
+	top: -12px;
+	left: 20px;
+	line-height: 24px;
+  	padding: 0 15px 0 10px;
+  	background: #fff;
+  	z-index: 2;
+}
+
+.headerline .end {
+	position: absolute;
+	top: -12px;
+	right: 20px;
+	line-height: 24px;
+  	padding-left: 15px;
+  	background: #fff;
+  	z-index: 2;
+}
+
+.input-group-addon {
+	background-color: inherit;
+  	border: 1px solid #e1e1e1;
+  	color: #888 !important;
+}
+
+.status {
+	position: absolute;
+  	height: 50px;
+  	width: 100px;
+  	/* border-radius: 50px; */
+  	border: dashed 2px #999;
+  	border-radius: 13px;
+  	padding-top: 7px;
+  	padding-left: 5px;
+  	text-align: center;
+  	right: 83px;
+  	top: 10px;
+  	background-color: #FFFFFF;
+  	color: #999;
+  	word-spacing: 8px;
+  	letter-spacing: 5px;
+  	-webkit-transform: rotate(15deg);
+  	-moz-transform: rotate(15deg);
+  	-o-transform: rotate(15deg);
+  	transform: rotate(14deg);
+  	font-size: 20px;
+  	z-index: 9;
+}
+
+</style>
+<div class="loading" ng-class="{'in': loading}">
+	<i></i>
+</div>
+<div class="block new">
+	<form class="form-horizontal" name="quotationForm">
+		<div class="headerline">
+			<div class="content">基本信息</div>
+			<div class="end">
+				<i class="fa fa-angle-down"></i>&nbsp;&nbsp;
+			</div>
+		</div>
+		<div style="position: relative;">
+			<div ng-if="item.quotation.status == 100" class="status">在录入</div>
+			<div ng-if="item.quotation.status == 101 && item.quotation.agreed == null" class="status">已提交</div>
+			<div ng-if="item.quotation.status == 101 && item.quotation.agreed == 1" class="status">报价已采纳</div>
+			<div ng-if="item.quotation.status == 101 && item.quotation.agreed == 0" class="status">报价未采纳</div>
+		</div>
+		<div class="form-group form-group-sm" ng-if="item.quotation.code">
+			<label for="code" class="col-sm-2 control-label">单据编号</label>
+			<div class="col-sm-4">
+				<div class="">
+					<input ng-model="item.quotation.code" readonly="readonly" type="text" class="form-control" id="code" 
+						>
+				</div>
+			</div>
+		</div>
+		<div class="form-group form-group-sm has-feedback">
+			<label for="customer" class="col-sm-2 control-label"><span class="text-inverse text-bold">* </span>客户</label>
+			<div class="col-sm-4">
+				<div class="">
+					<input ng-model="item.quotation.cust.enName" readonly="readonly" type="text" class="form-control" id="customer" 
+						placeholder="点击选择客户" style="cursor: pointer;" ng-click="dbfindCust()" ng-required="true">
+					<span class="form-control-feedback text-simple"><i class="fa fa-search"></i></span>
+				</div>
+				<div ng-if="item.quotation.cust.enAddress" class="text-muted">
+					<i class="fa fa-map-marker fa-fw"></i> {{item.quotation.cust.enAddress}}
+				</div>
+			</div>
+		</div>
+		<div class="form-group form-group-sm has-feedback">
+			<label for="customerUser" class="col-sm-2 control-label">客户联系人</label>
+			<div class="col-sm-4">
+				<div class="">
+					<input ng-model="item.quotation.custUser.userName" type="text" class="form-control input-dbfind" id="custUser" 
+						placeholder="点击选择客户联系人" readonly="readonly" style="cursor: pointer;">
+					<span class="form-control-feedback text-simple"><i class="fa fa-search"></i></span>
+				</div>
+				<div ng-if="item.quotation.custUser" class="text-muted">
+					<i class="fa fa-phone fa-fw icon-left"></i>{{item.quotation.custUser.userTel}}
+				</div>
+			</div>
+		</div>
+		<div class="form-group form-group-sm has-feedback">
+			<label for="product" class="col-sm-2 control-label"><span class="text-inverse text-bold">* </span>物料</label>
+			<div class="col-sm-4">
+				<div class="">
+					<input ng-model="item.product.code" type="text" class="form-control input-dbfind" id="product" 
+						placeholder="点击选择物料" readonly="readonly" style="cursor: pointer;"
+						ng-click="dbfindCustProd()" ng-required="true">
+					<span class="form-control-feedback text-simple"><i class="fa fa-search"></i></span>
+				</div>
+				<div ng-if="item.product.title" class="text-muted">
+					名称:{{item.product.title}}
+				</div>
+				<div ng-if="item.product.spec" class="text-muted">
+					规格:{{item.product.spec}}
+				</div>
+				<div ng-if="item.product.unit" class="text-muted">
+					单位:{{item.product.unit}}
+				</div>
+			</div>
+		</div>
+		<div class="form-group form-group-sm">
+			<label for="leadtime" class="col-sm-2 control-label"><span class="text-inverse text-bold">* </span>交货周期(天)</label>
+			<div class="col-sm-3">
+				<input ng-model="item.leadtime" type="number" class="form-control" id="leadtime" 
+					placeholder="只可以为整数" ng-readonly="!item.$editing" ng-required="true">
+			</div>
+		</div>
+		<div class="form-group form-group-sm">
+			<label for="brand" class="col-sm-2 control-label">物料品牌</label>
+			<div class="col-sm-3">
+				<input ng-model="item.brand" type="text" class="form-control" id="brand" 
+				placeholder="物料品牌" ng-readonly="!item.$editing">
+			</div>
+			<label for="vendorprodcode" class="col-sm-2 control-label">供应商物料编号</label>
+			<div class="col-sm-3">
+				<input ng-model="item.vendorprodcode" type="text" class="form-control" id="vendorprodcode" 
+					placeholder="供应商物料编号" ng-readonly="!item.$editing">
+			</div>
+		</div>
+		<div class="form-group form-group-sm">
+			<label for="minPackQty" class="col-sm-2 control-label"><span class="text-inverse text-bold">* </span>最小包装量</label>
+			<div class="col-sm-3">
+				<input ng-model="item.minPackQty" type="number" class="form-control" id="minPackQty" 
+					placeholder="最小包装量" ng-readonly="!item.$editing" ng-required="true">
+			</div>
+			<label for="minOrderQty" class="col-sm-2 control-label"><span class="text-inverse text-bold">* </span>最小订购量</label>
+			<div class="col-sm-3">
+				<input ng-model="item.minOrderQty" type="number" class="form-control" id="minOrderQty" 
+					placeholder="最小订购量" ng-readonly="!item.$editing" ng-required="true">
+			</div>
+		</div>
+		<div class="form-group form-group-sm">
+			<label for="date" class="col-sm-2 control-label">录入日期</label>
+			<div class="col-sm-3">
+				<div class="input-group">
+					<input ng-model="item.quotation.date" type="text" class="form-control" id="date" placeholder="录入日期"
+						readonly="readonly" datepicker-popup="yyyy-MM-dd">
+					<span class="input-group-btn">
+						<button disabled="disabled" type="button" class="btn btn-default btn-sm"
+							ng-click="openDatePicker($event, inquiryItem, '$fromOpened')">
+							<i class="fa fa-calendar"></i>
+						</button>
+					</span>
+				</div>
+			</div>
+			<label for="endDate" class="col-sm-2 control-label"><span class="text-inverse text-bold">* </span>价格有效日期</label>
+			<div class="col-sm-3">
+				<div class="input-group">
+					<input ng-model="item.quotation.endDate" type="text" class="form-control" id="endDate" 
+						placeholder="点击右侧图标选择时间" datepicker-popup="yyyy-MM-dd" is-open="item.$endDateOpen"
+						min-date="getMinDate()" ng-required="true"
+						current-text="今天" clear-text="清除" close-text="关闭"
+						datepicker-options="{formatDayTitle: 'yyyy年M月', formatMonth: 'M月', showWeeks: false}"
+						ng-focus="openDatePicker($event, item.$endDateOpen)" ng-readonly="!item.$editing">
+					<span class="input-group-btn">
+						<button type="button" class="btn btn-default btn-sm" ng-disabled="!item.$editing"
+							ng-click="openDatePicker($event, item.$endDateOpen)">
+							<i class="fa fa-calendar"></i>
+						</button>
+					</span>
+				</div>
+			</div>
+		</div>
+		<div class="form-group form-group-sm">
+			<label for="currency" class="col-sm-2 control-label"><span class="text-inverse text-bold">* </span>币别</label>
+			<div class="col-sm-3">
+				<select ng-model="item.quotation.currency" class="form-control" id="currency" ng-readonly="!item.$editing">
+					<option value="RMB">RMB 人民币</option>
+					<option value="USD">USD 美元</option>
+					<option value="EUR">EUR 欧元</option>
+					<option value="HKD">HKD 港币</option>
+				</select>
+			</div>
+			<label for="taxrate" class="col-sm-2 control-label"><span class="text-inverse text-bold">* </span>税率</label>
+			<div class="col-sm-3">
+				<input ng-model="item.quotation.taxrate" type="text" class="form-control" id="taxrate" 
+					placeholder="税率" ng-readonly="!item.$editing" ng-required="true">
+			</div>
+		</div>
+		<div class="form-group form-group-sm">
+			<label for="remark" class="col-sm-2 control-label">备注</label>
+			<div class="col-sm-5">
+				<textarea ng-model="item.quotation.remark" class="form-control" rows="3" cols="3" id="remark" 
+					placeholder="备注" ng-readonly="!item.$editing">
+				</textarea>
+			</div>
+		</div>
+		<div class="headerline">
+			<div class="content">分段价格信息</div>
+			<div class="end">
+				<i class="fa fa-angle-down"></i>&nbsp;&nbsp;
+			</div>
+		</div>
+		<div class="form-group form-group-sm" ng-repeat="price in item.prices">
+			<label class="col-sm-2 control-label">分段 {{$index + 1}}</label>
+			<label for="qty{{$index + 1}}" class="col-sm-1 control-label"><span class="text-inverse text-bold">* </span>数量</label>
+			<div class="col-sm-3">
+				<div class="input-group">
+					<div class="input-group-addon">≥</div>
+					<input ng-model="price.lapQty" type="number" class="form-control" id="qty{{$index + 1}}" 
+						placeholder="最小数量" ng-readonly="$first || !item.$editing" ng-required="true">
+					<div class="input-group-addon">{{item.product.unit}}</div>
+				</div>
+			</div>
+			<label for="price{{$index + 1}}" class="col-sm-1 control-label"><span class="text-inverse text-bold">* </span>单价</label>
+			<div class="col-sm-2">
+				<input ng-model="price.price" type="text" class="form-control" id="price{{$index + 1}}" placeholder="单价"
+					ng-pattern="/^[1-9]\d*\.{0,1}\d*|0\.\d*[1-9]\d*$/" ng-readonly="!item.$editing" ng-required="true">
+			</div>
+			<label class="col-sm-3" style="line-height: 30px;">
+				<a ng-if="!$first && item.$editing" href="javascript:void(0)" ng-click="removePrice($index)"><i class="fa fa-trash-o"></i> 删除</a>&nbsp;&nbsp;&nbsp;
+				<a ng-if="$last && item.$editing" href="javascript:void(0)" ng-click="addPrice()"><i class="fa fa-plus-square-o"></i> 增加</a>
+			</label>
+		</div>
+		<div class="form-group form-group-sm">
+			<div class="col-sm-2"></div>
+			<div class="col-sm-3" ng-if="!item.$editing && item.quotation.status == 100">
+				<button class="btn btn-warning btn-sm" style="width: 100%;" ng-click="update()">修改</button>
+			</div>
+			<div class="col-sm-3" ng-if="item.$editing && item.quotation.status == 100">
+				<button class="btn btn-info btn-sm" style="width: 100%;" ng-click="cancel()">取消</button>
+			</div>
+			<div class="col-sm-3" ng-if="item.$editing">
+				<button class="btn btn-success btn-sm" style="width: 100%;" ng-disabled="quotationForm.$invalid" ng-click="save()">保存</button>
+			</div>
+			<div class="col-sm-3" ng-if="!item.$editing && item.quotation.status == 100">
+				<button class="btn btn-success btn-sm" style="width: 100%;" ng-click="submit()">提交</button>
+			</div>
+		</div>
+		<div class="form-group form-group-sm">
+			<div class="col-sm-2"></div>
+			<div class="col-sm-6 text-muted">
+				<div ng-if="item.$editing"><i class="fa fa-info-circle"></i> 保存之后可以删除、修改、提交</div>
+				<div ng-if="!item.$editing && item.quotation.status == 100"><i class="fa fa-info-circle"></i> 提交之后客户才能接收到报价,提交之后无法修改、删除</div>
+			</div>
+		</div>
+	</form>
+</div>

+ 36 - 0
src/main/webapp/resources/tpl/index/sale/quotation_new_cust.html

@@ -0,0 +1,36 @@
+<div class="modal-body" style="min-height: 500px;">
+	<div class="headerline">
+		<span class="content"><i class="fa fa-fw fa-edit text-primary"></i>主动报价 - 选择客户</span>
+	</div>
+	<form class="form-horizontal">
+		<div class="form-group">
+			<label class="col-md-2 col-sm-2 control-label">筛选:</label>
+			<div class="col-md-8 col-sm-8">
+				<input type="text" class="form-control input-sm" 
+					required placeholder="输入客户名称关键字查询" autofocus>
+			</div>
+		</div>
+	</form>
+	<table class="block table table-default table-striped table-bordered"
+		ng-table="customerParams">
+		<thead>
+			<tr class="header">
+				<th>UU</th>
+				<th>客户名称</th>
+				<th>地址</th>
+				<th>选择</th>
+			</tr>
+		</thead>
+		<tbody>
+			<tr ng-repeat="customer in $data">
+				<td class="text-center" ng-bind="::customer.myEnterprise.uu"></td>
+				<td class="text-center" ng-bind="::customer.myEnterprise.enName"></td>
+				<td class="text-center" ng-bind="::customer.myEnterprise.enAddress"></td>
+				<td class="text-center"><a title="选择" href="javascript:void(0)" ng-click="check(customer)"><i class="fa fa-check-square-o"></i></a></td>
+			</tr>
+		</tbody>
+	</table>
+</div>
+<div class="modal-footer">
+	<button class="btn btn-default" ng-click="cancel()" type="button">取消</button>
+</div>

+ 38 - 0
src/main/webapp/resources/tpl/index/sale/quotation_new_custProd.html

@@ -0,0 +1,38 @@
+<div class="modal-body" style="min-height: 500px;">
+	<div class="headerline">
+		<span class="content"><i class="fa fa-fw fa-edit text-primary"></i>主动报价 - 选择客户物料</span>
+	</div>
+	<form class="form-horizontal">
+		<div class="form-group">
+			<label class="col-md-2 col-sm-2 control-label">筛选:</label>
+			<div class="col-md-8 col-sm-8">
+				<input ng-model="keyword" type="text" class="form-control input-sm" 
+					required placeholder="输入客户物料关键字查询" autofocus ng-search="onSearch()">
+			</div>
+		</div>
+	</form>
+	<table class="block table table-default table-striped table-bordered"
+		ng-table="customerParams">
+		<thead>
+			<tr class="header">
+				<th width="160px">编号</th>
+				<th width="160px">名称</th>
+				<th>规格</th>
+				<th width="80px">单位</th>
+				<th width="50px">选择</th>
+			</tr>
+		</thead>
+		<tbody>
+			<tr ng-repeat="product in $data">
+				<td class="text-center" ng-bind="::product.code"></td>
+				<td class="text-center" ng-bind="::product.title"></td>
+				<td class="text-left f12" ng-bind="::product.spec"></td>
+				<td class="text-center" ng-bind="::product.unit"></td>
+				<td class="text-center"><a title="选择" href="javascript:void(0)" ng-click="check(product)"><i class="fa fa-check-square-o"></i></a></td>
+			</tr>
+		</tbody>
+	</table>
+</div>
+<div class="modal-footer">
+	<button class="btn btn-default" ng-click="cancel()" type="button">取消</button>
+</div>