Commit eb65aee0 by peii

直销开票申请及汇总

(cherry picked from commit 4231d95c)
parent 760913d5
......@@ -39,6 +39,7 @@ import DistributeInvoiceApplyDetail from '../src/pages/invoice/distribution/deta
// 直销开票
import DirectionInvoice from '../src/pages/invoice/direct';
import DirectionInvoiceCollections from '../src/pages/invoice/direct/collections';
import DirectionInvoiceApplyDetail from '../src/pages/invoice/direct/detail';
......@@ -72,6 +73,7 @@ const Router = createAppContainer(createStackNavigator({
DistributeInvoice: {screen: DistributeInvoice},
DistributeInvoiceApplyDetail: {screen: DistributeInvoiceApplyDetail},
DirectionInvoice: {screen: DirectionInvoice},
DirectionInvoiceCollections: {screen: DirectionInvoiceCollections},
DirectionInvoiceApplyDetail: {screen: DirectionInvoiceApplyDetail},
}, {
navigationOptions: {
......
......@@ -2,13 +2,13 @@
* @FilePath: /BoneHouse_Business_APP/app/action/SettlementAction.js
* @Author: peii
* @Date: 2021-12-21 16:30:41
* @LastEditTime: 2021-12-21 16:58:42
* @LastEditTime: 2022-01-05 15:35:27
* @LastEditors: peii
* @Vision: 1.0
* @Description: 结算模块 action
*/
import { SET_SETTLEMENT_STATUS } from '../base/ActionTypes'
import { SET_SETTLEMENT_STATUS, SET_INVOICE_STATUS } from '../base/ActionTypes'
import * as R from 'ramda'
import { GetRequest } from '../network/RequestUtils'
import { getUrlParams } from '../utils/Utils'
......@@ -24,6 +24,17 @@ const settlementStatus = [
{ value_code: 'SUBMITTED', value_name: '已提交' },
]
const invoiceStatus = [
{ value_code: 'ENTERED', value_name: '未申请' },
{ value_code: 'INVOICING', value_name: '开票中' },
{ value_code: 'INVOICED', value_name: '开票完成' },
]
/**
* @description: 请求结算状态
* @param {*}
* @return {*}
*/
export const getSettlementStatus = () => {
return (dispatch, getState) => {
let { global_domain_config, token } = getState().login
......@@ -44,3 +55,24 @@ export function setSettlementStatus(valueSets) {
values: valueSets,
}
}
export const getInvoiceStatus = () => {
return (dispatch, getState) => {
let { global_domain_config, token } = getState().login
const params = {
access_token: token,
value_set_code: 'SUR_CONSUME_INVOICE_HEADER_STATUS',
}
GetRequest(global_domain_config, getUrlParams('/system/value_set/search', params)).then(res => {
const values = R.pathOr(invoiceStatus, ['data', 'sys_values'])(res)
return dispatch(setInvoiceStatus(values))
})
}
}
export function setInvoiceStatus(values) {
return {
type: SET_INVOICE_STATUS,
values,
}
}
/*
* @FilePath: /BoneHouse_Business_APP/app/base/ActionTypes.js
* @Author: peii
* @Date: 2022-01-04 10:18:02
* @LastEditTime: 2022-01-05 14:52:02
* @LastEditors: peii
* @Vision: 1.0
* @Description:
*/
//-----------user---------------------------
export const LOGIN_NO = "LOGIN_NO"
export const LOGIN_DOING = "LOGIN_DOING"
......@@ -70,3 +79,4 @@ export const DEVICE_INFORMATION_UPDATE_FAILURE = "DEVICE_INFORMATION_UPDATE_FAIL
//-----------settlement information---------------------
export const SET_SETTLEMENT_STATUS = 'SET_SETTLEMENT_STATUS'
export const SET_INVOICE_STATUS = 'SET_INVOICE_STATUS'
\ No newline at end of file
......@@ -14,7 +14,7 @@ import {
font_family_regular,
} from '../../base/BaseStyle'
import { exitLoginStatus, requestSysProfile, setNavigation } from '../../action/LoginAction'
import { getSettlementStatus } from '../../action/SettlementAction'
import { getSettlementStatus, getInvoiceStatus } from '../../action/SettlementAction'
import HeadBackItem from '../common/HeadBackItem'
import StatusBarView from '../common/StatusBarView'
import TabBottomItem from './module/TabBottomItem'
......@@ -79,14 +79,14 @@ class HomePage extends Component {
page: '',
},
MOBILE_DIRECT_INVOICE_APPLICATION: {
icon: require('../../images/quick_order.png'),
icon: require('../../images/direct_invoice_icon.png'),
title: '直销-开票申请',
page: 'DirectionInvoice',
},
MOBILE_DIRECT_INVOICE_GATHER: {
icon: require('../../images/quick_order.png'),
icon: require('../../images/invoice_list_icon.png'),
title: '直销-开票汇总',
page: '',
page: 'DirectionInvoiceCollections',
},
},
},
......@@ -201,6 +201,7 @@ class HomePage extends Component {
if (isBlank(settlementModule)) return
this.props.getSettlementStatus()
this.props.getInvoiceStatus()
}
// 跳转页面
......@@ -346,6 +347,9 @@ const mapDispatchToProps = dispatch => ({
getSettlementStatus: () => {
dispatch(getSettlementStatus())
},
getInvoiceStatus: () => {
dispatch(getInvoiceStatus())
},
})
export default connect(mapStateToProps, mapDispatchToProps)(HomePage)
......@@ -2,15 +2,16 @@
* @FilePath: /BoneHouse_Business_APP/app/reducers/module/settlement.js
* @Author: peii
* @Date: 2021-12-21 16:52:11
* @LastEditTime: 2021-12-21 16:57:52
* @LastEditTime: 2022-01-05 15:20:50
* @LastEditors: peii
* @Vision: 1.0
* @Description: 结算
*/
import { SET_SETTLEMENT_STATUS } from '../../base/ActionTypes'
import { SET_SETTLEMENT_STATUS, SET_INVOICE_STATUS } from '../../base/ActionTypes'
const defaultState = {
headerStatus: [],
invoiceHeaderStatus: []
}
export default (state = defaultState, action) => {
......@@ -20,6 +21,11 @@ export default (state = defaultState, action) => {
headerStatus: action.values,
})
case SET_INVOICE_STATUS:
return Object.assign({}, state, {
invoiceHeaderStatus: action.values,
})
default:
return state
}
......
/*
* @FilePath: /BoneHouse_Business_APP/src/pages/invoice/direct/collections.tsx
* @Author: peii
* @Date: 2021-12-27 09:59:21
* @LastEditTime: 2022-01-05 15:25:16
* @LastEditors: peii
* @Vision: 1.0
* @Description: 基于消耗单的直销开票查询汇总
*/
// @ts-nocheck
import React, { Component } from 'react'
import { View, Text, TouchableOpacity, Image, ActivityIndicator } from 'react-native'
import { connect } from 'react-redux'
import * as R from 'ramda'
import { INavigation } from 'navigation'
import { IFormField } from 'bonehouse'
import debounce from 'debounce'
import Loading from '../../../../app/containers/common/LodingModel'
import Header from '../../../components/header/header'
import Resolution from '../../../components/common/Resolution'
import FilterModal from './components/filter'
import InvoiceList from './components/list'
import { isBlank, g, isNotBlank, show } from '../../../utils/utils'
import { ConsumeProcessCode, FieldType } from '../../../enums'
import api from '../../../services/api'
import styles from './index.styl'
type IProps = {
navigation: INavigation
status: any[]
}
type IState = {
visible: boolean
}
class Direction extends Component<IProps, IState> {
constructor(props) {
super(props)
this.toggleModalVisible = this.toggleModalVisible.bind(this)
this.getData = this.getData.bind(this)
this.getLineData = this.getLineData.bind(this)
this.selectAllHandler = this.selectAllHandler.bind(this)
this.submitHandler = debounce(this.submitHandler.bind(this), 200)
this.itemClickHandler = this.itemClickHandler.bind(this)
this.checkedHandler = this.checkedHandler.bind(this)
this.countAndSum = this.countAndSum.bind(this)
}
state = {
visible: false,
loading: false,
data: [],
pagination: {
start_index: 0,
limit: 10,
},
filterData: {},
isEnd: false,
fresh: 0,
statistic: {
count: 0,
sum: 0,
},
customers: [],
submitting: false,
otherFilterItems: [
{
field: 'invoice_header_status',
label: '状态',
type: FieldType.RADIO,
options: R.compose(
R.map(
R.applySpec({
value: R.prop('value_code'),
label: R.prop('value_name'),
}),
),
R.propOr([], 'status'),
)(this.props),
},
],
}
componentDidMount() {
this.toggleModalVisible()
}
toggleModalVisible() {
const { visible } = this.state
this.setState({ visible: !visible })
}
/**
* @description: 请求分销结算数据
* @param {object} args 过滤参数
* @param {boolean} isRefresh 是否刷新类型
* @param {boolean} isNext 是否下一页
* @return {*}
*/
async getData(args, isRefresh = false, isNext = false) {
// 确认页面只过滤出已输入的那些
let { pagination, filterData, data, isEnd } = this.state
if (isRefresh || isNotBlank(args)) {
pagination.start_index = 0
}
if (isNext) {
pagination.start_index += pagination.limit
if (isEnd) return
}
if (isBlank(args)) {
args = filterData
} else {
this.setState({ filterData: args })
}
args.header_status = 'APPROVED'
// args.invoice_header_status = 'ENTERED'
const params = {
...args,
...pagination,
}
if (!isRefresh && !isNext) {
this.setState({ loading: true })
}
const res = await api.getConsumeHeaders(params)
this.setState({ loading: false })
if (res.error_code !== 0) return
const newData = R.pathOr([], ['data', 'sur_consume_headers'])(res)
if (isBlank(newData) || newData.length < pagination.limit) {
isEnd = true
} else {
isEnd = false
}
if (isNext) {
data = R.concat(data, newData)
} else {
data = newData
}
this.setState({ data, isEnd })
}
/**
* @description: 开票行
* @param {*}
* @return {*}
*/
async getLineData(order, loading = false) {
const params = {
consume_order_number: order.consume_order_number,
}
this.setState({ loading })
const res = await api.getConsumeLines(params)
this.setState({ loading: false })
if (res.error_code) return
order.lines = R.compose(R.sort(R.ascend(R.prop('line_number'))), R.pathOr([], ['data', 'sur_consume_lines']))(res)
}
/**
* @description: 单项点击
* @param {*} order
* @return {*}
*/
async itemClickHandler(order) {
if (isBlank(order.lines)) {
await this.getLineData(order, true)
}
const title = this.props.navigation.getParam('title')
this.props.navigation.navigate('DirectionInvoiceApplyDetail', {
title,
order,
isCollection: true,
refreshHandler: () => {
this.setState({ fresh: this.state.fresh + 1 })
this.countAndSum(order)
},
})
}
/**
* @description: 全选操作
* @param {*}
* @return {*}
*/
selectAllHandler() {}
/**
* @description: 单项选择
* @param {*}
* @return {*}
*/
async checkedHandler(checked, order) {
if (isBlank(order.lines)) {
await this.getLineData(order)
}
// order._indeterminate = false
// if (isNotBlank(order.lines)) {
// R.map(item => {
// item._checked = checked
// })(order.lines)
// }
this.countAndSum(order)
}
/**
* @description: 计算总数
* @param {*}
* @return {*}
*/
countAndSum(order) {
const { data } = this.state
const list = R.filter(R.propEq('_checked', true))(data)
const count = R.compose(R.sum, R.filter(isNotBlank), R.pluck('total_consumed_quantity'))(list)
const sum = R.compose(R.sum, R.filter(isNotBlank), R.pluck('total_amount'))(list).toFixed(2)
this.setState({ data, statistic: { count, sum } })
}
/**
* @description: 获取当前客户的收货地址
* @param {string} customer_code
* @return {*}
*/
getBillToSite(customer_code: string) {
const { customers = [] } = this.state
const customer = R.find(R.propEq('value', customer_code))(customers)
return R.pathOr(null, ['bill_to_sites', 0])(customer)
}
/**
* @description: 提交
* @param {*}
* @return {*}
*/
async submitHandler() {
const { data } = this.state
const list = R.compose(R.map(R.pick(['consume_order_number'])), R.filter(R.propEq('_checked', true)))(data)
if (isBlank(list)) {
return show('请选择要开票的物料')
}
const params = {
process_code: ConsumeProcessCode.APPLY_INVOICE,
data: list,
}
this.setState({ submitting: true })
const res = await api.postProcessConsumes(params)
this.setState({ submitting: false })
if (res.error_code) return
show('申请提交成功')
this.props.navigation.pop()
}
render() {
const title = this.props.navigation.getParam('title')
const { visible, loading, data, fresh, otherFilterItems } = this.state
return (
<View style={g(styles, 'container')}>
<Resolution.FixWidthView>
<Header
title={title}
backCallback={() => {
this.props.navigation.goBack()
}}
>
<TouchableOpacity style={g(styles, 'filter')} activeOpacity={0.8} onPress={this.toggleModalVisible}>
<Image source={require('../../../assets/images/filter_icon.png')} style={g(styles, 'filter-icon')} />
</TouchableOpacity>
</Header>
<View style={g(styles, 'body')}>
{/* 过滤弹窗 */}
<FilterModal
visible={visible}
onClose={this.toggleModalVisible}
otherFilterItems={otherFilterItems}
searchHandler={(filterData, customers) => {
this.setState({ customers })
this.getData(filterData)
}}
/>
{/* 显示列表 */}
{loading ? (
<Loading show={loading} />
) : (
<InvoiceList
data={data}
{...this.props}
fresh={fresh}
getData={this.getData}
itemClickHandler={this.itemClickHandler}
checkedHandler={this.checkedHandler}
isCollection={true}
/>
)}
{/* {isNotBlank(data) && !loading && (
<View style={g(styles, 'body-ft')}>
<View style={g(styles, 'body-ft-statistic')}>
<Text style={g(styles, 'body-ft-statistic__text')}>申请开票总数量: {statistic.count}</Text>
<Text style={g(styles, 'body-ft-statistic__text')}>申请开票总金额: {statistic.sum}</Text>
</View>
<View style={g(styles, 'body-ft-btn')}>
{!submitting ? (
<TouchableOpacity
style={g(styles, 'btn', 'btn-submit')}
activeOpacity={0.8}
onPress={this.submitHandler}
>
<Text style={g(styles, 'btn__text', 'btn-submit__text')}>申请开票</Text>
</TouchableOpacity>
) : (
<TouchableOpacity style={g(styles, 'btn', 'btn-disabled')} activeOpacity={1}>
<ActivityIndicator style={g(styles, 'btn-indicator')}></ActivityIndicator>
<Text style={g(styles, 'btn__text', 'btn-disabled__text')}>申请开票</Text>
</TouchableOpacity>
)}
</View>
</View>
)} */}
</View>
</Resolution.FixWidthView>
</View>
)
}
}
const mapStateToProps = state => ({
status: state.settlement.invoiceHeaderStatus,
})
const mapDispatchToProps = dispatch => ({})
export default connect(mapStateToProps, mapDispatchToProps)(Direction)
......@@ -42,6 +42,11 @@
width 80px
height @width
&-status
&__text
font-size 16px
font-family font_family_regular
.text
&-red
color #f00
......
......@@ -2,7 +2,7 @@
* @FilePath: /BoneHouse_Business_APP/src/pages/invoice/direct/components/list.tsx
* @Author: peii
* @Date: 2021-12-19 10:44:15
* @LastEditTime: 2022-01-04 11:49:24
* @LastEditTime: 2022-01-05 11:34:50
* @LastEditors: peii
* @Vision: 1.0
* @Description: 汇总列表
......@@ -119,6 +119,12 @@ class DistributeInvoiceList extends Component<IProps> {
return { count, sum: sum.toFixed(2) }
}
statusClzMap = R.cond([
[R.equals('INVOICING'), R.always('text-red')],
[R.equals('INVOICED'), R.always('text-blue')],
[R.T, R.always('text-black')],
])
/**
* @description: 结算单单项
* @param {*} param1
......@@ -128,9 +134,9 @@ class DistributeInvoiceList extends Component<IProps> {
const { isCollection } = this.props
// 开票汇总
if (isCollection) {
return this.renderCollectionItem.call(this, item, index)
}
// if (isCollection) {
// return this.renderCollectionItem.call(this, item, index)
// }
// 分销开票申请单项
return (
......@@ -154,7 +160,19 @@ class DistributeInvoiceList extends Component<IProps> {
<Text style={g(styles, 'item-text', 'item-left-text')}>
金额: {item.total_amount && item.total_amount.toFixed(2)}
</Text>
{isCollection && (
<Text style={g(styles, 'item-text', 'item-left-text')}>
申请开票时间: {item.invocie_time ? dayjs(item.invocie_time).format('YYYY-MM-DD') : '——'}
</Text>
)}
</View>
{isCollection ? (
<View style={g(styles, 'item-status')}>
<Text style={g(styles, 'item-status__text', this.statusClzMap(item.invoice_header_status))}>
{item.invoice_header_status_name}
</Text>
</View>
) : (
<View style={g(styles, 'item-select')}>
<Checkbox
style={g(styles, 'item-select-box')}
......@@ -163,6 +181,7 @@ class DistributeInvoiceList extends Component<IProps> {
onChange={checked => this.checkedHandler(checked, item)}
/>
</View>
)}
</View>
{/* <View style={g(styles, 'item-line')}>
......
......@@ -2,7 +2,7 @@
* @FilePath: /BoneHouse_Business_APP/src/pages/invoice/direct/detail.tsx
* @Author: peii
* @Date: 2021-12-29 11:26:53
* @LastEditTime: 2022-01-04 17:00:14
* @LastEditTime: 2022-01-05 11:45:19
* @LastEditors: peii
* @Vision: 1.0
* @Description: 开票申请详情
......@@ -136,6 +136,8 @@ class InvoiceApplyDetail extends Component<IProps> {
* @return {*}
*/
renderItem({ item, index }) {
const isCollection = this.props.navigation.getParam('isCollection', false)
return (
<View style={g(styles, 'item')}>
<View style={g(styles, 'item-info')}>
......@@ -167,6 +169,23 @@ class InvoiceApplyDetail extends Component<IProps> {
金额: {item.consumed_quantity * item.consumed_price}
</Text>
</View>
{isCollection && (
<>
<View style={g(styles, 'item-info-line')}>
<Text style={g(styles, 'item-info__text', 'item-info-line__text')}>
开票完成时间: {(item.invoiced_time && dayjs(item.invoiced_time).format('YYYY-MM-DD')) || '--'}
</Text>
<Text style={g(styles, 'item-info__text', 'item-info-line__text')}>
已开票数量: {item.invoiced_quantity || '--'}
</Text>
</View>
<View style={g(styles, 'item-info-line')}>
<Text style={g(styles, 'item-info__text', 'item-info-line__text')}>
发票号: {item.invoice_number || '--'}
</Text>
</View>
</>
)}
</View>
{/* <View style={g(styles, 'item-select')}>
<Checkbox
......
......@@ -2,7 +2,7 @@
* @FilePath: /BoneHouse_Business_APP/src/services/api.ts
* @Author: peii
* @Date: 2021-12-19 16:06:26
* @LastEditTime: 2022-01-04 17:21:58
* @LastEditTime: 2022-01-05 15:32:02
* @LastEditors: peii
* @Vision: 1.0
* @Description: 未重构完全暂用的所有请求
......@@ -90,7 +90,7 @@ export default {
* @return {*}
*/
postArInvoiceCreate(data: { org_code: string; customer_code: string; bill_to_site_code: string; lines: any[] }) {
return request({ url: `${v}/ar_invoice/create`, data: { data }, method: 'post' })
return request({ url: `${v}/receivable/ar_invoice/create`, data: { data }, method: 'post' })
},
/**
......
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 sign in to comment