feat: list group buy orders for dispatch
This commit is contained in:
40
admin-web/src/api/groupBuyApi.test.ts
Normal file
40
admin-web/src/api/groupBuyApi.test.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { filterPendingDeliveryGroupBuyOrders, groupBuyOrderDispatchLabel } from './groupBuyApi'
|
||||
import type { GroupBuyOrder } from '../types'
|
||||
|
||||
describe('group buy dispatch helpers', () => {
|
||||
it('keeps only group buy orders waiting for delivery', () => {
|
||||
const orders = [
|
||||
groupBuyOrder({ id: 1, status: 'PENDING_DELIVERY' }),
|
||||
groupBuyOrder({ id: 2, status: 'DELIVERING' }),
|
||||
groupBuyOrder({ id: 3, status: 'PENDING_PICKUP' })
|
||||
]
|
||||
|
||||
expect(filterPendingDeliveryGroupBuyOrders(orders).map((item) => item.id)).toEqual([1])
|
||||
})
|
||||
|
||||
it('builds a readable dispatch label', () => {
|
||||
expect(groupBuyOrderDispatchLabel(groupBuyOrder({
|
||||
orderNo: 'GB00000001',
|
||||
groupBuyTitle: 'Today eggs',
|
||||
quantity: 2,
|
||||
amountCent: 5980
|
||||
}))).toBe('GB00000001 Today eggs x2 ¥59.80')
|
||||
})
|
||||
})
|
||||
|
||||
function groupBuyOrder(overrides: Partial<GroupBuyOrder>): GroupBuyOrder {
|
||||
return {
|
||||
id: 1,
|
||||
orderNo: 'GB00000001',
|
||||
groupBuyId: 1,
|
||||
groupBuyTitle: 'Today eggs',
|
||||
quantity: 1,
|
||||
priceCent: 2990,
|
||||
amountCent: 2990,
|
||||
deliveryMethod: 'IMMEDIATE',
|
||||
status: 'PENDING_DELIVERY',
|
||||
offlinePayStatus: 'UNPAID',
|
||||
...overrides
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,22 @@
|
||||
import type { GroupBuy } from '../types'
|
||||
import type { GroupBuy, GroupBuyOrder } from '../types'
|
||||
import { apiGet, apiPost, apiPut } from './http'
|
||||
|
||||
export function listGroupBuys() {
|
||||
return apiGet<GroupBuy[]>('/api/admin/group-buys')
|
||||
}
|
||||
|
||||
export function listGroupBuyOrders(groupBuyId: number) {
|
||||
return apiGet<GroupBuyOrder[]>(`/api/admin/group-buys/${groupBuyId}/orders`)
|
||||
}
|
||||
|
||||
export function filterPendingDeliveryGroupBuyOrders(orders: GroupBuyOrder[]) {
|
||||
return orders.filter((order) => order.status === 'PENDING_DELIVERY')
|
||||
}
|
||||
|
||||
export function groupBuyOrderDispatchLabel(order: GroupBuyOrder) {
|
||||
return `${order.orderNo} ${order.groupBuyTitle} x${order.quantity} ¥${(order.amountCent / 100).toFixed(2)}`
|
||||
}
|
||||
|
||||
export function createGroupBuy(data: Partial<GroupBuy>) {
|
||||
return apiPost<GroupBuy>('/api/admin/group-buys', data)
|
||||
}
|
||||
|
||||
@@ -101,6 +101,22 @@ export interface GroupBuy {
|
||||
pickupAddress?: string
|
||||
}
|
||||
|
||||
export interface GroupBuyOrder {
|
||||
id: number
|
||||
orderNo: string
|
||||
groupBuyId: number
|
||||
groupBuyTitle: string
|
||||
coverUrl?: string
|
||||
quantity: number
|
||||
priceCent: number
|
||||
amountCent: number
|
||||
deliveryMethod: string
|
||||
status: string
|
||||
offlinePayStatus: string
|
||||
remark?: string
|
||||
createdAt?: string
|
||||
}
|
||||
|
||||
export interface SecondGoods {
|
||||
id: number
|
||||
title: string
|
||||
|
||||
@@ -3,6 +3,12 @@ import { onMounted, reactive, ref } from 'vue'
|
||||
import { Plus, Refresh, Van } from '@element-plus/icons-vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { listGoodsOrders, listExpressOrders } from '../api/orderApi'
|
||||
import {
|
||||
filterPendingDeliveryGroupBuyOrders,
|
||||
groupBuyOrderDispatchLabel,
|
||||
listGroupBuyOrders,
|
||||
listGroupBuys
|
||||
} from '../api/groupBuyApi'
|
||||
import {
|
||||
assignExpressOrder,
|
||||
assignGoodsOrder,
|
||||
@@ -11,7 +17,7 @@ import {
|
||||
listDeliveryOrders,
|
||||
listDeliveryUsers
|
||||
} from '../api/deliveryApi'
|
||||
import type { DeliveryOrder, DeliveryUser, ExpressOrder, GoodsOrder } from '../types'
|
||||
import type { DeliveryOrder, DeliveryUser, ExpressOrder, GoodsOrder, GroupBuyOrder } from '../types'
|
||||
import { statusText } from '../utils/format'
|
||||
|
||||
const loading = ref(false)
|
||||
@@ -19,22 +25,28 @@ const riders = ref<DeliveryUser[]>([])
|
||||
const tasks = ref<DeliveryOrder[]>([])
|
||||
const goodsOrders = ref<GoodsOrder[]>([])
|
||||
const expressOrders = ref<ExpressOrder[]>([])
|
||||
const groupBuyOrders = ref<GroupBuyOrder[]>([])
|
||||
const riderForm = reactive({ userId: 3, name: '', phone: '', enabled: true })
|
||||
const dispatchForm = reactive({ goodsOrderId: undefined as number | undefined, expressOrderId: undefined as number | undefined, groupBuyOrderId: undefined as number | undefined, riderId: undefined as number | undefined })
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
try {
|
||||
const [riderRows, taskRows, goodsRows, expressRows] = await Promise.all([
|
||||
const [riderRows, taskRows, goodsRows, expressRows, groupBuyRows] = await Promise.all([
|
||||
listDeliveryUsers(),
|
||||
listDeliveryOrders(),
|
||||
listGoodsOrders({ status: 'PENDING_DELIVERY' }),
|
||||
listExpressOrders('PENDING_PICKUP')
|
||||
listExpressOrders('PENDING_PICKUP'),
|
||||
listGroupBuys()
|
||||
])
|
||||
const groupOrderRows = groupBuyRows.length
|
||||
? ([] as GroupBuyOrder[]).concat(...await Promise.all(groupBuyRows.map((item) => listGroupBuyOrders(item.id))))
|
||||
: []
|
||||
riders.value = riderRows
|
||||
tasks.value = taskRows
|
||||
goodsOrders.value = goodsRows
|
||||
expressOrders.value = expressRows
|
||||
groupBuyOrders.value = filterPendingDeliveryGroupBuyOrders(groupOrderRows)
|
||||
if (!dispatchForm.riderId && riderRows[0]) dispatchForm.riderId = riderRows[0].id
|
||||
} catch (error) {
|
||||
ElMessage.error(error instanceof Error ? error.message : '加载失败')
|
||||
@@ -113,7 +125,9 @@ onMounted(load)
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="团购订单">
|
||||
<div class="toolbar">
|
||||
<el-input-number v-model="dispatchForm.groupBuyOrderId" :min="1" />
|
||||
<el-select v-model="dispatchForm.groupBuyOrderId" placeholder="待配送团购订单" style="width: 320px">
|
||||
<el-option v-for="item in groupBuyOrders" :key="item.id" :label="groupBuyOrderDispatchLabel(item)" :value="item.id" />
|
||||
</el-select>
|
||||
<el-button type="primary" :icon="Van" @click="dispatch('group')">派单</el-button>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
|
||||
Reference in New Issue
Block a user