jiaxing.zhou

Merge branch 'master' into dev

# Conflicts:
#	frontend/src/api/delivery.ts
#	frontend/src/api/invoice.ts
#	frontend/src/views/delivery/index.vue
#	frontend/src/views/invoice/index.vue
......@@ -40,7 +40,7 @@ public class DeliveryAddReq {
@NotNull(message = "出库日期不能为空")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Schema(description = "出库日期", required = true)
private LocalDateTime deliveryDate;
private String deliveryDate;
@Schema(description = "出库状态(0-未出库/1-已出库)")
private Integer deliveryStatus;
......
......@@ -44,15 +44,9 @@ public class DeliveryMain {
@Schema(description = "出库状态(0-未出库/1-已出库)")
private Integer deliveryStatus;
@Schema(description = "出库总金额")
private BigDecimal totalAmount;
@Schema(description = "仓库编码")
private String warehouseCode;
@Schema(description = "仓库名称")
private String warehouseName;
@Schema(description = "数据来源")
private String dataSource;
......
......@@ -111,6 +111,9 @@ public class DeliveryMainServiceImpl extends ServiceImpl<DeliveryMainMapper, Del
BeanUtils.copyProperties(addReq, deliveryMain);
deliveryMain.setCreateTime(LocalDateTime.now());
deliveryMain.setUpdateTime(LocalDateTime.now());
if(StringUtils.hasText(addReq.getDeliveryDate())) {
deliveryMain.setDeliveryDate(parseDateTime(addReq.getDeliveryDate()));
}
deliveryMain.setDelFlag("0");
int insert = baseMapper.insert(deliveryMain);
if (insert > 0) {
......
......@@ -35,12 +35,15 @@ VALUES
INSERT INTO t_sys_menu (menu_id, parent_id, menu_name, menu_type, path, icon, sort, status, perms, create_by, create_time, update_by, update_time, del_flag)
VALUES
(301, 3, '出库查询', '2', '', '', 1, '1', 'delivery:list', 'admin', NOW(), 'admin', NOW(), '0'),
(302, 3, '出库详情', '2', '', '', 2, '1', 'delivery:query', 'admin', NOW(), 'admin', NOW(), '0'),
(303, 3, '出库导出', '2', '', '', 3, '1', 'delivery:export', 'admin', NOW(), 'admin', NOW(), '0'),
(304, 3, '出库统计', '2', '', '', 4, '1', 'delivery:statistics', 'admin', NOW(), 'admin', NOW(), '0'),
(305, 3, '出库打印', '2', '', '', 5, '1', 'delivery:print', 'admin', NOW(), 'admin', NOW(), '0'),
(306, 3, '出库确认', '2', '', '', 6, '1', 'delivery:confirm', 'admin', NOW(), 'admin', NOW(), '0'),
(307, 3, '出库撤销', '2', '', '', 7, '1', 'delivery:cancel', 'admin', NOW(), 'admin', NOW(), '0');
(302, 3, '出库新增', '2', '', '', 2, '1', 'delivery:add', 'admin', NOW(), 'admin', NOW(), '0'),
(303, 3, '出库修改', '2', '', '', 3, '1', 'delivery:edit', 'admin', NOW(), 'admin', NOW(), '0'),
(304, 3, '出库删除', '2', '', '', 4, '1', 'delivery:delete', 'admin', NOW(), 'admin', NOW(), '0'),
(305, 3, '出库详情', '2', '', '', 5, '1', 'delivery:detail', 'admin', NOW(), 'admin', NOW(), '0'),
(306, 3, '出库导出', '2', '', '', 6, '1', 'delivery:export', 'admin', NOW(), 'admin', NOW(), '0'),
(307, 3, '出库统计', '2', '', '', 7, '1', 'delivery:statistics', 'admin', NOW(), 'admin', NOW(), '0'),
(308, 3, '出库打印', '2', '', '', 8, '1', 'delivery:print', 'admin', NOW(), 'admin', NOW(), '0'),
(309, 3, '出库确认', '2', '', '', 9, '1', 'delivery:confirm', 'admin', NOW(), 'admin', NOW(), '0'),
(310, 3, '出库撤销', '2', '', '', 10, '1', 'delivery:cancel', 'admin', NOW(), 'admin', NOW(), '0');
-- =========================================
-- 3. 插入发票管理相关按钮权限
......@@ -78,7 +81,7 @@ AND del_flag = '0';
INSERT INTO t_sys_role_menu (role_id, menu_id, create_by, create_time, update_by, update_time, del_flag)
SELECT @admin_role_id, menu_id, 'admin', NOW(), 'admin', NOW(), '0'
FROM t_sys_menu
WHERE menu_id IN (301, 302, 303, 304, 305, 306, 307)
WHERE menu_id IN (301, 302, 303, 304, 305, 306, 307, 308, 309, 310)
AND del_flag = '0';
-- 为ADMIN角色分配发票管理按钮权限
......@@ -102,11 +105,11 @@ FROM t_sys_menu
WHERE menu_id IN (201, 202, 203, 205, 206, 207, 208, 209, 210)
AND del_flag = '0';
-- 为OPERATOR角色分配出库查询按钮权限
-- 为OPERATOR角色分配出库查询按钮权限(除删除外)
INSERT INTO t_sys_role_menu (role_id, menu_id, create_by, create_time, update_by, update_time, del_flag)
SELECT @operator_role_id, menu_id, 'admin', NOW(), 'admin', NOW(), '0'
FROM t_sys_menu
WHERE menu_id IN (301, 302, 303, 304, 305, 306, 307)
WHERE menu_id IN (301, 302, 303, 305, 306, 307, 308, 309, 310)
AND del_flag = '0';
-- 为OPERATOR角色分配发票管理按钮权限(除删除外)
......@@ -130,11 +133,11 @@ FROM t_sys_menu
WHERE menu_id IN (201, 205, 206)
AND del_flag = '0';
-- 为DEALER_MANAGER角色分配出库查询按钮权限
-- 为DEALER_MANAGER角色分配出库查询按钮权限(只读权限)
INSERT INTO t_sys_role_menu (role_id, menu_id, create_by, create_time, update_by, update_time, del_flag)
SELECT @dealer_manager_role_id, menu_id, 'admin', NOW(), 'admin', NOW(), '0'
FROM t_sys_menu
WHERE menu_id IN (301, 302, 303, 304, 305)
WHERE menu_id IN (301, 305, 306, 307, 308)
AND del_flag = '0';
-- 为DEALER_MANAGER角色分配发票管理按钮权限(只读权限)
......
-- Apple经销商ERP系统 - 修复出库新增权限
-- 创建时间: 2025-01-27
-- 版本: v1.0
-- 设置数据库和字符集
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- 使用数据库
USE apple_erp;
-- =========================================
-- 1. 添加缺失的出库新增权限
-- =========================================
-- 检查是否已存在出库新增权限
SET @delivery_add_exists = (SELECT COUNT(*) FROM t_sys_menu WHERE perms = 'delivery:add' AND del_flag = '0');
-- 如果不存在,则添加出库新增权限
INSERT INTO t_sys_menu (menu_id, parent_id, menu_name, menu_type, path, icon, sort, status, perms, create_by, create_time, update_by, update_time, del_flag)
SELECT 302, 3, '出库新增', '2', '', '', 2, '1', 'delivery:add', 'admin', NOW(), 'admin', NOW(), '0'
WHERE @delivery_add_exists = 0;
-- =========================================
-- 2. 为所有角色分配出库新增权限
-- =========================================
-- 获取ADMIN角色ID
SET @admin_role_id = (SELECT role_id FROM t_sys_role WHERE role_code = 'ADMIN' AND del_flag = '0' LIMIT 1);
-- 为ADMIN角色分配出库新增权限
INSERT IGNORE INTO t_sys_role_menu (role_id, menu_id, create_by, create_time, update_by, update_time, del_flag)
SELECT @admin_role_id, menu_id, 'admin', NOW(), 'admin', NOW(), '0'
FROM t_sys_menu
WHERE perms = 'delivery:add' AND del_flag = '0';
-- 获取OPERATOR角色ID
SET @operator_role_id = (SELECT role_id FROM t_sys_role WHERE role_code = 'OPERATOR' AND del_flag = '0' LIMIT 1);
-- 为OPERATOR角色分配出库新增权限
INSERT IGNORE INTO t_sys_role_menu (role_id, menu_id, create_by, create_time, update_by, update_time, del_flag)
SELECT @operator_role_id, menu_id, 'admin', NOW(), 'admin', NOW(), '0'
FROM t_sys_menu
WHERE perms = 'delivery:add' AND del_flag = '0';
-- 获取DEALER_MANAGER角色ID
SET @dealer_manager_role_id = (SELECT role_id FROM t_sys_role WHERE role_code = 'DEALER_MANAGER' AND del_flag = '0' LIMIT 1);
-- 为DEALER_MANAGER角色分配出库新增权限
INSERT IGNORE INTO t_sys_role_menu (role_id, menu_id, create_by, create_time, update_by, update_time, del_flag)
SELECT @dealer_manager_role_id, menu_id, 'admin', NOW(), 'admin', NOW(), '0'
FROM t_sys_menu
WHERE perms = 'delivery:add' AND del_flag = '0';
-- 重置外键检查
SET FOREIGN_KEY_CHECKS = 1;
-- 输出完成信息
SELECT '出库新增权限修复完成!' AS message;
......@@ -3,13 +3,15 @@ import { request } from '../utils/request'
// 出库相关类型定义
export interface DeliveryInfo {
deliveryId: number
orderId: number
orderNo: string
deliveryNo: string
dealerCode: string
dealerName: string
orderNo: string
deliveryDate: string
totalAmount: number
deliveryStatus: number
warehouseCode: string
dataSource: string
uploadTime?: string
createBy?: string
createTime?: string
updateBy?: string
......@@ -22,42 +24,73 @@ export interface DeliveryItemInfo {
deliveryId?: number
productCode: string
productName: string
productQty: number
unitPrice: number
totalPrice: number
createBy?: string
createTime?: string
deliveryQty: number
deliveryPrice: number
deliveryAmount: number
}
export interface DeliveryQueryReq {
pageNum?: number
pageSize?: number
orderNo?: string
deliveryNo?: string
dealerCode?: string
dealerName?: string
deliveryStatus?: number
warehouseCode?: string
dataSource?: string
deliveryStartDate?: string
deliveryEndDate?: string
deliveryStatus?: number
minAmount?: number
maxAmount?: number
pageNum?: number
pageSize?: number
}
export interface DeliveryAddReq {
orderId: number
deliveryNo: string
dealerCode: string
dealerName: string
orderNo: string
deliveryDate: string
deliveryItems: Omit<DeliveryItemInfo, 'itemId' | 'deliveryId' | 'createBy' | 'createTime'>[]
deliveryStatus?: number
warehouseCode: string
dataSource?: string
deliveryItems: DeliveryItemAddReq[]
}
export interface DeliveryItemAddReq {
productCode: string
productName: string
deliveryQty: number
deliveryPrice: number
deliveryAmount: number
}
export interface DeliveryUpdateReq {
deliveryId: number
deliveryDate?: string
deliveryNo: string
dealerCode: string
dealerName: string
orderNo: string
deliveryDate: string
deliveryStatus?: number
deliveryItems?: Omit<DeliveryItemInfo, 'itemId' | 'deliveryId' | 'createBy' | 'createTime'>[]
warehouseCode: string
dataSource?: string
deliveryItems: DeliveryItemUpdateReq[]
}
export interface DeliveryItemUpdateReq {
itemId?: number
productCode: string
productName: string
deliveryQty: number
deliveryPrice: number
deliveryAmount: number
}
// 出库API接口
export const deliveryApi = {
// 分页查询出库列表
getDeliveryList: (params: DeliveryQueryReq) => {
return request.get('/api/delivery/list', { params })
return request.get('/api/delivery/list', params)
},
// 获取出库详情
......@@ -67,10 +100,10 @@ export const deliveryApi = {
// 新增出库
addDelivery: (data: DeliveryAddReq) => {
return request.post('/api/delivery/add', data)
return request.post('/api/delivery', data)
},
// 更新出库
// 修改出库
updateDelivery: (data: DeliveryUpdateReq) => {
return request.post('/api/delivery/update', data)
},
......@@ -81,14 +114,14 @@ export const deliveryApi = {
},
// 批量删除出库
batchDeleteDelivery: (deliveryIds: number[]) => {
batchDeleteDeliveries: (deliveryIds: number[]) => {
return request.post('/api/delivery/batchDelete', deliveryIds)
},
// 导出出库数据
exportDelivery: (params: DeliveryQueryReq) => {
return request.get('/api/delivery/export', { params, responseType: 'blob' })
// 修改出库状态
updateDeliveryStatus: (deliveryId: number, deliveryStatus: number) => {
return request.post(`/api/delivery/${deliveryId}/deliveryStatus`, null, {
params: { deliveryStatus }
})
}
}
export default deliveryApi
......
import { request } from '../utils/request'
// 发票相关类型定义
export interface InvoiceInfo {
invoiceId: number
orderId: number
invoiceNo: string
orderNo: string
deliveryNo: string
dealerCode: string
dealerName: string
invoiceDate: string
totalAmount: number
invoiceDate: string
invoiceStatus: number
invoiceNo?: string
taxRate: number
dataSource: string
uploadTime?: string
createBy?: string
createTime?: string
updateBy?: string
......@@ -19,79 +21,108 @@ export interface InvoiceInfo {
}
export interface InvoiceItemInfo {
itemId?: number
invoiceId?: number
itemId: number
invoiceId: number
invoiceNo: string
productCode: string
productName: string
productQty: number
unitPrice: number
totalPrice: number
itemAmount: number
taxRate: number
taxAmount: number
createBy?: string
createTime?: string
updateBy?: string
updateTime?: string
}
export interface InvoiceQueryReq {
pageNum?: number
pageSize?: number
invoiceNo?: string
orderNo?: string
deliveryNo?: string
dealerCode?: string
dealerName?: string
invoiceStatus?: number
dataSource?: string
invoiceStartDate?: string
invoiceEndDate?: string
invoiceStatus?: number
pageNum: number
pageSize: number
}
export interface InvoiceAddReq {
orderId: number
invoiceNo: string
orderNo: string
deliveryNo: string
dealerCode: string
dealerName: string
totalAmount: number
invoiceDate: string
invoiceNo?: string
invoiceItems: Omit<InvoiceItemInfo, 'itemId' | 'invoiceId' | 'createBy' | 'createTime'>[]
invoiceStatus?: number
taxRate: number
dataSource?: string
invoiceItems: InvoiceItemAddReq[]
}
export interface InvoiceUpdateReq {
invoiceId: number
invoiceDate?: string
invoiceNo: string
orderNo: string
deliveryNo: string
dealerCode: string
dealerName: string
totalAmount: number
invoiceDate: string
invoiceStatus?: number
invoiceNo?: string
invoiceItems?: Omit<InvoiceItemInfo, 'itemId' | 'invoiceId' | 'createBy' | 'createTime'>[]
taxRate: number
dataSource?: string
invoiceItems: InvoiceItemUpdateReq[]
}
export interface InvoiceItemAddReq {
productCode: string
productName: string
productQty: number
unitPrice: number
itemAmount: number
taxRate: number
taxAmount: number
}
export interface InvoiceItemUpdateReq {
itemId?: number
productCode: string
productName: string
productQty: number
unitPrice: number
itemAmount: number
taxRate: number
taxAmount: number
}
// 发票API接口
export const invoiceApi = {
// 分页查询发票列表
getInvoiceList: (params: InvoiceQueryReq) => {
return request.get('/api/invoice/list', { params })
return request.get('/api/invoice/list', params)
},
// 获取发票详情
getInvoiceDetail: (invoiceId: number) => {
return request.get(`/api/invoice/${invoiceId}`)
},
// 新增发票
addInvoice: (data: InvoiceAddReq) => {
return request.post('/api/invoice/add', data)
return request.post('/api/invoice', data)
},
// 更新发票
updateInvoice: (data: InvoiceUpdateReq) => {
return request.post('/api/invoice/update', data)
},
// 删除发票
deleteInvoice: (invoiceId: number) => {
return request.delete(`/api/invoice/${invoiceId}`)
},
// 批量删除发票
batchDeleteInvoice: (invoiceIds: number[]) => {
batchDeleteInvoices: (invoiceIds: number[]) => {
return request.post('/api/invoice/batchDelete', invoiceIds)
},
// 导出发票数据
exportInvoice: (params: InvoiceQueryReq) => {
return request.get('/api/invoice/export', { params, responseType: 'blob' })
updateInvoiceStatus: (invoiceId: number, invoiceStatus: number) => {
return request.post(`/api/invoice/${invoiceId}/invoiceStatus`, null, {
params: { invoiceStatus }
})
}
}
export default invoiceApi
......
......@@ -103,7 +103,7 @@ export interface OrderItemUpdateReq {
export const orderApi = {
// 分页查询订单列表
getOrderList: (params: OrderQueryReq) => {
return request.get('/order/list', { params })
return request.get('/order/list', params)
},
// 获取订单详情
......
......@@ -86,25 +86,25 @@
<table class="data-table">
<thead>
<tr>
<th>出库ID</th>
<th class="sortable">出库单号 ↕️</th>
<th>出库ID</th>
<th class="sortable">出库单号 ↕️</th>
<th>经销商编码</th>
<th>经销商名称</th>
<th>出库日期</th>
<th>出库金额</th>
<th>关联订单编号</th>
<th>出库状态</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="delivery in deliveryList" :key="delivery.deliveryId">
<td>{{ delivery.deliveryId }}</td>
<td>{{ delivery.deliveryNo }}</td>
<td>{{ delivery.dealerCode }}</td>
<td>{{ delivery.dealerName }}</td>
<td>{{ formatDate(delivery.deliveryDate) }}</td>
<td>{{ formatCurrency(delivery.totalAmount) }}</td>
<tr v-for="order in orderList" :key="order.deliveryId">
<td>{{ order.deliveryId }}</td>
<td>{{ order.deliveryNo }}</td>
<td>{{ order.dealerCode }}</td>
<td>{{ order.dealerName }}</td>
<td>{{ formatDate(order.deliveryDate) }}</td>
<td>{{ order.orderNo }}</td>
<td>
<span :class="getDeliveryStatusClass(delivery.deliveryStatus)">
{{ getDeliveryStatusText(delivery.deliveryStatus) }}
......@@ -113,6 +113,7 @@
<td>{{ formatTime(delivery.createTime || '') }}</td>
<td class="action-col">
<button @click="handleView(delivery)" class="view-btn">👁️ 查看</button>
<button @click="handleDelete(order)" class="delete-btn">🗑️ 删除</button>
</td>
</tr>
</tbody>
......@@ -298,6 +299,7 @@
v-model="addFormData.deliveryDate"
class="form-input"
type="datetime-local"
step="1"
required
/>
</div>
......@@ -409,7 +411,7 @@
<script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue'
import { deliveryApi, type DeliveryInfo, type DeliveryQueryReq } from '../../api/delivery'
import { deliveryApi, type DeliveryAddReq, type DeliveryInfo, type DeliveryQueryReq } from '../../api/delivery'
// 响应式数据
const loading = ref(false)
......@@ -433,12 +435,14 @@ const addFormData = reactive({
// 搜索参数
const searchParams = reactive({
orderNo: '',
deliveryNo: '',
dealerCode: '',
dealerName: '',
deliveryStatus: undefined,
startDate: '',
endDate: '',
warehouseCode: '',
dataSource: '',
deliveryStartDate: '',
deliveryEndDate: '',
pageNum: 1,
pageSize: 10
})
......@@ -551,9 +555,9 @@ const handleReset = () => {
fetchDeliveries()
}
const handleView = async (delivery: DeliveryInfo) => {
const handleView = async (order: DeliveryInfo) => {
try {
const response = await deliveryApi.getDeliveryDetail(delivery.deliveryId) as any
const response = await deliveryApi.getDeliveryDetail(order.deliveryId) as any
console.log('出库查询详情API响应:', response)
// 由于request.ts的响应拦截器已经处理了code=200的情况,直接返回data
......@@ -569,6 +573,19 @@ const handleView = async (delivery: DeliveryInfo) => {
}
}
const handleDelete = async (order: DeliveryInfo) => {
if (confirm(`确定要删除出库单"${order.deliveryNo}"吗?`)) {
try {
await deliveryApi.deleteDelivery(order.deliveryId)
showMessage('删除出库单成功', 'success')
fetchOrders() // 刷新列表
} catch (error) {
console.error('删除出库单失败:', error)
showMessage('删除出库单失败, 请重试', 'error')
}
}
}
const handleExport = () => {
showMessage('导出功能开发中...', 'warning')
......@@ -618,11 +635,36 @@ const calculateDeliveryItemTotal = (index: number) => {
const handleSubmitAdd = async () => {
try {
// 这里应该调用新增出库的API
// await deliveryApi.addDelivery(addFormData)
showMessage('新增出库功能开发中...', 'warning')
// 处理日期时间格式,将datetime-local格式转换为后端需要的格式
let formattedDeliveryDate = addFormData.deliveryDate
if (formattedDeliveryDate && formattedDeliveryDate.includes('T')) {
// 将 YYYY-MM-DDTHH:MM:SS 格式转换为 YYYY-MM-DD HH:MM:SS 格式
formattedDeliveryDate = formattedDeliveryDate.replace('T', ' ')
}
// 构造新增出库的请求数据
const deliveryData: DeliveryAddReq = {
deliveryNo: addFormData.deliveryNo,
dealerCode: addFormData.dealerCode,
dealerName: addFormData.dealerName,
orderNo: addFormData.orderNo,
deliveryDate: formattedDeliveryDate,
deliveryStatus: 1, // 默认已出库
warehouseCode: addFormData.warehouseCode,
dataSource: addFormData.dataSource || '系统录入',
deliveryItems: addFormData.deliveryItems.map(item => ({
productCode: item.productCode,
productName: item.productName,
deliveryQty: item.deliveryQty,
deliveryPrice: item.deliveryPrice,
deliveryAmount: item.deliveryAmount
}))
}
await deliveryApi.addDelivery(deliveryData)
showMessage('新增出库成功', 'success')
closeAddDialog()
// fetchOrders() // 刷新列表
fetchOrders() // 刷新列表
} catch (error) {
console.error('新增出库失败:', error)
showMessage('新增出库失败, 请重试', 'error')
......@@ -891,6 +933,11 @@ onMounted(() => {
color: white;
}
.delete-btn {
background: #dc3545;
color: white;
}
.status-btn {
background: #28a745;
color: white;
......
This diff is collapsed. Click to expand it.
......@@ -467,6 +467,8 @@ const searchParams = reactive<OrderQueryReq>({
invoiceStatus: undefined,
rebateCalcFlag: undefined,
verifyStatus: undefined,
minAmount: undefined,
maxAmount: undefined,
pageNum: 1,
pageSize: 10
})
......@@ -593,7 +595,20 @@ const showMessage = (message: string, type: 'success' | 'error' | 'warning' = 's
const fetchOrders = async () => {
try {
loading.value = true
const params = { ...searchParams, pageNum: pagination.pageNum, pageSize: pagination.pageSize }
// 构造查询参数对象
const params: OrderQueryReq = {
orderNo: searchParams.orderNo || undefined,
dealerCode: searchParams.dealerCode || undefined,
dealerName: searchParams.dealerName || undefined,
deliveryStatus: searchParams.deliveryStatus,
invoiceStatus: searchParams.invoiceStatus,
rebateCalcFlag: searchParams.rebateCalcFlag,
verifyStatus: searchParams.verifyStatus,
minAmount: searchParams.minAmount,
maxAmount: searchParams.maxAmount,
pageNum: pagination.pageNum,
pageSize: pagination.pageSize
}
const response = await orderApi.getOrderList(params) as any
console.log('API响应:', response) // 添加调试日志
......@@ -632,7 +647,9 @@ const handleReset = () => {
deliveryStatus: undefined,
invoiceStatus: undefined,
rebateCalcFlag: undefined,
verifyStatus: undefined
verifyStatus: undefined,
minAmount: undefined,
maxAmount: undefined
})
pagination.pageNum = 1
fetchOrders()
......