auto verify for order fulfillment and payment
This commit is contained in:
@@ -12,6 +12,9 @@ async function detail(id: string): Promise<OrderFulfillment> {
|
|||||||
async function create(request: OrderFulfillmentCreateRequest): Promise<OrderFulfillment> {
|
async function create(request: OrderFulfillmentCreateRequest): Promise<OrderFulfillment> {
|
||||||
return await axios.post(`${URI}/create`, request);
|
return await axios.post(`${URI}/create`, request);
|
||||||
}
|
}
|
||||||
|
async function createAndVerify(request: OrderFulfillmentCreateRequest): Promise<OrderFulfillment> {
|
||||||
|
return await axios.post(`${URI}/create-and-verify`, request);
|
||||||
|
}
|
||||||
async function prepareStock(request: FulfillmentPrepareStockRequest): Promise<OrderFulfillment> {
|
async function prepareStock(request: FulfillmentPrepareStockRequest): Promise<OrderFulfillment> {
|
||||||
return await axios.post(`${URI}/prepare-stock`, request);
|
return await axios.post(`${URI}/prepare-stock`, request);
|
||||||
}
|
}
|
||||||
@@ -28,4 +31,4 @@ async function revoke(request: FulfillmentRevokeRequest): Promise<OrderFulfillme
|
|||||||
return await axios.post(`${URI}/revoke`, request);
|
return await axios.post(`${URI}/revoke`, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default { list, detail, create, prepareStock, verify, reject, cancel, revoke };
|
export default { list, detail, create, createAndVerify, prepareStock, verify, reject, cancel, revoke };
|
||||||
|
|||||||
@@ -37,6 +37,9 @@ async function cancel(request: SalesOrderCancelRequest): Promise<SalesOrder> {
|
|||||||
async function receivePayment(request: OrderPaymentReceiveRequest): Promise<FundRecord> {
|
async function receivePayment(request: OrderPaymentReceiveRequest): Promise<FundRecord> {
|
||||||
return await axios.post(`${ORDER_URI}/payment/receive`, request);
|
return await axios.post(`${ORDER_URI}/payment/receive`, request);
|
||||||
}
|
}
|
||||||
|
async function receivePaymentAndVerify(request: OrderPaymentReceiveRequest): Promise<FundRecord> {
|
||||||
|
return await axios.post(`${ORDER_URI}/payment/receive-and-verify`, request);
|
||||||
|
}
|
||||||
async function verifyPayment(id: string): Promise<FundRecord> {
|
async function verifyPayment(id: string): Promise<FundRecord> {
|
||||||
return await axios.post(`${ORDER_URI}/payment/verify`, undefined, { params: { id } });
|
return await axios.post(`${ORDER_URI}/payment/verify`, undefined, { params: { id } });
|
||||||
}
|
}
|
||||||
@@ -77,6 +80,7 @@ export default {
|
|||||||
update,
|
update,
|
||||||
cancel,
|
cancel,
|
||||||
receivePayment,
|
receivePayment,
|
||||||
|
receivePaymentAndVerify,
|
||||||
verifyPayment,
|
verifyPayment,
|
||||||
rejectPayment,
|
rejectPayment,
|
||||||
cancelPayment,
|
cancelPayment,
|
||||||
|
|||||||
@@ -89,7 +89,7 @@
|
|||||||
</t-form-item>
|
</t-form-item>
|
||||||
</t-form>
|
</t-form>
|
||||||
<div v-else class="empty" v-text="'暂无可履约明细,请返回订单详情检查'" />
|
<div v-else class="empty" v-text="'暂无可履约明细,请返回订单详情检查'" />
|
||||||
<t-form class="form" label-align="left" label-width="6rem">
|
<t-form class="form" label-width="7rem">
|
||||||
<t-form-item label="履约时间" content-align="right">
|
<t-form-item label="履约时间" content-align="right">
|
||||||
<t-button
|
<t-button
|
||||||
theme="primary"
|
theme="primary"
|
||||||
@@ -99,6 +99,12 @@
|
|||||||
@click="pickerVisible = true"
|
@click="pickerVisible = true"
|
||||||
/>
|
/>
|
||||||
</t-form-item>
|
</t-form-item>
|
||||||
|
<t-form-item v-if="canDirectVerify" label="直接核销履约" content-align="right">
|
||||||
|
<t-switch v-model="directVerify" size="small" :disabled="isSaving" />
|
||||||
|
<template #help v-if="directVerify">
|
||||||
|
<span class="red">直接核销会立即扣减实物库存;提交前会校验库存,库存不足时不能提交。</span>
|
||||||
|
</template>
|
||||||
|
</t-form-item>
|
||||||
<t-form-item label="备注">
|
<t-form-item label="备注">
|
||||||
<t-textarea v-model="remark" borderless autosize maxlength="500" />
|
<t-textarea v-model="remark" borderless autosize maxlength="500" />
|
||||||
</t-form-item>
|
</t-form-item>
|
||||||
@@ -140,6 +146,7 @@ import { comparePackageQuantity, convertPackageQuantity, createPackageRequestNo,
|
|||||||
import { getErrorMessage } from "@/utils/error";
|
import { getErrorMessage } from "@/utils/error";
|
||||||
import { Message } from "@/utils/message";
|
import { Message } from "@/utils/message";
|
||||||
import { gaoRoleCodes, permissionCodes } from "@/utils/permission";
|
import { gaoRoleCodes, permissionCodes } from "@/utils/permission";
|
||||||
|
import { getProductStockShortageMessage, mergeProductStockRequirements } from "@/utils/productStock";
|
||||||
import { uploadPhotoList } from "@/utils/photo";
|
import { uploadPhotoList } from "@/utils/photo";
|
||||||
import { getProductPhotoURL } from "@/utils/product";
|
import { getProductPhotoURL } from "@/utils/product";
|
||||||
|
|
||||||
@@ -162,6 +169,7 @@ const photoItems = ref<PhotoItem[]>([]);
|
|||||||
const unitPickerVisible = ref(false);
|
const unitPickerVisible = ref(false);
|
||||||
const unitPickerSourceItemId = ref("");
|
const unitPickerSourceItemId = ref("");
|
||||||
const unitPickerDraft = ref<Array<string | number>>([]);
|
const unitPickerDraft = ref<Array<string | number>>([]);
|
||||||
|
const directVerify = ref(false);
|
||||||
const photoUrlList = computed(() => photoItems.value.map(item => item.url));
|
const photoUrlList = computed(() => photoItems.value.map(item => item.url));
|
||||||
const isPackage = computed(() => order.value?.orderType === "PACKAGE");
|
const isPackage = computed(() => order.value?.orderType === "PACKAGE");
|
||||||
const expectedItemType = computed(() => isPackage.value ? "PACKAGE_ENTITLEMENT" : "DIRECT_PRODUCT");
|
const expectedItemType = computed(() => isPackage.value ? "PACKAGE_ENTITLEMENT" : "DIRECT_PRODUCT");
|
||||||
@@ -172,6 +180,10 @@ const unitPickerOptions = computed(() => {
|
|||||||
return item ? getFulfillmentUnitList(item).map(unit => ({ label: unit.name, value: unit.id || "" })) : [];
|
return item ? getFulfillmentUnitList(item).map(unit => ({ label: unit.name, value: unit.id || "" })) : [];
|
||||||
});
|
});
|
||||||
const canFulfillByPayment = computed(() => order.value?.paymentStatus === "PAID" || userStore.hasRoles(gaoRoleCodes.storeManager));
|
const canFulfillByPayment = computed(() => order.value?.paymentStatus === "PAID" || userStore.hasRoles(gaoRoleCodes.storeManager));
|
||||||
|
const canDirectVerify = computed(() => userStore.hasRoles(gaoRoleCodes.storeManager)
|
||||||
|
&& userStore.hasPermissions(permissionCodes.orderFulfillment.create)
|
||||||
|
&& userStore.hasPermissions(permissionCodes.orderFulfillment.verify)
|
||||||
|
&& userStore.hasPermissions(permissionCodes.productStock.read));
|
||||||
|
|
||||||
async function loadData(): Promise<void> {
|
async function loadData(): Promise<void> {
|
||||||
const salesOrderId = String(route.query.salesOrderId || "");
|
const salesOrderId = String(route.query.salesOrderId || "");
|
||||||
@@ -343,6 +355,55 @@ function buildAttachments(): Partial<Attachment>[] {
|
|||||||
}] : []);
|
}] : []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function validateDirectStock(): Promise<boolean> {
|
||||||
|
const selected = sourceItems.value.filter(item => !!item.id && quantityMap[item.id]);
|
||||||
|
const skuMap = new Map<string, ProductSku>();
|
||||||
|
for (const item of selected) {
|
||||||
|
if (!item.skuId) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let sku = fulfillmentSkuMap[item.skuId];
|
||||||
|
if (!sku) {
|
||||||
|
try {
|
||||||
|
sku = await ProductAPI.skuDetail(item.skuId);
|
||||||
|
} catch {
|
||||||
|
// 统一在下方提示,避免部分 SKU 查询失败时静默跳过库存校验
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!sku) {
|
||||||
|
Message.warning(`${item.productNameSnapshot || "产品"} 的库存信息加载失败,请刷新后重试`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fulfillmentSkuMap[item.skuId] = sku;
|
||||||
|
skuMap.set(item.skuId, sku);
|
||||||
|
}
|
||||||
|
const requirementList = mergeProductStockRequirements(selected.flatMap(item => {
|
||||||
|
const sku = item.skuId ? skuMap.get(item.skuId) : undefined;
|
||||||
|
const unit = getFulfillmentUnit(item);
|
||||||
|
const quantity = normalizePackageQuantity(quantityMap[item.id || ""] || "");
|
||||||
|
const baseQuantity = quantity && unit ? toPackageBaseQuantity(quantity, unit.baseQuantityPerUnit) : undefined;
|
||||||
|
if (!item.skuId || !sku?.stockEnabled || !baseQuantity) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return [{ skuId: item.skuId, baseQuantity, productName: item.productNameSnapshot || "未命名产品", unitName: "基础单位" }];
|
||||||
|
}));
|
||||||
|
if (!requirementList.length) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const stockList = await ProductAPI.stockBatchDetail({ skuIdList: requirementList.map(item => item.skuId) });
|
||||||
|
const shortageMessage = getProductStockShortageMessage(stockList, requirementList);
|
||||||
|
if (shortageMessage) {
|
||||||
|
Message.warning(`${shortageMessage},不能直接核销履约`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
Message.error(getErrorMessage(error, "库存查询失败,暂不能直接核销履约"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function validate(): boolean {
|
function validate(): boolean {
|
||||||
if (!order.value?.id) {
|
if (!order.value?.id) {
|
||||||
Message.warning("请从订单详情进入履约创建");
|
Message.warning("请从订单详情进入履约创建");
|
||||||
@@ -397,15 +458,19 @@ async function save(): Promise<void> {
|
|||||||
skuUnitId: fulfillmentUnitMap[item.id!]!,
|
skuUnitId: fulfillmentUnitMap[item.id!]!,
|
||||||
quantity: normalizePackageQuantity(quantityMap[item.id || ""])!
|
quantity: normalizePackageQuantity(quantityMap[item.id || ""])!
|
||||||
}));
|
}));
|
||||||
const result = await FulfillmentAPI.create({
|
const request = {
|
||||||
salesOrderId: order.value!.id!,
|
salesOrderId: order.value!.id!,
|
||||||
requestNo: requestNo.value,
|
requestNo: requestNo.value,
|
||||||
deliveredAt: resolveTimestamp(deliveredAtText.value),
|
deliveredAt: resolveTimestamp(deliveredAtText.value),
|
||||||
itemList,
|
itemList,
|
||||||
attachmentList: buildAttachments(),
|
attachmentList: buildAttachments(),
|
||||||
remark: remark.value.trim() || null
|
remark: remark.value.trim() || null
|
||||||
});
|
};
|
||||||
Message.success("履约单已提交");
|
if (directVerify.value && !await validateDirectStock()) return;
|
||||||
|
const result = directVerify.value
|
||||||
|
? await FulfillmentAPI.createAndVerify(request)
|
||||||
|
: await FulfillmentAPI.create(request);
|
||||||
|
Message.success(directVerify.value ? "履约单创建并核销成功" : "履约单已提交");
|
||||||
await router.replace(`/management/order-fulfillments/${result.id}`);
|
await router.replace(`/management/order-fulfillments/${result.id}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
Message.error(getErrorMessage(error, "履约单创建失败,重试会复用同一请求号"));
|
Message.error(getErrorMessage(error, "履约单创建失败,重试会复用同一请求号"));
|
||||||
|
|||||||
@@ -234,11 +234,12 @@ import type { Customer } from "@/types/Customer";
|
|||||||
import type { Product, ProductSku, ProductSkuUnit } from "@/types/Product";
|
import type { Product, ProductSku, ProductSkuUnit } from "@/types/Product";
|
||||||
import type { PhotoItem } from "@/types/Photo";
|
import type { PhotoItem } from "@/types/Photo";
|
||||||
import type { DirectProductOrderItemRequest } from "@/types/SalesOrder";
|
import type { DirectProductOrderItemRequest } from "@/types/SalesOrder";
|
||||||
import { createPackageRequestNo, normalizePackageQuantity, parsePackageAmount } from "@/utils/package";
|
import { createPackageRequestNo, normalizePackageQuantity, parsePackageAmount, toPackageBaseQuantity } from "@/utils/package";
|
||||||
import { formatProductAmount, getProductQuantityStep } from "@/utils/product";
|
import { formatProductAmount, getProductQuantityStep } from "@/utils/product";
|
||||||
import { getErrorMessage } from "@/utils/error";
|
import { getErrorMessage } from "@/utils/error";
|
||||||
import { Message } from "@/utils/message";
|
import { Message } from "@/utils/message";
|
||||||
import { permissionCodes } from "@/utils/permission";
|
import { permissionCodes } from "@/utils/permission";
|
||||||
|
import { getProductStockShortageMessage, mergeProductStockRequirements } from "@/utils/productStock";
|
||||||
import { uploadPhotoList } from "@/utils/photo";
|
import { uploadPhotoList } from "@/utils/photo";
|
||||||
import { useNavBarStore } from "@/store/navBarStore";
|
import { useNavBarStore } from "@/store/navBarStore";
|
||||||
import { useSettingStore } from "@/store/settingStore";
|
import { useSettingStore } from "@/store/settingStore";
|
||||||
@@ -289,6 +290,7 @@ const canReceiveImmediately = computed(() => userStore.hasPermissions(permission
|
|||||||
&& userStore.hasPermissions(permissionCodes.fundReceive.verify));
|
&& userStore.hasPermissions(permissionCodes.fundReceive.verify));
|
||||||
const canFulfillImmediately = computed(() => userStore.hasPermissions(permissionCodes.orderFulfillment.create)
|
const canFulfillImmediately = computed(() => userStore.hasPermissions(permissionCodes.orderFulfillment.create)
|
||||||
&& userStore.hasPermissions(permissionCodes.orderFulfillment.verify)
|
&& userStore.hasPermissions(permissionCodes.orderFulfillment.verify)
|
||||||
|
&& userStore.hasPermissions(permissionCodes.productStock.read)
|
||||||
&& (totalAmount.value === 0 || canReceiveImmediately.value));
|
&& (totalAmount.value === 0 || canReceiveImmediately.value));
|
||||||
|
|
||||||
watch(fulfillAll, value => {
|
watch(fulfillAll, value => {
|
||||||
@@ -465,6 +467,34 @@ function resolveTimestamp(value: string): number | undefined {
|
|||||||
function buildAttachments(source: PhotoItem[] = photoItems.value): Partial<Attachment>[] {
|
function buildAttachments(source: PhotoItem[] = photoItems.value): Partial<Attachment>[] {
|
||||||
return source.flatMap(item => item.tempFileId ? [{ tempFileId: item.tempFileId, attachType: "PHOTO" }] : []);
|
return source.flatMap(item => item.tempFileId ? [{ tempFileId: item.tempFileId, attachType: "PHOTO" }] : []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function validateDirectStock(): Promise<boolean> {
|
||||||
|
const requirementList = mergeProductStockRequirements(items.value.flatMap(item => {
|
||||||
|
const sku = getSku(item);
|
||||||
|
const unit = getUnit(item);
|
||||||
|
const quantity = normalizePackageQuantity(item.quantity ?? "");
|
||||||
|
const baseQuantity = quantity && unit ? toPackageBaseQuantity(quantity, unit.baseQuantityPerUnit) : undefined;
|
||||||
|
if (!item.skuId || !sku?.stockEnabled || !baseQuantity) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return [{ skuId: item.skuId, baseQuantity, productName: getProduct(item)?.name || item.productName || "未命名产品", unitName: "基础单位" }];
|
||||||
|
}));
|
||||||
|
if (!requirementList.length) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const stockList = await ProductAPI.stockBatchDetail({ skuIdList: requirementList.map(item => item.skuId) });
|
||||||
|
const shortageMessage = getProductStockShortageMessage(stockList, requirementList);
|
||||||
|
if (shortageMessage) {
|
||||||
|
Message.warning(`${shortageMessage},不能直接履约`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
Message.error(getErrorMessage(error, "库存查询失败,暂不能直接履约"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
function validate(): boolean {
|
function validate(): boolean {
|
||||||
if (!customer.value?.id) { Message.warning("请选择客户"); return false; }
|
if (!customer.value?.id) { Message.warning("请选择客户"); return false; }
|
||||||
if (!items.value.length) { Message.warning("请至少添加一项产品"); return false; }
|
if (!items.value.length) { Message.warning("请至少添加一项产品"); return false; }
|
||||||
@@ -515,6 +545,7 @@ async function submitOrder(): Promise<void> {
|
|||||||
if (!requestNo.value) requestNo.value = createPackageRequestNo();
|
if (!requestNo.value) requestNo.value = createPackageRequestNo();
|
||||||
isSaving.value = true;
|
isSaving.value = true;
|
||||||
try {
|
try {
|
||||||
|
if (fulfillAll.value && !await validateDirectStock()) return;
|
||||||
const itemList = items.value.map((item, index) => ({
|
const itemList = items.value.map((item, index) => ({
|
||||||
skuId: item.skuId!,
|
skuId: item.skuId!,
|
||||||
skuUnitId: item.skuUnitId!,
|
skuUnitId: item.skuUnitId!,
|
||||||
@@ -715,8 +746,8 @@ onUnmounted(() => navBarStore.clearRight());
|
|||||||
|
|
||||||
.submit-wrap {
|
.submit-wrap {
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
left: 2rem;
|
left: 1.5rem;
|
||||||
right: 2rem;
|
right: 1.5rem;
|
||||||
border: 1px solid rgba(0, 0, 0, .05);
|
border: 1px solid rgba(0, 0, 0, .05);
|
||||||
bottom: calc(env(safe-area-inset-bottom, 0) + 1rem);
|
bottom: calc(env(safe-area-inset-bottom, 0) + 1rem);
|
||||||
z-index: 12;
|
z-index: 12;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
<t-form
|
<t-form
|
||||||
v-if="order"
|
v-if="order"
|
||||||
class="form"
|
class="form"
|
||||||
label-width="6rem"
|
label-width="7rem"
|
||||||
v-entrance-transition="70"
|
v-entrance-transition="70"
|
||||||
>
|
>
|
||||||
<t-form-item label="收款金额" required-mark>
|
<t-form-item label="收款金额" required-mark>
|
||||||
@@ -31,8 +31,9 @@
|
|||||||
size="extra-small"
|
size="extra-small"
|
||||||
theme="primary"
|
theme="primary"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
content="全额收款"
|
||||||
@click="fillUnpaidAmount"
|
@click="fillUnpaidAmount"
|
||||||
>全额收款</t-button>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</t-input>
|
</t-input>
|
||||||
</t-form-item>
|
</t-form-item>
|
||||||
@@ -55,6 +56,12 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</t-form-item>
|
</t-form-item>
|
||||||
|
<t-form-item v-if="canDirectVerify" label="直接核销收款" content-align="right">
|
||||||
|
<t-switch v-model="directVerify" size="small" />
|
||||||
|
<template #help v-if="directVerify">
|
||||||
|
<span class="red">店长直接核销后,收款会立即计入订单已收款,不再进入待核销队列。</span>
|
||||||
|
</template>
|
||||||
|
</t-form-item>
|
||||||
<t-form-item label="备注">
|
<t-form-item label="备注">
|
||||||
<t-textarea
|
<t-textarea
|
||||||
v-model="remark"
|
v-model="remark"
|
||||||
@@ -95,7 +102,7 @@ import type { PhotoItem } from "@/types/Photo";
|
|||||||
import { createPackageRequestNo, formatPackageAmount, formatPackageAmountInput, parsePackageAmount } from "@/utils/package";
|
import { createPackageRequestNo, formatPackageAmount, formatPackageAmountInput, parsePackageAmount } from "@/utils/package";
|
||||||
import { getErrorMessage } from "@/utils/error";
|
import { getErrorMessage } from "@/utils/error";
|
||||||
import { Message } from "@/utils/message";
|
import { Message } from "@/utils/message";
|
||||||
import { permissionCodes } from "@/utils/permission";
|
import { gaoRoleCodes, permissionCodes } from "@/utils/permission";
|
||||||
import { uploadPhotoList } from "@/utils/photo";
|
import { uploadPhotoList } from "@/utils/photo";
|
||||||
|
|
||||||
defineOptions({ name: "SalesOrderPayment" });
|
defineOptions({ name: "SalesOrderPayment" });
|
||||||
@@ -114,6 +121,10 @@ const remark = ref("");
|
|||||||
const photoItems = ref<PhotoItem[]>([]);
|
const photoItems = ref<PhotoItem[]>([]);
|
||||||
const photoUrlList = computed(() => photoItems.value.map(item => item.url));
|
const photoUrlList = computed(() => photoItems.value.map(item => item.url));
|
||||||
const requestNo = ref("");
|
const requestNo = ref("");
|
||||||
|
const directVerify = ref(false);
|
||||||
|
const canDirectVerify = computed(() => userStore.hasRoles(gaoRoleCodes.storeManager)
|
||||||
|
&& userStore.hasPermissions(permissionCodes.fundReceive.create)
|
||||||
|
&& userStore.hasPermissions(permissionCodes.fundReceive.verify));
|
||||||
|
|
||||||
function openOccurredAtPicker(): void {
|
function openOccurredAtPicker(): void {
|
||||||
draftTime.value = occurredAtText.value || Time.formatDateTime(new Date());
|
draftTime.value = occurredAtText.value || Time.formatDateTime(new Date());
|
||||||
@@ -162,6 +173,10 @@ async function loadData(): Promise<void> {
|
|||||||
|
|
||||||
async function save(): Promise<void> {
|
async function save(): Promise<void> {
|
||||||
if (saving.value || !order.value?.id) return;
|
if (saving.value || !order.value?.id) return;
|
||||||
|
if (directVerify.value && !canDirectVerify.value) {
|
||||||
|
Message.warning("当前账号没有店长直接核销权限");
|
||||||
|
return;
|
||||||
|
}
|
||||||
const amount = parsePackageAmount(amountText.value);
|
const amount = parsePackageAmount(amountText.value);
|
||||||
const attachmentList = buildAttachments();
|
const attachmentList = buildAttachments();
|
||||||
if (amount === undefined || amount === 0) {
|
if (amount === undefined || amount === 0) {
|
||||||
@@ -175,15 +190,18 @@ async function save(): Promise<void> {
|
|||||||
if (!requestNo.value) requestNo.value = createPackageRequestNo();
|
if (!requestNo.value) requestNo.value = createPackageRequestNo();
|
||||||
saving.value = true;
|
saving.value = true;
|
||||||
try {
|
try {
|
||||||
const record = await SalesOrderAPI.receivePayment({
|
const request = {
|
||||||
salesOrderId: order.value.id,
|
salesOrderId: order.value.id,
|
||||||
requestNo: requestNo.value,
|
requestNo: requestNo.value,
|
||||||
amount,
|
amount,
|
||||||
occurredAt: resolveTimestamp(occurredAtText.value),
|
occurredAt: resolveTimestamp(occurredAtText.value),
|
||||||
attachmentList,
|
attachmentList,
|
||||||
remark: remark.value.trim() || null
|
remark: remark.value.trim() || null
|
||||||
});
|
};
|
||||||
Message.success("收款登记已提交");
|
const record = directVerify.value
|
||||||
|
? await SalesOrderAPI.receivePaymentAndVerify(request)
|
||||||
|
: await SalesOrderAPI.receivePayment(request);
|
||||||
|
Message.success(directVerify.value ? "收款登记并核销成功" : "收款登记已提交");
|
||||||
await router.replace(record.id && userStore.hasPermissions(permissionCodes.fundReceive.create)
|
await router.replace(record.id && userStore.hasPermissions(permissionCodes.fundReceive.create)
|
||||||
? `/management/fund-records/${record.id}`
|
? `/management/fund-records/${record.id}`
|
||||||
: `/management/sales-orders/${order.value.id}`);
|
: `/management/sales-orders/${order.value.id}`);
|
||||||
|
|||||||
Reference in New Issue
Block a user