Commit d2960ac7 authored by 武广's avatar 武广

feat: 添加库存审核提交功能

parent f0aca99e
...@@ -2,7 +2,7 @@ const isProduction = process.env.NODE_ENV === 'production'; ...@@ -2,7 +2,7 @@ const isProduction = process.env.NODE_ENV === 'production';
const isPre = process.env.PRE_ENV === 'pre'; const isPre = process.env.PRE_ENV === 'pre';
const envAPi = { const envAPi = {
api: '//backstms-yxm.liangkebang.net', api: 'https://backstms-yxm.liangkebang.net',
kdspOpApi: 'https://kdsp-operation-yxm.liangkebang.net', kdspOpApi: 'https://kdsp-operation-yxm.liangkebang.net',
kdspApi: 'https://sc-op-api-yxm.liangkebang.net', kdspApi: 'https://sc-op-api-yxm.liangkebang.net',
goodsApi: 'https://sc-op-api-yxm.liangkebang.net', goodsApi: 'https://sc-op-api-yxm.liangkebang.net',
......
...@@ -5,15 +5,19 @@ import { ...@@ -5,15 +5,19 @@ import {
Select, Select,
notification, notification,
Upload, Upload,
Tag,
Cascader, Cascader,
InputNumber, InputNumber,
Popover, Popover,
Divider, Divider,
} from 'antd'; } from 'antd';
import React, { Component } from 'react'; import React, { Component, useState } from 'react';
import { connect } from 'dva'; import { connect } from 'dva';
import { saveAs } from 'file-saver';
import { format } from 'date-fns';
import styles from '../style.less'; import styles from '../style.less';
import { stateList } from '../staticdata'; import { stateList } from '../staticdata';
import { apiGoodsInfosExport } from '../service';
const FormItem = Form.Item; const FormItem = Form.Item;
const { Option } = Select; const { Option } = Select;
...@@ -23,6 +27,10 @@ const { Option } = Select; ...@@ -23,6 +27,10 @@ const { Option } = Select;
class goodsManage extends Component { class goodsManage extends Component {
formRef = React.createRef(); formRef = React.createRef();
state = {
loading: false,
};
componentDidMount() { componentDidMount() {
this.props.onRef(this); this.props.onRef(this);
this.handleSearch(); this.handleSearch();
...@@ -59,6 +67,33 @@ class goodsManage extends Component { ...@@ -59,6 +67,33 @@ class goodsManage extends Component {
this.props.setArea(isAll, type); this.props.setArea(isAll, type);
}; };
// 验证是否可以修改库存
checkEnableUpdateStock = () => {
if (this.props.selectNum) {
this.props.checkStock();
} else {
notification.info({ message: '请选择' });
}
};
// 导出明细
onExportGoodsInfo = async () => {
this.setState({
loading: true,
});
const form = this.formRef?.current?.getFieldValue();
const res = await apiGoodsInfosExport(form);
this.setState({
loading: false,
});
if (res) {
const blob = new Blob([res]);
saveAs(blob, `商品明细-${format(new Date(), 'yyyyMMdd')}.xlsx`);
} else {
notification.error({ message: '下载失败' });
}
};
render() { render() {
const { treeData } = this.props; const { treeData } = this.props;
const selectW = { width: 250 }; const selectW = { width: 250 };
...@@ -81,6 +116,10 @@ class goodsManage extends Component { ...@@ -81,6 +116,10 @@ class goodsManage extends Component {
<Button style={{ border: 'none' }} onClick={() => this.setArea(0, 'after')}> <Button style={{ border: 'none' }} onClick={() => this.setArea(0, 'after')}>
勾选商品售后地址设置 勾选商品售后地址设置
</Button> </Button>
<br />
<Button style={{ border: 'none' }} onClick={() => this.checkEnableUpdateStock()}>
勾选商品库存修改
</Button>
</div> </div>
); );
// const uploadProps = { // const uploadProps = {
...@@ -166,16 +205,21 @@ class goodsManage extends Component { ...@@ -166,16 +205,21 @@ class goodsManage extends Component {
<Button onClick={() => this.onReset()} type="primary" className={styles.button}> <Button onClick={() => this.onReset()} type="primary" className={styles.button}>
重置 重置
</Button> </Button>
<Button
loading={this.state.loading}
onClick={() => this.onExportGoodsInfo()}
className={styles.button}
>
导出
</Button>
</FormItem> </FormItem>
<FormItem style={{ float: 'right' }}> <FormItem style={{ float: 'right' }}>
<Popover content={content} onVisibleChange={this.handleVisibleChange}> <Popover content={content} onVisibleChange={this.handleVisibleChange}>
<Button type="primary" className={styles.button}> <Button type="primary" className={styles.button}>
批量操作 批量设置
</Button> </Button>
</Popover> </Popover>
<Button type="primary" className={styles.button} onClick={this.addSpu}> {this.props.selectNum > 0 && <Tag color="green">已选商品 {this.props.selectNum}</Tag>}
新增商品
</Button>
{/* <Button {/* <Button
className={styles.button} className={styles.button}
type="primary" type="primary"
......
...@@ -2,21 +2,24 @@ import { Form } from '@ant-design/compatible'; ...@@ -2,21 +2,24 @@ import { Form } from '@ant-design/compatible';
import '@ant-design/compatible/assets/index.css'; import '@ant-design/compatible/assets/index.css';
import { Modal, InputNumber, notification, Input, Radio } from 'antd'; import { Modal, InputNumber, notification, Input, Radio } from 'antd';
import React from 'react'; import React from 'react';
import { updateStock } from '../service'; import { apiCreateGoodsLog } from '../service';
import styles from '../style.less';
const UpdateStock = props => { const UpdateStock = props => {
const { getFieldDecorator, validateFields, resetFields, getFieldValue } = props.form; const { getFieldDecorator, validateFields, resetFields, getFieldValue } = props.form;
const valueInfo = props.info; const valueInfo = props.info;
getFieldDecorator('stockChangeType', { initialValue: 1 }); getFieldDecorator('changeType', { initialValue: 1 });
const submit = async () => { const submit = async () => {
validateFields(async (err, { stock, changeReason, stockChangeType }) => { validateFields(async (err, { stock, changeReason, changeType }) => {
if (err) return; if (err) return;
const error = await updateStock({ const error = await apiCreateGoodsLog({
stock, afterChange: stock,
id: valueInfo.id, // id: valueInfo.id,
supplierId: valueInfo.supplierId, supplierId: valueInfo.supplierId,
stockChangeType, productIdType: 2,
changeType,
changeReason, changeReason,
productIds: valueInfo.id ? [valueInfo.id] : props.skuIds,
}); });
if (!error) { if (!error) {
notification.success({ message: '操作成功!' }); notification.success({ message: '操作成功!' });
...@@ -31,7 +34,7 @@ const UpdateStock = props => { ...@@ -31,7 +34,7 @@ const UpdateStock = props => {
}; };
const formItemLayout = { const formItemLayout = {
labelCol: { labelCol: {
span: 8, span: 6,
}, },
wrapperCol: { wrapperCol: {
span: 16, span: 16,
...@@ -40,23 +43,25 @@ const UpdateStock = props => { ...@@ -40,23 +43,25 @@ const UpdateStock = props => {
const validatorCallback = (rule, value, callback) => { const validatorCallback = (rule, value, callback) => {
// 减库存存时,校验可售库存-输入值>=0,即可售库存不可为负; // 减库存存时,校验可售库存-输入值>=0,即可售库存不可为负;
const stockChangeType = getFieldValue('stockChangeType'); const changeType = getFieldValue('changeType');
const increment = valueInfo.marketableStock - value; const increment = valueInfo.marketableStock - value;
return !stockChangeType && increment < 0 ? callback(new Error(rule.message)) : callback(); return +changeType === 29 && increment < 0 ? callback(new Error(rule.message)) : callback();
}; };
return ( return (
<Modal title="修改库存" visible={props.visible} onCancel={onCancel} onOk={submit} width={400}> <Modal title="修改库存" visible={props.visible} onCancel={onCancel} onOk={submit} width={500}>
<Form {...formItemLayout}> <Form {...formItemLayout}>
<Form.Item label="变更类型:"> <Form.Item label="变更类型:">
{getFieldDecorator('stockChangeType', { {getFieldDecorator('changeType', {
rules: [{ required: true, message: '请选择类型!' }], rules: [{ required: true, message: '请选择类型!' }],
})( })(
<Radio.Group> <Radio.Group>
<Radio value={1}>增库存</Radio> <Radio value={28}>增库存</Radio>
<Radio value={0}>减库存</Radio> <Radio value={29}>减库存</Radio>
<Radio value={30}>使用新值</Radio>
</Radio.Group>, </Radio.Group>,
)} )}
<div className={styles.stockTip}>库存变更审批通过后生效</div>
</Form.Item> </Form.Item>
<Form.Item label="库存数:"> <Form.Item label="库存数:">
{getFieldDecorator('stock', { {getFieldDecorator('stock', {
...@@ -73,6 +78,7 @@ const UpdateStock = props => { ...@@ -73,6 +78,7 @@ const UpdateStock = props => {
initialValue: valueInfo.changeReason, initialValue: valueInfo.changeReason,
})(<Input.TextArea />)} })(<Input.TextArea />)}
</Form.Item> </Form.Item>
{valueInfo.state === 4 && <div className={styles.stockErrMsg}>审核中</div>}
</Form> </Form>
</Modal> </Modal>
); );
......
import { Form } from '@ant-design/compatible'; import { Form } from '@ant-design/compatible';
import '@ant-design/compatible/assets/index.css'; import '@ant-design/compatible/assets/index.css';
import { Card, Pagination, Table, notification, Drawer, Spin } from 'antd'; import { Card, Pagination, Table, notification, Drawer, Spin, Button } from 'antd';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { PageHeaderWrapper } from '@ant-design/pro-layout'; import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { connect } from 'dva'; import { connect } from 'dva';
...@@ -18,6 +18,7 @@ import { ...@@ -18,6 +18,7 @@ import {
getTemplateList, getTemplateList,
specList, specList,
queryAllAfterAddress, queryAllAfterAddress,
apiEnableUpdataStock,
} from './service'; } from './service';
import LogModal from './LogModal'; import LogModal from './LogModal';
import CreateModal from './createModal'; import CreateModal from './createModal';
...@@ -218,6 +219,29 @@ class goodsManage extends Component { ...@@ -218,6 +219,29 @@ class goodsManage extends Component {
filterShopList = (list = [], isEdit) => filterShopList = (list = [], isEdit) =>
list.filter(item => isEdit || !JDSHOPID.includes(item.id)); list.filter(item => isEdit || !JDSHOPID.includes(item.id));
// 验证是否可以修改库存
checkEnableUpdateStock = async (row = {}) => {
let ids = '';
if (row && row.skuId) {
ids = row.skuId;
} else {
ids = this.state.selectedRowKeys.join(',');
}
if (ids) {
const res = await apiEnableUpdataStock(ids);
if (res.data) {
if (res.data.allResult || res.data.successSkuIds?.length) {
this.openModal(row, 1);
} else {
const message = res.data.failedInfoList[0]?.message || '未存在可修改库存的商品';
notification.info({ message });
}
}
} else {
notification.info({ message: '请选择' });
}
};
openModal = ( openModal = (
{ {
skuId, skuId,
...@@ -228,6 +252,7 @@ class goodsManage extends Component { ...@@ -228,6 +252,7 @@ class goodsManage extends Component {
supplierId, supplierId,
stock, stock,
productStock, productStock,
state,
}, },
isStock, isStock,
) => { ) => {
...@@ -246,6 +271,7 @@ class goodsManage extends Component { ...@@ -246,6 +271,7 @@ class goodsManage extends Component {
marketPrice, marketPrice,
salePrice, salePrice,
supplierId, supplierId,
state,
}, },
}); });
}; };
...@@ -302,6 +328,13 @@ class goodsManage extends Component { ...@@ -302,6 +328,13 @@ class goodsManage extends Component {
return ( return (
<PageHeaderWrapper> <PageHeaderWrapper>
<Spin spinning={this.state.createloading}> <Spin spinning={this.state.createloading}>
<Button
type="primary"
className={styles.button}
onClick={() => this.setState({ createVisible: true, initData: {} })}
>
新增商品
</Button>
<Card> <Card>
<SearchForm <SearchForm
handleSearch={this.handleSearch} handleSearch={this.handleSearch}
...@@ -312,7 +345,9 @@ class goodsManage extends Component { ...@@ -312,7 +345,9 @@ class goodsManage extends Component {
}} }}
treeData={this.state.treeData} treeData={this.state.treeData}
shopList={this.shopList} shopList={this.shopList}
addSpu={() => this.setState({ createVisible: true, initData: {} })} checkStock={this.checkEnableUpdateStock}
// addSpu={() => this.setState({ createVisible: true, initData: {} })}
selectNum={selectedRowKeys.length}
setArea={(isALL, type) => this.setArea(isALL, type)} setArea={(isALL, type) => this.setArea(isALL, type)}
/> />
</Card> </Card>
...@@ -383,6 +418,7 @@ class goodsManage extends Component { ...@@ -383,6 +418,7 @@ class goodsManage extends Component {
<UpdateStock <UpdateStock
visible={this.state.updateStockVisible} visible={this.state.updateStockVisible}
skuIds={this.state.selectedRowKeys}
info={this.state.priceInfo} info={this.state.priceInfo}
onCancel={this.cancel} onCancel={this.cancel}
/> />
......
...@@ -197,3 +197,44 @@ export async function getAfterAddress(params) { ...@@ -197,3 +197,44 @@ export async function getAfterAddress(params) {
}); });
return data; return data;
} }
/**
* 商品是否可以做库存变更
* skuIds: 多个用英文逗号隔开
*/
export const apiEnableUpdataStock = skuIds =>
request.get(`/api/kdsp/sku/can/stockChange?skuIds=${skuIds}`, {
prefix: goodsApi,
});
// 商品明细导出
export const apiGoodsInfosExport = params =>
request.post('/api/kdsp/sku/export', {
prefix: goodsApi,
data: params,
responseType: 'arrayBuffer',
headers: {
'Content-Type': 'application/json;charset=UTF-8',
},
});
// 新建商品审核记录
export const apiCreateGoodsLog = params =>
request.post('/api/kdsp/product/audit/create', {
data: params,
prefix: goodsApi,
});
// 查询库存变更记录(未审核状态)
export const apiStockChangeLog = params =>
request.post('/product/change/audit/stockChange/page', {
data: params,
prefix: goodsApi,
});
// 审核商品变更记录
export const apiCheckStockChangeLog = params =>
request.post('/product/change/audit/audit', {
data: params,
prefix: goodsApi,
});
...@@ -107,13 +107,16 @@ export function column() { ...@@ -107,13 +107,16 @@ export function column() {
align: 'center', align: 'center',
sorter: (a, b) => a.stock - b.stock, sorter: (a, b) => a.stock - b.stock,
render: (_, row) => { render: (_, row) => {
// const stockView = // const stockView = row.productStock;
// row.state !== 4 ? ( const stockView = (
// <a onClick={() => this.openModal(row, 'productStock')}>{row.productStock}</a> <Button
// ) : ( type="link"
// <span>{row.productStock}</span> onClick={() => this.checkEnableUpdateStock(row)}
// ); style={{ padding: 0 }}
const stockView = row.productStock; >
{row.productStock}
</Button>
);
return ( return (
<> <>
<p>当前库存:{stockView}</p> <p>当前库存:{stockView}</p>
......
...@@ -99,3 +99,14 @@ ...@@ -99,3 +99,14 @@
.sizeTitle { .sizeTitle {
font-size: 12px; font-size: 12px;
} }
.stockTip {
color: #999;
line-height: 1;
}
.stockErrMsg {
box-sizing: border-box;
padding-left: 25%;
color: #d9363e;
line-height: 1;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment