AddPurchaseModal.tsx 15.4 KB
import React, { useEffect, useState } from 'react';
import { Modal, Select, Button, Table, Form, message, Tabs, Input } from 'antd';
import ChoosePartModal from './ChoosePartModal';
import usePagination from '@/hooks/usePagination';
import { getStoragePage } from '@/pages/pms/storage/StorageManage/api';
import { getPageListApi, Item as item } from "@/pages/pms/partPlan/PlanSupplier/api";
import {getPurchasePool, Item as poolitem} from '@/pages/pms/purchase/PurchasePool/api';
import PartModal from '@/pages/pms/purchase/PurchasePool/comonents/PartModal';
import {purchaseApply, getrelationlist, EditItem} from '../api';
import {getList, ListVO, Params} from '@/pages/pms/partPlan/PlanPool/api';
import _ from 'lodash';
import useInitial from '@/hooks/useInitail';
import PmsSelect from '@/pages/pms/comonents/PmsSelect';
import { getPartTypeApi } from '@/pages/pms/part/Repertory/api';
import {planPoolTypeData} from '@/pages/pms/entity';

const Option = Select.Option;
const {Item} = Form;
const {Column} = Table;
const {TabPane} = Tabs;
interface Props {
  onCancel: () => any,
  visible: boolean,
  itemData?:EditItem,
  setItemData?:Function
}
interface Relation{
  value: number,
  name: string
}

