Commit a73d2b93bef25ef4adbde7d3d9d7fc220d17daa5

Authored by by1642146903
2 parents c3dd38dd f9fa7e97

Merge remote-tracking branch 'origin/pms'

src/pages/pms/partPlan/PlanManage/subpages/Apply/components/PartModal.tsx
... ... @@ -13,12 +13,15 @@ interface Props {
13 13 parts: any[]
14 14 onOk: (parts: any[]) => any
15 15 setParams: Function
  16 + _supplierId: number | undefined
16 17 }
17 18 const {Option} = Select;
18   -export default function Index({ onCancel, visible, parts=[], onOk, setParams }: Props) {
  19 +export default function Index({ onCancel, visible, parts = [], onOk, setParams, _supplierId }: Props) {
19 20 const [selectedParts, setSelectedParts] = useState<any[]>([]);
20 21 const [dfParam, setDfParam] = useState<any>({keywords: ''});
21 22 const [partList, setPartList] = useState(parts);
  23 + const [info, setInfo] = useState<{open: boolean, partName: string, poolId?: number}>({open: false, partName: '', poolId: undefined});
  24 + const [partArr, setPartArr] = useState<any[]>([]);
22 25  
23 26 const shopNames = useMemo(() => {
24 27 return Array.from(new Set(parts.map(it => it.shopName || '').filter(it => !!it)));
... ... @@ -37,6 +40,7 @@ export default function Index({ onCancel, visible, parts=[], onOk, setParams }:
37 40 useEffect(() => {
38 41 if (!visible) {
39 42 setSelectedParts([]);
  43 + setPartArr([]);
40 44 setPartList(parts);
41 45 }
42 46 }, [visible, parts]);
... ... @@ -46,6 +50,14 @@ export default function Index({ onCancel, visible, parts=[], onOk, setParams }:
46 50 message.error("请选择配件");
47 51 return;
48 52 }
  53 + if (partArr.some(it => !!it.supplierId)) {
  54 + for (const item of partArr) {
  55 + if (!!item.supplierId && item.supplierId != _supplierId) {
  56 + setInfo({ open: true, partName: item.partName, poolId: item.poolId });
  57 + return;
  58 + }
  59 + }
  60 + }
49 61 onOk && onOk(selectedParts);
50 62 onCancel && onCancel();
51 63 }
... ... @@ -81,6 +93,7 @@ export default function Index({ onCancel, visible, parts=[], onOk, setParams }:
81 93 visible={visible}
82 94 title="配件采购明细"
83 95 onCancel={onCancel}
  96 + maskClosable={false}
84 97 footer={[
85 98 <Button key="cancel" onClick={onCancel}>取消</Button>,
86 99 <Button
... ... @@ -195,6 +208,7 @@ export default function Index({ onCancel, visible, parts=[], onOk, setParams }:
195 208 } else if (index > -1) {
196 209 newData.splice(index, 1);
197 210 }
  211 + setPartArr(newData);
198 212 setSelectedParts([...newData]);
199 213 },
200 214 onSelectAll: (selected, selectedRows, changeRows) => {
... ... @@ -206,6 +220,7 @@ export default function Index({ onCancel, visible, parts=[], onOk, setParams }:
206 220 } else {
207 221 newData = selectedParts.filter(row => !changedKeys.includes(`${row.poolId}`));
208 222 }
  223 + setPartArr(newData);
209 224 setSelectedParts(newData);
210 225 },
211 226 }}
... ... @@ -220,6 +235,25 @@ export default function Index({ onCancel, visible, parts=[], onOk, setParams }:
220 235 <Column title="配件来源类型" dataIndex="typeName" />
221 236 <Column title="上次采购供应商" dataIndex="supplierName" />
222 237 </Table>
  238 + <Modal
  239 + title="提示"
  240 + open={info.open}
  241 + maskClosable={false}
  242 + closable={false}
  243 + cancelText="重新选择"
  244 + okText="继续"
  245 + onCancel={() => {
  246 + setPartArr(partArr.filter((i => i.poolId != info.poolId)));
  247 + setSelectedParts(selectedParts.filter((i => i.poolId != info.poolId)));
  248 + setInfo({open: false, partName: '', poolId: undefined});
  249 + }}
  250 + onOk={() => {
  251 + setPartArr(partArr.filter((i => i.poolId != info.poolId)));
  252 + setInfo({ open: false, partName: '', poolId: undefined });
  253 + }}
  254 + >
  255 + <p style={{ color: 'red' }}><span style={{ color: '#333333', fontWeight: '500', marginRight: 3}}>【{info.partName}】</span>本次采购供应商和上次采购供应商不一致,是否继续?</p>
  256 + </Modal>
223 257 </Modal>
224 258 );
225 259 }
... ...
src/pages/pms/partPlan/PlanManage/subpages/Apply/index.tsx
... ... @@ -41,6 +41,7 @@ export default function Index() {
41 41 const partList = flattenDeep(dealerList.map(it => (it.suppliers || []).map((su: any) => (su.storages || []).map((st: any) => (st.parts || [])))));
42 42 const poolIds = partList.map((it: any) => it.poolId);
43 43 const [info, setInfo] = useState<{ remark?: string, fids?: any }>();
  44 + const [_supplierId, setSupplierId] = useState<number| undefined>(undefined);
44 45  
45 46 useEffect(() => {
46 47 if (planId?.planId) {
... ... @@ -254,7 +255,7 @@ export default function Index() {
254 255 <div key={`supplier${supplier.supplierId}`} style={{ marginTop: 10, marginLeft: 40 }}>
255 256 <div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center'}}>
256 257 <div style={{ fontWeight: "bold" }}>{`供应商: ${supplier.supplierName || ''}`}</div>
257   - <a style={{marginLeft: 20}} onClick={() => { setVisiblePart(true); setDealer({...dealer, ...supplier}); }}>
  258 + <a style={{ marginLeft: 20 }} onClick={() => { setVisiblePart(true); setDealer({ ...dealer, ...supplier }); setSupplierId(supplier.supplierId); }}>
258 259 添加采购配件
259 260 </a>
260 261 <Popconfirm
... ... @@ -322,6 +323,7 @@ export default function Index() {
322 323 parts={parts.filter(it => !poolIds.includes(it.poolId))}
323 324 onOk={onOk}
324 325 setParams={setParams}
  326 + _supplierId={_supplierId}
325 327 />
326 328 <PartDetailModal
327 329 visible={visiblePartDetail}
... ...
src/pages/pms/partPlan/PlanShipping/api.ts
... ... @@ -36,10 +36,91 @@ export interface Item {
36 36 otherRatio?: number; // 对方责任占比(几成)
37 37 againCnt?: number; // 补发数量
38 38 }
  39 +export interface Detail {
  40 + brandId?:number
  41 + // int64
  42 + // 品牌ID
  43 + // 510
  44 + brandName?:
  45 + string
  46 + // 品牌名称
  47 +// opal.prohaska
  48 +supplierId?:number
  49 +// int64
  50 +// 供应商id
  51 +// 950
  52 +partKind?:number
  53 +// int32
  54 +// 配件种类
  55 +// 863
  56 +supplierName?:
  57 +string
  58 +// 供应商名称
  59 +// opal.prohaska
  60 +shopId?:number
  61 +// int64
  62 +// 服务站id
  63 +// 705/
  64 +shopName?:
  65 +string
  66 +// 门店名称
  67 +// opal.prohaska
  68 +storageId?:number
  69 +// int64
  70 +// 库房id
  71 +// 563
  72 +storageName?:
  73 +string
  74 +// 库房名称
  75 +// opal.prohaska
  76 +groupId?:number
  77 +// int64
  78 +// 集团ID
  79 +// 33/
  80 +shippingNo?:
  81 +string
  82 +// 发运单号
  83 +// zt910g
  84 +shippingDate?:
  85 +string
  86 +// 发运日期?;
  87 +// 2023 - 05 - 23
  88 +totalAmount?:
  89 +number
  90 +// 总金额
  91 +// 904
  92 +payToken?:
  93 +string
  94 +// 待付token
  95 +// wywo3x
  96 +importUserName?:
  97 +string
  98 +// 导入人员
  99 +// opal.prohaska
  100 +inStorageUserName?:
  101 +string
  102 +// 入库人员
  103 +// opal.prohaska
  104 +status?:number
  105 +// enum
  106 + // 状态0待确认1待入库2已完成9作废(See: 配件发运单状态
  107 +// create at 2020-03 - 18)
  108 +
  109 +settleDealerId?:number
  110 +// int64
  111 +// 结算商家/Id
  112 +// 115
  113 +settleDealerName?:
  114 +string
  115 +// 结算商家名称
  116 + settleShopId?:number
  117 + settleShopName?:string
  118 + list?: DetailItem[]
  119 +}
39 120 /**
40 121 * 明细
41 122 */
42   -export interface Detail {
  123 +export interface DetailItem {
43 124 supplierName?: string; // 供应商名称
44 125 partId?: number; // 配件ID
45 126 partName?: string; // 配件名称
... ... @@ -68,8 +149,8 @@ export function getList(params?: Params): http.PromisePageResp&lt;Item&gt; {
68 149 /**
69 150 * 查询明细
70 151 */
71   -export function getDetail(shippingNo?: string): http.PromiseResp<Detail[]> {
72   - return request.get(`${PMS_HOST}/app/part/shipping/detail`, { params: {shippingNo} });
  152 +export function getDetail(shippingNo?: string): http.PromiseResp<Detail> {
  153 + return request.get(`${PMS_HOST}/app/part/shipping/part/detail`, { params: {shippingNo} });
73 154 }
74 155  
75 156 /**
... ...
src/pages/pms/partPlan/PlanShipping/components/ConfirmDetailModal.tsx
1 1 import React, { useState, useEffect } from 'react';
2   -import { Button, message, Modal, Table } from 'antd';
3   -import { confirmApi, getDetail, Detail, Item } from "../api";
  2 +import { Button, message, Modal, Table, Descriptions } from 'antd';
  3 +import { confirmApi, getDetail, Detail, Item, DetailItem } from "../api";
4 4 import useInitail from "@/hooks/useInitail";
5 5 import _ from "lodash";
6 6  
... ... @@ -16,7 +16,7 @@ const { Column } = Table;
16 16 export default function Index(props: Props) {
17 17 const { visible, onCancel, fetchList, item, confirm } = props;
18 18 const [delay, setDelay] = useState(true);
19   - const { data, setParams, loading: aloading} = useInitail<Detail[], string | undefined>(getDetail, [], item.shippingNo, delay);
  19 + const { data, setParams, loading: aloading} = useInitail<Detail, string | undefined>(getDetail, {}, item.shippingNo, delay);
20 20 const [loading, setLoading] = useState(false);
21 21  
22 22 useEffect(() => {
... ... @@ -54,13 +54,19 @@ export default function Index(props: Props) {
54 54 <Button key="2" type="primary" loading={loading} disabled={loading} onClick={() => submit(true)}>确认</Button>
55 55 ] : [<Button key="1" loading={loading} onClick={() => onCancel()}>取消</Button>]}
56 56 >
57   - <Table loading={aloading} rowKey={(v: Detail) => `${v.partId}`} scroll={{y: 500, x: 1200}} dataSource={data || []} pagination={false}>
  57 + <Descriptions column={3}>
  58 + <Descriptions.Item label="品牌">{data.brandName}</Descriptions.Item>
  59 + <Descriptions.Item label="供应商" span={2}>{data.supplierName}</Descriptions.Item>
  60 + <Descriptions.Item label="库房">{data.storageName}</Descriptions.Item>
  61 + <Descriptions.Item label="提报门店" span={2}>{data.settleShopName}</Descriptions.Item>
  62 + </Descriptions>
  63 + <Table loading={aloading} rowKey={(v: DetailItem) => `${v.partId}`} scroll={{y: 500, x: 1200}} dataSource={data.list || []} pagination={false}>
58 64 <Column title="配件名称" dataIndex="partName" />
59 65 <Column title="配件编码" dataIndex="partCode" />
60 66 <Column title="配件件号" dataIndex="partNo" />
61 67 <Column title="发运数量" dataIndex="partCount" />
62 68 <Column title="采购单价" dataIndex="price" />
63   - <Column title="总金额(元)" dataIndex="totalAmount" render={(t: number, _:Detail) => ((_.price || 0) * (_.partCount || 0) || '--')} />
  69 + <Column title="总金额(元)" dataIndex="totalAmount" render={(t: number, _: DetailItem) => ((_.price || 0) * (_.partCount || 0) || '--')} />
64 70 {!confirm && <Column title="入库数量" dataIndex="storageCnt" render={(t: number) => (t || '--')} />}
65 71 {!confirm && <Column title="遗漏数量" dataIndex="omitCnt" render={(t: number) => (t || '--')} />}
66 72 {!confirm && <Column title="破损数量" dataIndex="damagedCnt" render={(t: number) => (t || '--')} />}
... ...
src/pages/pms/partPlan/PlanShipping/components/UploadExcel.tsx
... ... @@ -107,7 +107,7 @@ export default function UploadExcel({ getList, importVisible, setImportVisible,
107 107 onChange={supplierId => setParam({ ...param, supplierId })}
108 108 />
109 109 <SelectRow
110   - title="库房"
  110 + title="发运库房"
111 111 value={param.storageId}
112 112 data={storages}
113 113 id="id"
... ... @@ -115,7 +115,7 @@ export default function UploadExcel({ getList, importVisible, setImportVisible,
115 115 onChange={storageId => setParam({ ...param, storageId })}
116 116 />
117 117 <SelectRow
118   - title="结算门店"
  118 + title="提报门店"
119 119 value={param.settleShopId}
120 120 data={shops}
121 121 id="id"
... ...
src/pages/pms/partPlan/PlanShipping/index.tsx
1 1 import React, { useState } from "react";
2   -import { Card, ConfigProvider, DatePicker, Divider, Table } from 'antd';
  2 +import { Card, ConfigProvider, DatePicker, Divider, Table, Dropdown, Menu } from 'antd';
  3 +import { DownOutlined } from '@ant-design/icons';
3 4 import { PageHeaderWrapper } from '@ant-design/pro-layout';
4 5 import usePagination from "@/hooks/usePagination";
5 6 import DetailModal from './components/ConfirmDetailModal';
... ... @@ -23,6 +24,23 @@ export default function PartPriceCoefficient() {
23 24 const [item, setItem] = useState<Item>({});
24 25 const { data: shops } = useInitial<PmsStoragePartShop.Option[], {}>(api.getShopApi, [], {});
25 26  
  27 + const menu = (
  28 + <Menu
  29 + items={
  30 + [
  31 + {
  32 + label: <a href="/api/pms/erp/part/template/shipping">通用模板</a>,
  33 + key: '0',
  34 + },
  35 + {
  36 + label: <a href="/api/pms/erp/part/template/shipping/ca">长安模板</a>,
  37 + key: '1',
  38 + },
  39 + ]
  40 + }
  41 + />
  42 +);
  43 +
26 44 return (
27 45 <PageHeaderWrapper title="发运单">
28 46 <ConfigProvider locale={zhCN}>
... ... @@ -56,13 +74,10 @@ export default function PartPriceCoefficient() {
56 74 />
57 75 </div>
58 76 <div style={{ display: 'flex', flexDirection: 'row'}}>
59   - <a
60   - href={`/api/pms/erp/part/template/shipping?t=${moment().valueOf()}`}
61   - style={{ marginRight: 20 }}
62   - >
63   - 下载模板
64   - </a>
65   - <a onClick={() => { setImportVisible(true); }}>导入数据</a>
  77 + <Dropdown overlay={menu} trigger={['click']} placement="bottomLeft" arrow overlayStyle={{width: 120}}>
  78 + <a style={{display: 'flex', alignItems: 'center'}}>导入模板<DownOutlined style={{fontSize: 14, marginLeft: 3}} /></a>
  79 + </Dropdown>
  80 + <div style={{marginLeft: 20}}><a onClick={() => { setImportVisible(true); }}>导入数据</a></div>
66 81 </div>
67 82 </div>
68 83 <Table
... ...