Merge remote-tracking branch 'origin/codex/xuxiake-mainline' into codex/wuyongjie-ai-render-texture-resign
This commit is contained in:
commit
e3217c6bc1
@ -7679,6 +7679,15 @@ describe("NonIntegratedDetailClient", () => {
|
||||
executeStandard: "GB/T3324-2024",
|
||||
},
|
||||
],
|
||||
sampleMeasurementRows: [
|
||||
{
|
||||
skuId: "sku-pricing-1",
|
||||
lengthCm: "",
|
||||
widthCm: "",
|
||||
heightCm: "",
|
||||
weightKg: "",
|
||||
},
|
||||
],
|
||||
}),
|
||||
);
|
||||
|
||||
@ -7724,11 +7733,34 @@ describe("NonIntegratedDetailClient", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
expect(screen.getByRole("button", { name: "确认推送" })).toBeEnabled();
|
||||
expect(screen.getByRole("button", { name: "批量确认推送" })).toBeEnabled();
|
||||
expect(screen.getByRole("button", { name: "确认推送" })).toBeDisabled();
|
||||
expect(screen.getByRole("button", { name: "批量确认推送" })).toBeDisabled();
|
||||
expect(screen.queryByText("已录入")).not.toBeInTheDocument();
|
||||
expect(screen.queryByText("已推送")).not.toBeInTheDocument();
|
||||
|
||||
await actor.click(screen.getByTestId("document-workspace-trigger-样包测量"));
|
||||
await actor.type(
|
||||
screen.getByTestId("sample-measurement-lengthCm-sku-pricing-1"),
|
||||
"120",
|
||||
);
|
||||
await actor.type(
|
||||
screen.getByTestId("sample-measurement-widthCm-sku-pricing-1"),
|
||||
"60",
|
||||
);
|
||||
await actor.type(
|
||||
screen.getByTestId("sample-measurement-heightCm-sku-pricing-1"),
|
||||
"75",
|
||||
);
|
||||
await actor.type(
|
||||
screen.getByTestId("sample-measurement-weightKg-sku-pricing-1"),
|
||||
"18.5",
|
||||
);
|
||||
|
||||
await actor.click(screen.getByTestId("document-workspace-trigger-产品核价"));
|
||||
|
||||
expect(screen.getByRole("button", { name: "确认推送" })).toBeEnabled();
|
||||
expect(screen.getByRole("button", { name: "批量确认推送" })).toBeEnabled();
|
||||
|
||||
const savedProduct = getNonIntegratedProductById("DNZ0001-product-pricing");
|
||||
expect(savedProduct?.documentWorkspaceConfirmations?.产品核价).not.toBe(true);
|
||||
expect(savedProduct?.documentWorkspaceApprovedAt?.产品核价).toBeUndefined();
|
||||
|
||||
@ -1452,6 +1452,7 @@ export default function NonIntegratedDetailClient({
|
||||
displayedProductPricingRowsReadyForPush,
|
||||
displayedSampleMeasurementRowsConfirmedByPricing,
|
||||
displayedSampleMeasurementRowsComplete,
|
||||
isDisplayedProductPricingRowReadyForPush,
|
||||
isSampleMeasurementSkuLocked,
|
||||
planningLayoutHasContent,
|
||||
populatedFinishedSampleShipmentRowCount,
|
||||
@ -4126,6 +4127,7 @@ export default function NonIntegratedDetailClient({
|
||||
isReadOnly,
|
||||
isNodeLocked: isProductPricingNodeLocked,
|
||||
canUsePushControls: canUseProductPricingPushControls,
|
||||
isRowReadyForPush: isDisplayedProductPricingRowReadyForPush,
|
||||
onUpdateRow: updateProductPricingRow,
|
||||
onConfirmPushRows: handleConfirmProductPricingPushRows,
|
||||
},
|
||||
|
||||
@ -17,8 +17,8 @@ import {
|
||||
import { isProductFactoryRowComplete } from "./productFactoryHelpers";
|
||||
import {
|
||||
isProductLimitRowComplete,
|
||||
isProductPricingRowComplete,
|
||||
isProductPricingRowReadyForJstPush,
|
||||
isProductPricingRowReadyForPush,
|
||||
isProductPricingRowSystemEntered,
|
||||
type PlanningLayoutSkuRow,
|
||||
type ProductLimitDisplayRow,
|
||||
@ -143,6 +143,16 @@ export function useNonIntegratedWorkflowCompletion({
|
||||
displayedProductPricingRows.every((row) =>
|
||||
isProductPricingRowReadyForJstPush(row, row),
|
||||
);
|
||||
const displayedSampleMeasurementCompletionBySkuId = useMemo(
|
||||
() =>
|
||||
new Map(
|
||||
displayedProductSampleMeasurementRows.map((row) => [
|
||||
row.skuId,
|
||||
isSampleMeasurementRowComplete(row),
|
||||
]),
|
||||
),
|
||||
[displayedProductSampleMeasurementRows],
|
||||
);
|
||||
const allProductPricingRowsSystemEntered =
|
||||
productPricingRows.length > 0 &&
|
||||
productPricingRows.every(isProductPricingRowSystemEntered);
|
||||
@ -153,12 +163,31 @@ export function useNonIntegratedWorkflowCompletion({
|
||||
displayedProductPricingRows.every(isProductPricingRowSystemEntered);
|
||||
const displayedProductPricingRowsReadyForPush =
|
||||
displayedProductPricingRows.length > 0 &&
|
||||
displayedProductPricingRowsComplete &&
|
||||
displayedProductPricingRows.some(
|
||||
displayedProductPricingRows.some((row) =>
|
||||
isProductPricingRowReadyForPush({
|
||||
pricingRow: row,
|
||||
sampleMeasurementComplete:
|
||||
displayedSampleMeasurementCompletionBySkuId.get(row.skuId) ?? false,
|
||||
}),
|
||||
) &&
|
||||
displayedProductPricingRows.every(
|
||||
(row) =>
|
||||
isProductPricingRowReadyForJstPush(row, row) &&
|
||||
!isProductPricingRowSystemEntered(row),
|
||||
isProductPricingRowSystemEntered(row) ||
|
||||
isProductPricingRowReadyForPush({
|
||||
pricingRow: row,
|
||||
sampleMeasurementComplete:
|
||||
displayedSampleMeasurementCompletionBySkuId.get(row.skuId) ?? false,
|
||||
}),
|
||||
);
|
||||
const isDisplayedProductPricingRowReadyForPush = useCallback(
|
||||
(row: ProductPricingDisplayRow) =>
|
||||
isProductPricingRowReadyForPush({
|
||||
pricingRow: row,
|
||||
sampleMeasurementComplete:
|
||||
displayedSampleMeasurementCompletionBySkuId.get(row.skuId) ?? false,
|
||||
}),
|
||||
[displayedSampleMeasurementCompletionBySkuId],
|
||||
);
|
||||
const productPricingSystemEnteredSkuIdSet = useMemo(
|
||||
() =>
|
||||
new Set(
|
||||
@ -213,6 +242,7 @@ export function useNonIntegratedWorkflowCompletion({
|
||||
displayedProductPricingRowsReadyForPush,
|
||||
displayedSampleMeasurementRowsConfirmedByPricing,
|
||||
displayedSampleMeasurementRowsComplete,
|
||||
isDisplayedProductPricingRowReadyForPush,
|
||||
isSampleMeasurementSkuLocked,
|
||||
planningLayoutHasContent,
|
||||
populatedFinishedSampleShipmentRowCount,
|
||||
|
||||
@ -6,7 +6,6 @@ import {
|
||||
type NonIntegratedPricingRow,
|
||||
} from "../nonIntegratedStorage";
|
||||
import {
|
||||
isProductPricingRowReadyForJstPush,
|
||||
isProductPricingRowSystemEntered,
|
||||
PRODUCT_PRICING_JST_PUSH_ENABLED,
|
||||
type ProductPricingDisplayRow,
|
||||
@ -21,6 +20,7 @@ type ProductPricingWorkspaceProps = {
|
||||
isReadOnly: boolean;
|
||||
isNodeLocked: boolean;
|
||||
canUsePushControls: boolean;
|
||||
isRowReadyForPush: (row: ProductPricingDisplayRow) => boolean;
|
||||
onUpdateRow: (
|
||||
skuId: string,
|
||||
key: ProductPricingFieldKey,
|
||||
@ -93,6 +93,7 @@ export function ProductPricingWorkspace({
|
||||
isReadOnly,
|
||||
isNodeLocked,
|
||||
canUsePushControls,
|
||||
isRowReadyForPush,
|
||||
onUpdateRow,
|
||||
onConfirmPushRows,
|
||||
}: ProductPricingWorkspaceProps) {
|
||||
@ -153,8 +154,7 @@ export function ProductPricingWorkspace({
|
||||
<tbody>
|
||||
{displayedRows.map((row) => {
|
||||
const isSystemEntered = isProductPricingRowSystemEntered(row);
|
||||
const pricingReadyForFuturePush =
|
||||
isProductPricingRowReadyForJstPush(row, row);
|
||||
const pricingReadyForFuturePush = isRowReadyForPush(row);
|
||||
const isModularParentRow =
|
||||
isDraftGroupModularParentSkuItem(row);
|
||||
const virtualInventoryStatusMeta =
|
||||
@ -251,14 +251,15 @@ export function ProductPricingWorkspace({
|
||||
title={
|
||||
isSystemEntered
|
||||
? "当前 SKU 已录入系统,后续以聚水潭回传状态为准"
|
||||
: PRODUCT_PRICING_JST_PUSH_ENABLED &&
|
||||
pricingReadyForFuturePush
|
||||
? "确认推送当前 SKU 到聚水潭"
|
||||
: !PRODUCT_PRICING_JST_PUSH_ENABLED
|
||||
? "聚水潭接口未接入,暂不可确认推送"
|
||||
: pricingReadyForFuturePush
|
||||
? "聚水潭接口未接入,暂不可确认推送"
|
||||
? "确认推送当前 SKU 到聚水潭"
|
||||
: isModularParentRow
|
||||
? "当前模块化父商品将直接录入聚水潭组合装"
|
||||
: "请先填写成本价"
|
||||
: row.costPrice.trim().length > 0
|
||||
? "请先填写当前 SKU 的样包测量数据"
|
||||
: "请先填写成本价"
|
||||
}
|
||||
className="inline-flex h-7 min-w-[52px] items-center justify-center rounded-full bg-[#1f8bff] px-3 text-xs font-apple-medium text-white shadow-sm transition hover:bg-[#1478df] disabled:cursor-not-allowed disabled:bg-apple-bg-tertiary disabled:text-apple-label-tertiary disabled:shadow-none"
|
||||
>
|
||||
|
||||
@ -38,6 +38,8 @@ export function ProductPricingHeaderActions({
|
||||
? "聚水潭接口未接入,暂不可批量确认推送"
|
||||
: !rowsComplete
|
||||
? "当前批次成本价未填写完成"
|
||||
: !rowsReadyForPush
|
||||
? "当前批次样包测量未填写完成"
|
||||
: "批量确认推送当前批次 SKU";
|
||||
|
||||
return (
|
||||
|
||||
@ -178,7 +178,9 @@ export function normalizePricingRowsForPayload(
|
||||
);
|
||||
}
|
||||
|
||||
export function isProductPricingRowComplete(row: NonIntegratedPricingRow) {
|
||||
export function isProductPricingRowComplete(
|
||||
row: Pick<NonIntegratedPricingRow, "costPrice">,
|
||||
) {
|
||||
return row.costPrice.trim().length > 0;
|
||||
}
|
||||
|
||||
@ -205,6 +207,32 @@ export function isProductPricingRowSystemEntered(
|
||||
);
|
||||
}
|
||||
|
||||
export function isProductPricingRowReadyForPush({
|
||||
pricingRow,
|
||||
sampleMeasurementComplete,
|
||||
}: {
|
||||
pricingRow: Pick<
|
||||
ProductPricingDisplayRow,
|
||||
| "costPrice"
|
||||
| "systemEnteredAt"
|
||||
| "source"
|
||||
| "skuCode"
|
||||
| "barcode"
|
||||
| "componentDetails"
|
||||
>;
|
||||
sampleMeasurementComplete: boolean;
|
||||
}) {
|
||||
if (isProductPricingRowSystemEntered(pricingRow)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isDraftGroupModularParentSkuItem(pricingRow)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return sampleMeasurementComplete && isProductPricingRowComplete(pricingRow);
|
||||
}
|
||||
|
||||
export function createProductLimitRowFromSku(
|
||||
sku: NonIntegratedSkuItem,
|
||||
spu: string,
|
||||
|
||||
@ -30,6 +30,7 @@ import {
|
||||
} from "../first-quality/firstQualityHelpers";
|
||||
import {
|
||||
normalizeFinishedSampleShipmentShipped,
|
||||
isSampleMeasurementRowComplete,
|
||||
updateFinishedSampleShipmentRowsForSku,
|
||||
updateSampleMeasurementRowsForSku,
|
||||
} from "../sample-workflow/sampleWorkflowHelpers";
|
||||
@ -43,9 +44,7 @@ import {
|
||||
createPlanningLayoutClipboardValue,
|
||||
getPlanningLayoutDraftKey,
|
||||
getPlanningLayoutFieldTextValue,
|
||||
isProductPricingRowReadyForJstPush,
|
||||
isProductPricingRowComplete,
|
||||
isProductPricingRowSystemEntered,
|
||||
isProductPricingRowReadyForPush,
|
||||
parsePlanningLayoutListInput,
|
||||
PRODUCT_PRICING_JST_PUSH_ENABLED,
|
||||
removePlanningLayoutListValueFromRow,
|
||||
@ -188,16 +187,24 @@ export function useProductWorkflowRowController({
|
||||
) {
|
||||
if (!canUseProductPricingPushControls) return;
|
||||
if (isReadOnly || isProductPricingNodeLocked) return;
|
||||
const sampleMeasurementCompletionBySkuId = new Map(
|
||||
productSampleMeasurementRows.map((row) => [
|
||||
row.skuId,
|
||||
isSampleMeasurementRowComplete(row),
|
||||
]),
|
||||
);
|
||||
const readyRows = rows.filter(
|
||||
(row) =>
|
||||
isProductPricingRowReadyForJstPush(
|
||||
row,
|
||||
workflowSkuItems.find((item) => item.id === row.skuId),
|
||||
) &&
|
||||
!isProductPricingRowSystemEntered(row),
|
||||
isProductPricingRowReadyForPush({
|
||||
pricingRow: row,
|
||||
sampleMeasurementComplete:
|
||||
sampleMeasurementCompletionBySkuId.get(row.skuId) ?? false,
|
||||
}),
|
||||
);
|
||||
if (readyRows.length === 0) {
|
||||
setSaveMessage("请先填写要推送 SKU 的成本价,已录入的 SKU 不会重复推送");
|
||||
setSaveMessage(
|
||||
"请先填写要推送 SKU 的样包测量数据和成本价,已录入的 SKU 不会重复推送",
|
||||
);
|
||||
setSaveMessageType("error");
|
||||
return;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user