export default function PartStorageModal({ onCancel, visible, itemData, setItemData }: Props) {
  const { list: storages } = usePagination<PartStorageSpace.PageVO>(getStoragePage, { pageSize: 1000 });
  const { list: suppliers } = usePagination<item>(getPageListApi, { supplierType: 40, pageSize: 500 });
  const [delay, setDelay] = useState(true);
  const {data: planeData, setParams, setData: setPlaneData} = useInitial<ListVO[], Params>(getList, [], {}, delay);
  const {data: casData, setParams: casSetParams, setData: casSetData} = useInitial<poolitem[], Params>(getPurchasePool, [], {}, delay);
  const [planePart, setPlanePart] = useState<ListVO[]>([]);
  const { data: partTypeData } = useInitial(getPartTypeApi, [], {});

  const [choosePartVisable, setChoosePartVisable] = useState(false);
  const [selectedParts, setSelectedParts] = useState<any[]>([]);
  const [form] = Form.useForm();
  const [btnloading, setBtnloading] = useState(false);
  const [storageid, setStorageid] = useState<number>();
  const [partParams, setPartParams] = useState<{stId?:number, spId?: number}>();
  const [casPart, setCasPart] = useState<poolitem[]>();
  const [listRelation, setListRelation] = useState<Relation[]>();
  const [partvisible, setPartvisible] = useState(false);
  const [item, setItem] = useState();
  const [settlementMethod, setSettlementMethod] = useState<number>();
  
  // 编辑时数据回显
  useEffect(() => {
    if (itemData?.storageId) {
      form.setFieldsValue({
        storageId: itemData.storageId, 
        supplierId: itemData.supplierId,
        settlementMethod: itemData.payType,
        proportion: itemData.proportion,
        isOutSide: itemData.isOutSide ? "1" : "0"
      });
      getrelationlist({tradeCompanyId: itemData.supplierId, compCategory: 1, dealerId: storages.find(i => i.id == itemData.storageId)?.dealerId}).then(res => {
        if (res.success) {
          setListRelation(res.data && res.data[0].settleMethodList);
          form.setFieldsValue({accountCheckPeriod: res.data && res.data[0].accountCheckPeriod});
          }
      }).catch(e => message.error(e.message));
      setPartParams({stId: itemData.storageId, spId: itemData.supplierId});
      setStorageid(itemData.storageId);
      setSelectedParts(itemData.parts || []);
      setCasPart(itemData.poolParts);
      setPlanePart(itemData.planParts || []);
      return;
    }
    if (!visible) {
      form.resetFields();
      setStorageid(undefined);
      setPlaneData([]);
      casSetData([]);
      setSelectedParts([]);
      setCasPart([]);
      setPlanePart([]);
      setListRelation([]);
    }
  }, [visible]);

  //查询计划池配件和工单缺件配件
  useEffect(() => {
    if (storageid) {
      setDelay(false);
      setParams({}, true);
      casSetParams({storageId: storageid}, true);
    }
  }, [storageid]);

  // 提交申请
  function handSave() {
    form.validateFields().then(fields => {
      const supplier = suppliers.find(it => it.supplierId == fields.supplierId) || {};
      const storage = storages.find(it => it.id == fields.storageId) || {};
      const params = {
        storageId: storage.id, 
        storageName: storage.storageName,
        supplierId: supplier.supplierId,
        supplierName: supplier.supplierName,
        proportion: fields.proportion,
        payType: fields.settlementMethod,
        accountCheckPeriod: settlementMethod == 2 ? fields.accountCheckPeriod : undefined,
        parts: [...selectedParts.map(i => ({partId: i.partId, partCnt: i.partCnt, price: i.price, type: 1})),
          ...planePart.map(i => ({poolId: i.poolId, partId: i.partId, partCnt: i.cnt, price: i.price, type: 2})),
          ...(casPart?.map(i => (i.details?.map(it => ({partId: it.partId, partCnt: it.partCnt, poolId: it.poolId, expectInTime: it.expectInTime, price: it.price, type: 3})))).flat() || [])
        ],
        isOutSide: !!fields.isOutSide
      };
      setBtnloading(true);
      purchaseApply(params).then(res => {
        message.success("提交成功");
        setBtnloading(false);
        setItemData && setItemData();
        onCancel && onCancel();
        setPartParams({});
      }).catch(e => {
        message.error(e.message);
        setBtnloading(false);
      });
    });
  }
  
  return (
    <Modal
      width={1000}
      visible={visible}
      onCancel={() => { onCancel(); setPartParams({}); }}
      maskClosable={false}
      title="新增配件外采申请"
      footer={[
        <Button key="cancel" onClick={() => { onCancel(); setPartParams({}); }} loading={btnloading}>取消</Button>,
        <Button
          key="submit"
          onClick={handSave}
          type="primary"
          htmlType="submit"
          loading={btnloading}
          disabled={!selectedParts.length && !casPart?.length && !planePart.length}
        >
          提交申请
        </Button>
      ]}
    >
      <Form
        form={form}
        labelCol={{span: 4}}
        wrapperCol={{span: 19}}
      >
        <Item label="库房" name="storageId" required rules={[{ required: true, message: '请选择库房' }]}>
          <Select
            style={{ width: 250 }}
            placeholder="请选择库房"
            value={storageid}
            onChange={v => { 
              setStorageid(v);
              form.setFieldsValue({supplierId: '', settlementMethod: undefined, proportion: undefined});
              setListRelation([]);
              setSettlementMethod(undefined);
            }}
            showSearch
            optionFilterProp="children"
          >
            {storages.map((item) => (
              <Option value={item.id} key={item.id}>{item.storageName}</Option>
          ))}
          </Select>
        </Item>
        <Item label="供应商" name="supplierId" required rules={[{ required: true, message: '请选择供应商' }]}>
          <Select
            style={{ width: 250 }}
            placeholder="请选择供应商"
            showSearch
            optionFilterProp="children"
            options={suppliers.filter((item, index, self) => {
              return self.findIndex(el => el.supplierId == item.supplierId) === index;
            }).map((item) => ({ value: item.supplierId, label: item.supplierName }))} 
            onChange={v => {
              setPartParams({stId: storageid, spId: v});
              setListRelation([]);
              form.setFieldsValue({settlementMethod: undefined, proportion: undefined});
              setSettlementMethod(undefined);
              getrelationlist({tradeCompanyId: v, compCategory: 1, dealerId: storages.find(i => i.id == storageid)?.dealerId}).then(res => {
                if (res.data?.length) {
                  form.setFieldsValue({ proportion: res.data[0].billAmountRatio, accountCheckPeriod: res.data && res.data[0].accountCheckPeriod});
                  setListRelation(res.data && res.data[0].settleMethodList);
                }
              }).catch(e => message.error(e.message));
            }}
          />
        </Item>
        <Item label="结算方式" name="settlementMethod" required rules={[{ required: true, message: '请选择结算方式' }]}>
          <Select
            style={{ width: 250 }}
            placeholder="请选择结算方式"
            value={settlementMethod}
            showSearch
            optionFilterProp="children"
            onChange={setSettlementMethod}
            onFocus={() => { 
              if (!form.getFieldValue("supplierId")) {
                message.error("请先选择供应商");
                return;
              }
              if (!listRelation?.length) { 
                message.error(`请财务先配置${suppliers.find(i => i.supplierId == form.getFieldValue('supplierId'))?.supplierName}的结算方式`); 
              }
            }}
          >
            {listRelation?.map(i => <Option value={i.value} key={i.value}>{i.name}</Option>)}
          </Select>
        </Item>
        {!!settlementMethod && settlementMethod == 2 && (
        <Item label="对账周期" name="accountCheckPeriod">
          <Input
            style={{ width: 250 }}
            addonAfter="日"
            addonBefore="下月"
            disabled
          />
        </Item>
        )}
        <Item label="发票金额要求比例" name="proportion">
          <Input style={{ width: 250 }} disabled addonAfter="%" />
        </Item>
        <Item label="是否推送外勤资格" name="isOutSide">
          <Select
            style={{ width: 250 }}
            defaultValue="0"
          >
            <Option value="1" key="1">是</Option>
            <Option value="0" key="0">否</Option>
          </Select>
        </Item>
      </Form>
      <Tabs animated>
        <TabPane tab="配件" key="1">
          <div style={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center', marginBottom: 10}}>
            <Button type="primary" onClick={() => setChoosePartVisable(true)} disabled={!partParams?.spId || !partParams.stId}>选择配件</Button>
          </div>
          <Table
            style={{width: '100%'}}
            dataSource={selectedParts}
            pagination={false}
            scroll={{y: 300}}
            rowKey={r => `${r.partCode}`}
          >
            <Column title="配件名称" dataIndex="partName" />
            <Column title="配件编码" dataIndex="partCode" />
            <Column title="采购数量" dataIndex="partCnt" />
            <Column title="单价" dataIndex="price" />
            <Column title="总价" render={r => _.ceil((r.partCnt * r.price), 2)} />
            <Column
              title="操作"
              render={(_item: any) => (
                <a onClick={() => setSelectedParts(selectedParts.filter(i => i.partCode != _item.partCode))}>
                  删除
                </a>
          )}
            />
          </Table>
        </TabPane>
        <TabPane tab="计划待外采配件" key="3">
          <div style={{display: 'flex', marginBottom: 10}}>
            <Input.Search
              allowClear
              enterButton
              placeholder="请输入配件名称/编码"
              onSearch={e => setParams({keywords: e}, true)}
              style={{ width: 220 }}
            />
            <PmsSelect
              allowClear
              style={{ width: 180, marginRight: 10, marginLeft: 10}}
              onChange={v => {
                setParams({poolType: v}, true);
              }}
              placeholder="请选择来源类型"
              options={planPoolTypeData.map(i => ({value: i.value, label: i.label}))}
            />
            <PmsSelect
              allowClear
              style={{ width: 180}}
              onChange={v => setParams({partType: v}, true)}
              placeholder="请选择配件类型"
              options={partTypeData.map(i => ({value: i.value, label: i.label}))}
            />
            <PmsSelect
              allowClear
              style={{ width: 180, marginLeft: 10}}
              onChange={v => setParams({storageId: v}, true)}
              placeholder="请选择库房"
              options={storages.map(i => ({value: i.id, label: i.storageName}))}
            />
          </div>
          <Table
            style={{width: '100%'}}
            dataSource={planeData}
            pagination={false}
            scroll={{y: 300}}
            rowKey="poolId"
            rowSelection={{
            type: "checkbox",
            onChange: (selectedRowKeys: any, selectedRows) => {
              setPlanePart(selectedRows);
            },
            selectedRowKeys: [...(planePart?.map(i => i.poolId) || [])]
          }}
          >
            <Column title="配件名称" dataIndex="partName" />
            <Column title="配件编码" dataIndex="partCode" />
            <Column title="数据来源" dataIndex="typeName" />
            <Column title="配件类型" dataIndex="partTypeName" />
            <Column title="采购单价(元)" dataIndex="price" />
            <Column title="采购数量" dataIndex="cnt" />
            <Column title="库房" dataIndex="storageName" />
            <Column title="总价(元)" render={r => _.ceil((r.cnt * r.price), 2)} />
          </Table>
        </TabPane>
        <TabPane tab="工单缺件配件" key="2">
          <div style={{display: 'flex', marginBottom: 10}}>
            <Input.Search
              allowClear
              enterButton
              placeholder="请输入VIN/工单号"
              onSearch={e => casSetParams({keywords: e}, true)}
              style={{ width: 220 }}
            />
          </div>
          <Table
            style={{width: '100%'}}
            dataSource={casData}
            pagination={false}
            scroll={{y: 300}}
            rowKey="name"
            rowSelection={{
            type: "checkbox",
            onChange: (selectedRowKeys: any, selectedRows) => {
              setCasPart(selectedRows);
            },
            selectedRowKeys: [...(casPart?.map(i => i.name) || [])]
          }}
          > 
            <Column title="工单号" dataIndex="name" />
            <Column title="VIN" dataIndex="id" />
            <Column title="车牌号" dataIndex="plateNo" />
            <Column title="缺件外采品种" render={(r) => <a onClick={() => { setPartvisible(true); setItem(r.details); }}>{r.kind}</a>} />
          </Table>
        </TabPane>
      </Tabs>
      <div style={{display: 'flex', justifyContent: 'flex-end', marginTop: 20, marginBottom: 20}}>
        <span>合计金额:{
        ((selectedParts.reduce((sum, i) => (sum + _.ceil(Number(i.partCnt * i.price), 2)), 0)) +
        casPart?.map(i => i.details).flat().reduce((sum, item) => (sum + (item?.amount || 0)), 0) + 
        planePart.reduce((sum, it) => (sum + _.ceil(Number((it.price || 0) * (it.cnt || 0)), 2)), 0)).toFixed(2)
        }

        </span>
      </div>
      <ChoosePartModal
        partParams={partParams}
        visible={choosePartVisable}
        onCancel={() => setChoosePartVisable(false)}
        onOk={(part) => { 
          const findPart = selectedParts.find(it => it.partId == part.partId);
          if (JSON.stringify(findPart) != undefined) {
            setSelectedParts([...selectedParts.filter(it => it.partId != part.partId), {...part}]);
          } else {
            setSelectedParts([...selectedParts, part]);
          }
        }}
      />
      <PartModal visible={partvisible} item={item} onCancel={() => setPartvisible(false)} />
    </Modal>
  );
}