Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
Kivii.Biz.Finances.V2.5
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
陶然
Kivii.Biz.Finances.V2.5
Commits
40c38680
Commit
40c38680
authored
May 22, 2025
by
Neo Turing
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
增加发票申请及流程审批,发票关联到账等功能
parent
c63f4bf2
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
701 additions
and
5 deletions
+701
-5
.gitignore
.gitignore
+1
-0
ApplyExtension.cs
Src/Extensions/ApplyExtension.cs
+88
-0
Kivii.Biz.Finances.V2.5.csproj
Src/Kivii.Biz.Finances.V2.5.csproj
+2
-0
AssemblyInfo.cs
Src/Properties/AssemblyInfo.cs
+2
-2
RestfulApply.cs
Src/Transforms/RestfulApply.cs
+588
-0
RestfulInvoice.cs
Src/Transforms/RestfulInvoice.cs
+20
-3
No files found.
.gitignore
View file @
40c38680
...
@@ -4,3 +4,4 @@
...
@@ -4,3 +4,4 @@
/.vs
/.vs
/Src/obj
/Src/obj
/Src/bin/Debug
Src/Extensions/ApplyExtension.cs
0 → 100644
View file @
40c38680
using
Kivii.Finances.Entities
;
using
Kivii.Linq
;
using
System
;
using
System.Collections.Generic
;
using
System.Data
;
using
System.Linq
;
using
System.Text
;
using
System.Threading.Tasks
;
namespace
Kivii.Finances
{
public
static
class
ApplyExtension
{
public
static
void
ExcuteCompleted
(
this
List
<
InvoiceApply
>
allApplys
,
IDbConnection
conn
=
null
)
{
if
(
allApplys
.
IsNullOrEmpty
())
return
;
var
applys
=
allApplys
.
Where
(
o
=>
o
.
AmountInvoice
<
o
.
Amount
).
ToList
();
if
(
applys
.
IsNullOrEmpty
())
return
;
var
applyKvids
=
applys
.
ConvertAll
(
p
=>
p
.
Kvid
);
bool
useTransaction
=
conn
==
null
;
//是否启用事务,如果外部未传入conn,启用内部事务
if
(
conn
==
null
)
conn
=
KiviiContext
.
GetOpenedDbConnection
<
InvoiceApply
>();
var
queryInvoices
=
conn
.
From
<
Invoice
>();
queryInvoices
.
Where
(
o
=>
o
.
OffsetKvid
==
Guid
.
Empty
&&
o
.
RootKvid
==
o
.
Kvid
&&
Sql
.
In
(
o
.
ApplyKvid
,
applyKvids
));
queryInvoices
.
Select
(
o
=>
new
{
o
.
Kvid
,
o
.
Amount
,
o
.
ApplyKvid
});
var
invoices
=
conn
.
Select
(
queryInvoices
);
if
(
invoices
.
IsNullOrEmpty
())
return
;
var
relations
=
conn
.
Select
<
InvoiceApply
>(
o
=>
o
.
OffsetKvid
==
Guid
.
Empty
&&
o
.
OperateType
==
InvoiceApplyType
.
Related
&&
Sql
.
In
(
o
.
ParentKvid
,
applyKvids
));
List
<
InvoiceApply
>
preUpdates
=
new
List
<
InvoiceApply
>();
foreach
(
var
apply
in
applys
)
{
if
(
apply
.
AmountInvoice
==
apply
.
Amount
)
continue
;
var
currentInvoices
=
invoices
.
Where
(
o
=>
o
.
ApplyKvid
==
apply
.
Kvid
).
ToList
();
if
(
currentInvoices
.
IsNullOrEmpty
())
continue
;
var
amountSum
=
currentInvoices
.
Sum
(
o
=>
o
.
Amount
);
List
<
InvoiceApply
>
applyRelations
=
null
;
if
(!
relations
.
IsNullOrEmpty
())
applyRelations
=
relations
.
Where
(
o
=>
o
.
ParentKvid
==
apply
.
Kvid
).
ToList
();
if
(
amountSum
!=
apply
.
Amount
)
throw
new
Exception
(
$"
{
apply
.
PayerName
}
:发票金额
{
currentInvoices
.
Sum
(
o
=>
o
.
Amount
)}
和申请金额
{
apply
.
Amount
}
不一致"
);
apply
.
AmountInvoice
=
amountSum
;
apply
.
AddOnlyProperties
(
o
=>
o
.
AmountInvoice
);
if
(
apply
.
AmountInvoice
==
apply
.
Amount
)
{
apply
.
Status
=
(
int
)
InvoiceApplyStatus
.
Completed
;
apply
.
AddOnlyProperties
(
o
=>
o
.
Status
);
}
preUpdates
.
Add
(
apply
);
if
(!
applyRelations
.
IsNullOrEmpty
())
{
foreach
(
var
item
in
applyRelations
)
{
item
.
AmountInvoice
=
item
.
Amount
;
item
.
AddOnlyProperties
(
o
=>
o
.
AmountInvoice
);
if
(
item
.
AmountInvoice
==
item
.
Amount
)
{
item
.
Status
=
(
int
)
InvoiceApplyStatus
.
Completed
;
item
.
AddOnlyProperties
(
o
=>
o
.
Status
);
}
preUpdates
.
Add
(
item
);
}
}
}
if
(
preUpdates
.
IsNullOrEmpty
())
return
;
IDbTransaction
trans
=
null
;
//事务,如果外部来了Connection,不生成事务
if
(
useTransaction
)
trans
=
conn
.
OpenTransaction
();
try
{
if
(!
preUpdates
.
IsNullOrEmpty
())
{
foreach
(
var
item
in
preUpdates
)
{
if
(!
item
.
OnlyProperties
.
IsNullOrEmpty
())
conn
.
UpdateOnly
(
item
);
}
}
trans
?.
Commit
();
}
catch
(
Exception
ex
)
{
trans
?.
Rollback
();
throw
ex
;
}
}
}
}
Src/Kivii.Biz.Finances.V2.5.csproj
View file @
40c38680
...
@@ -59,11 +59,13 @@
...
@@ -59,11 +59,13 @@
<Compile
Include=
"Entities\InvoiceDetail.cs"
/>
<Compile
Include=
"Entities\InvoiceDetail.cs"
/>
<Compile
Include=
"Entities\InvoiceTitle.cs"
/>
<Compile
Include=
"Entities\InvoiceTitle.cs"
/>
<Compile
Include=
"Entities\Payment.cs"
/>
<Compile
Include=
"Entities\Payment.cs"
/>
<Compile
Include=
"Extensions\ApplyExtension.cs"
/>
<Compile
Include=
"Extensions\Extension.cs"
/>
<Compile
Include=
"Extensions\Extension.cs"
/>
<Compile
Include=
"Extensions\InvoiceExtension.cs"
/>
<Compile
Include=
"Extensions\InvoiceExtension.cs"
/>
<Compile
Include=
"Extensions\PaymentExtension.cs"
/>
<Compile
Include=
"Extensions\PaymentExtension.cs"
/>
<Compile
Include=
"Properties\AssemblyInfo.cs"
/>
<Compile
Include=
"Properties\AssemblyInfo.cs"
/>
<Compile
Include=
"Transforms\RestfulAccount.cs"
/>
<Compile
Include=
"Transforms\RestfulAccount.cs"
/>
<Compile
Include=
"Transforms\RestfulApply.cs"
/>
<Compile
Include=
"Transforms\RestfulInvoice.cs"
/>
<Compile
Include=
"Transforms\RestfulInvoice.cs"
/>
<Compile
Include=
"Transforms\RestfulInvoiceDetail.cs"
/>
<Compile
Include=
"Transforms\RestfulInvoiceDetail.cs"
/>
<Compile
Include=
"Transforms\RestfulInvoiceTitle.cs"
/>
<Compile
Include=
"Transforms\RestfulInvoiceTitle.cs"
/>
...
...
Src/Properties/AssemblyInfo.cs
View file @
40c38680
...
@@ -37,5 +37,5 @@ using System.Runtime.InteropServices;
...
@@ -37,5 +37,5 @@ using System.Runtime.InteropServices;
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("5.4.2025.5
07
0")]
[assembly: AssemblyVersion("5.4.2025.5
22
0")]
[assembly: AssemblyFileVersion("5.4.2025.5
07
0")]
[assembly: AssemblyFileVersion("5.4.2025.5
22
0")]
Src/Transforms/RestfulApply.cs
0 → 100644
View file @
40c38680
using
Kivii.Finances.Entities
;
using
Kivii.Linq
;
using
Kivii.Web
;
using
System
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Text
;
using
System.Threading.Tasks
;
namespace
Kivii.Finances.Transforms
{
[
RequiresAnyRole
(
MemberRoles
.
Everyone
)]
public
class
InvoiceApplyQuery
:
RestfulExecution
<
InvoiceApply
>
{
#
region
QueryArgs
public
virtual
int
?
Skip
{
get
;
set
;
}
public
virtual
int
?
Take
{
get
;
set
;
}
public
virtual
string
OrderBy
{
get
;
set
;
}
public
string
OrderByDesc
{
get
;
set
;
}
public
virtual
string
Include
{
get
;
set
;
}
public
virtual
string
Fields
{
get
;
set
;
}
public
string
QueryKeys
{
get
;
set
;
}
public
string
QueryValues
{
get
;
set
;
}
#
endregion
public
DateTime
BeginTime
{
get
;
set
;
}
public
DateTime
EndTime
{
get
;
set
;
}
public
override
object
OnExecution
(
IRequest
req
,
IResponse
res
)
{
if
(
EndTime
<
BeginTime
)
throw
new
Exception
(
"查询结束日期不可小于开始日期!"
);
var
conn
=
KiviiContext
.
GetOpenedDbConnection
<
InvoiceApply
>();
var
dynamicParams
=
Request
.
GetRequestParams
();
var
autoQuery
=
Request
.
TryResolve
<
IAutoQueryDb
>();
autoQuery
.
IncludeTotal
=
true
;
var
request
=
new
RestfulQuery
<
InvoiceApply
>();
request
=
request
.
PopulateWith
(
this
);
var
sqlExpress
=
autoQuery
.
CreateQuery
(
Request
,
conn
,
request
,
dynamicParams
);
sqlExpress
.
Where
(
o
=>
o
.
OperateType
!=
InvoiceApplyType
.
Related
);
if
(
BeginTime
!=
DateTime
.
MinValue
)
sqlExpress
.
Where
(
o
=>
o
.
OperateTime
>=
BeginTime
);
if
(
EndTime
!=
DateTime
.
MinValue
)
sqlExpress
.
And
(
o
=>
o
.
OperateTime
<
EndTime
);
var
rtns
=
autoQuery
.
Execute
(
Request
,
conn
,
request
,
sqlExpress
);
return
rtns
;
}
}
[
RequiresAnyRole
(
MemberRoles
.
Everyone
)]
public
class
InvoiceApplyRead
:
RestfulRead
<
InvoiceApply
>
{
}
[
RequiresAnyRole
(
MemberRoles
.
Everyone
)]
public
class
InvoiceApplyUpdate
:
RestfulUpdate
<
InvoiceApply
>
{
}
[
RequiresAnyRole
(
MemberRoles
.
Everyone
)]
public
class
InvoiceApplyDelete
:
RestfulDelete
<
InvoiceApply
>
{
}
#
region
申请开票相关
[
Api
(
Description
=
"开票申请"
)]
[
RequiresAnyRole
(
MemberRoles
.
Everyone
)]
public
class
InvoiceApplyApply
:
RestfulExecution
<
InvoiceApply
>
{
public
InvoiceApply
Item
{
get
;
set
;
}
public
List
<
Guid
>
PaymentKvids
{
get
;
set
;
}
//发票开具最大额度限制 默认10万
public
decimal
Limit
{
get
;
set
;
}
=
100000
;
public
override
object
OnExecution
(
IRequest
req
,
IResponse
res
)
{
Item
.
ThrowIfNull
(
"请传入要申请的内容!"
);
if
(
Item
.
PayerName
.
IsNullOrEmpty
())
throw
new
Exception
(
"请输入发票抬头!"
);
if
(
Item
.
Currency
==
CurrencyUnit
.
Unsupported
)
throw
new
Exception
(
"不支持的货币单位!"
);
if
(
Item
.
Amount
<=
0
)
throw
new
Exception
(
"申请金额不能小于0!"
);
if
(
Item
.
Details
.
IsNullOrEmpty
())
throw
new
Exception
(
"请传入申请明细!"
);
if
(
Item
.
Amount
!=
Item
.
Details
.
Sum
(
o
=>
o
.
Amount
))
throw
new
Exception
(
"总金额和明细总额不一致!"
);
if
(
Item
.
Details
.
Exists
(
o
=>
o
.
GoodsFullName
.
IsNullOrEmpty
()))
throw
new
Exception
(
"明细名称存在空值!"
);
if
(
Item
.
Details
.
Exists
(
o
=>
o
.
TaxRate
<
0
)
||
Item
.
Details
.
Exists
(
o
=>
o
.
TaxRate
>
1
))
throw
new
Exception
(
"存在明细税率设置范围不在0-1之间!"
);
if
(
Item
.
Details
.
Exists
(
o
=>
o
.
Quantity
<=
0
))
throw
new
Exception
(
"请填写数量!"
);
if
(
Item
.
Details
.
Count
>
1
)
{
var
group
=
Item
.
Details
.
GroupBy
(
o
=>
o
.
GoodsId
);
foreach
(
var
kv
in
group
)
{
var
sum
=
kv
.
Sum
(
o
=>
o
.
Amount
);
if
(
sum
>
Limit
)
throw
new
Exception
(
$"组别:
{
kv
.
Key
}
,总额:
{
sum
}
元,金额总和不能超过限额
{
Limit
}
元!"
);
}
}
if
(
Item
.
OperateType
!=
InvoiceApplyType
.
Debit
)
PaymentKvids
.
ThrowIfNullOrEmpty
(
"请先选择相应收款!"
);
//申请人为当前登录人
Item
.
OperatorName
=
KiviiContext
.
CurrentMember
.
FullName
;
Item
.
OperatorKvid
=
KiviiContext
.
CurrentMember
.
Kvid
;
//申请所属部门
Item
.
OwnerKvid
=
KiviiContext
.
CurrentMember
.
DepartmentKvid
;
Item
.
OwnerName
=
KiviiContext
.
CurrentMember
.
DepartmentName
;
#
region
计算
(
不根据前端传来
)
foreach
(
var
detail
in
Item
.
Details
)
{
detail
.
AmountUntaxed
=
Math
.
Round
(
detail
.
Amount
/
(
1
+
detail
.
TaxRate
),
2
);
detail
.
AmountTax
=
detail
.
Amount
-
detail
.
AmountUntaxed
;
detail
.
QuantityUnitPriceUntaxed
=
Math
.
Round
(
detail
.
AmountUntaxed
/
detail
.
Quantity
,
2
);
detail
.
QuantityUnitPrice
=
Math
.
Round
(
detail
.
Amount
/
detail
.
Quantity
,
2
);
}
#
endregion
var
rtns
=
new
RestfulQueryResponse
<
InvoiceApply
>();
rtns
.
Results
=
new
List
<
InvoiceApply
>();
var
conn
=
KiviiContext
.
GetOpenedDbConnection
<
InvoiceApply
>();
if
(
Item
.
OperateType
==
InvoiceApplyType
.
Debit
)
{
var
trans
=
conn
.
OpenTransaction
();
try
{
var
applyKvid
=
Guid
.
NewGuid
();
foreach
(
var
detail
in
Item
.
Details
)
{
detail
.
ApplyKvid
=
applyKvid
;
conn
.
Insert
(
detail
);
}
Item
.
RootKvid
=
applyKvid
;
Item
.
ParentKvid
=
Guid
.
Empty
;
//Item.AmountUsed = 0;
Item
.
OperateTime
=
DateTime
.
Now
;
Item
.
Status
=
(
int
)
InvoiceApplyStatus
.
FinancialExecute
;
Item
.
Kvid
=
applyKvid
;
conn
.
Insert
(
Item
);
rtns
.
Results
.
Add
(
Item
);
trans
.
Commit
();
}
catch
(
Exception
ex
)
{
trans
.
Rollback
();
throw
ex
;
}
}
else
{
var
paymentKvidsDistinct
=
PaymentKvids
.
Distinct
().
ToList
();
var
payments
=
conn
.
Select
<
Payment
>(
o
=>
Sql
.
In
(
o
.
Kvid
,
paymentKvidsDistinct
));
(
payments
.
Count
<=
0
||
payments
.
Count
!=
paymentKvidsDistinct
.
Count
).
ThrowIfTrue
(
"收款信息与所选项目不一致!"
);
(
payments
.
Exists
(
o
=>
o
.
Type
!=
PaymentType
.
Bank
&&
o
.
Type
!=
PaymentType
.
Split
&&
o
.
Type
!=
PaymentType
.
AliPay
&&
o
.
Type
!=
PaymentType
.
Pos
&&
o
.
Type
!=
PaymentType
.
WeChat
&&
o
.
Type
!=
PaymentType
.
Cash
)).
ThrowIfTrue
(
"请选择正确的收款信息进行申请!"
);
(
payments
.
Exists
(
o
=>
o
.
Amount
<=
o
.
AmountInvoice
)).
ThrowIfTrue
(
"存在已开票的到账!无法重复申请!"
);
if
(
Item
.
Amount
!=
payments
.
Sum
(
o
=>
o
.
Amount
-
o
.
AmountInvoice
))
throw
new
Exception
(
"申请金额与所选到账金额不一致!"
);
var
paymentKvids
=
payments
.
ConvertAll
(
o
=>
o
.
Kvid
);
(
conn
.
Exists
<
InvoiceApply
>(
o
=>
o
.
OperateType
==
InvoiceApplyType
.
Related
&&
o
.
OffsetKvid
==
Guid
.
Empty
&&
Sql
.
In
(
o
.
BizKvid
,
paymentKvids
))).
ThrowIfTrue
(
"已有申请开票中的到账!"
);
var
trans
=
conn
.
OpenTransaction
();
try
{
var
applyKvid
=
Guid
.
NewGuid
();
foreach
(
var
detail
in
Item
.
Details
)
{
detail
.
ApplyKvid
=
applyKvid
;
conn
.
Insert
(
detail
);
}
Item
.
RootKvid
=
applyKvid
;
Item
.
ParentKvid
=
Guid
.
Empty
;
//Item.AmountUsed = Item.Amount;
Item
.
OperateTime
=
DateTime
.
Now
;
Item
.
Status
=
(
int
)
InvoiceApplyStatus
.
FinancialExecute
;
Item
.
Kvid
=
applyKvid
;
conn
.
Insert
(
Item
);
rtns
.
Results
.
Add
(
Item
);
foreach
(
var
item
in
payments
)
{
var
relation
=
new
InvoiceApply
();
relation
.
PopulateWith
(
Item
);
relation
.
BizId
=
item
.
SerialNumber
;
relation
.
BizKvid
=
item
.
Kvid
;
relation
.
BizType
=
typeof
(
Payment
).
FullName
;
relation
.
Kvid
=
Guid
.
NewGuid
();
relation
.
RootKvid
=
applyKvid
;
relation
.
ParentKvid
=
applyKvid
;
relation
.
SerialNumber
=
string
.
Empty
;
relation
.
OperateType
=
InvoiceApplyType
.
Related
;
relation
.
Type
=
Item
.
OperateType
.
ToString
();
relation
.
Amount
=
item
.
Amount
-
item
.
AmountInvoice
;
relation
.
OperatorName
=
KiviiContext
.
CurrentMember
.
FullName
;
relation
.
OperatorKvid
=
KiviiContext
.
CurrentMember
.
Kvid
;
relation
.
AmountInvoice
=
0
;
//relation.AmountUsed = relation.Amount;
conn
.
Insert
(
relation
);
}
trans
.
Commit
();
}
catch
(
Exception
ex
)
{
trans
.
Rollback
();
throw
ex
;
}
}
rtns
.
Total
=
rtns
.
Results
.
Count
();
return
rtns
;
}
}
[
Api
(
Description
=
"批量借票申请"
)]
[
RequiresAnyRole
(
MemberRoles
.
Everyone
)]
public
class
InvoiceApplyMultiApply
:
RestfulExecution
<
InvoiceApply
>
{
public
InvoiceApply
Item
{
get
;
set
;
}
public
List
<
InvoiceApply
>
Items
{
get
;
set
;
}
public
override
object
OnExecution
(
IRequest
req
,
IResponse
res
)
{
(
Item
==
null
&&
Items
.
IsNullOrEmpty
()).
ThrowIfTrue
(
"请传入要借票信息!"
);
if
(
Items
.
IsNullOrEmpty
())
Items
=
new
List
<
InvoiceApply
>();
if
(
Item
!=
null
)
Items
.
Add
(
Item
);
if
(
Items
.
Exists
(
o
=>
o
.
PayerName
.
IsNullOrEmpty
()))
throw
new
Exception
(
"存在发票抬头为空!"
);
if
(
Items
.
Exists
(
o
=>
o
.
PayerTaxNumber
.
IsNullOrEmpty
()))
throw
new
Exception
(
"存在税号为空!"
);
if
(
Items
.
Exists
(
o
=>
o
.
Currency
==
CurrencyUnit
.
Unsupported
))
throw
new
Exception
(
"存在不支持的货币单位!"
);
if
(
Items
.
Exists
(
o
=>
o
.
Amount
<=
0
))
throw
new
Exception
(
"申请金额不能小于0!"
);
if
(
Items
.
Exists
(
o
=>
o
.
OperateType
!=
InvoiceApplyType
.
Debit
))
throw
new
Exception
(
"此接口仅针对借票申请开票!"
);
var
rtns
=
new
RestfulQueryResponse
<
InvoiceApply
>();
rtns
.
Results
=
new
List
<
InvoiceApply
>();
var
conn
=
KiviiContext
.
GetOpenedDbConnection
<
InvoiceApply
>();
foreach
(
var
item
in
Items
)
{
#
region
创建借票申请
var
applyKvid
=
Guid
.
NewGuid
();
item
.
OperateType
=
InvoiceApplyType
.
Debit
;
//申请人为当前登录人
item
.
OperatorName
=
KiviiContext
.
CurrentMember
.
FullName
;
item
.
OperatorKvid
=
KiviiContext
.
CurrentMember
.
Kvid
;
//申请所属部门
item
.
OwnerKvid
=
KiviiContext
.
CurrentMember
.
DepartmentKvid
;
item
.
OwnerName
=
KiviiContext
.
CurrentMember
.
DepartmentName
;
item
.
RootKvid
=
applyKvid
;
item
.
ParentKvid
=
Guid
.
Empty
;
//item.AmountUsed = 0;
item
.
OperateTime
=
DateTime
.
Now
;
item
.
Status
=
(
int
)
InvoiceApplyStatus
.
FinancialApproval
;
item
.
Kvid
=
applyKvid
;
conn
.
Insert
(
item
);
#
endregion
rtns
.
Results
.
Add
(
item
);
}
rtns
.
Total
=
rtns
.
Results
.
Count
();
return
rtns
;
}
}
#
endregion
#
region
审批过程
/// <summary>
/// 财务通过申请
/// </summary>
[
Api
(
Description
=
"财务审批申请开票通过"
)]
[
RequiresAnyRole
(
MemberRoles
.
Everyone
)]
public
class
InvoiceApplyAgree
:
RestfulExecution
<
InvoiceApply
>
{
public
List
<
Guid
>
ApplyKvids
{
get
;
set
;
}
public
override
object
OnExecution
(
IRequest
req
,
IResponse
res
)
{
var
rtns
=
new
List
<
InvoiceApply
>();
var
conn
=
KiviiContext
.
GetOpenedDbConnection
<
InvoiceApply
>();
var
applys
=
conn
.
Select
<
InvoiceApply
>(
o
=>
Sql
.
In
(
o
.
Kvid
,
ApplyKvids
));
if
(
applys
==
null
)
throw
new
Exception
(
"无相关申请!"
);
foreach
(
var
item
in
applys
)
{
if
(
item
.
Status
>=
(
int
)
InvoiceApplyStatus
.
FinancialApproval
)
continue
;
//流程还未走完的申请跳过
if
(
item
.
Status
<
(
int
)
InvoiceApplyStatus
.
ProcessAdoption
)
continue
;
item
.
Status
=
(
int
)
InvoiceApplyStatus
.
FinancialApproval
;
item
.
AddOnlyProperties
(
o
=>
o
.
Status
);
conn
.
UpdateOnly
(
item
);
item
.
RemoveAllOnlyProperties
();
rtns
.
Add
(
item
);
}
return
new
RestfulUpdateResponse
<
InvoiceApply
>
{
Results
=
rtns
};
}
}
[
Api
(
Description
=
"申请驳回"
)]
[
RequiresAnyRole
(
MemberRoles
.
Everyone
)]
public
class
InvoiceApplyReject
:
RestfulExecution
<
InvoiceApply
>
{
public
List
<
Guid
>
ApplyKvids
{
get
;
set
;
}
public
string
Summary
{
get
;
set
;
}
public
override
object
OnExecution
(
IRequest
req
,
IResponse
res
)
{
var
conn
=
KiviiContext
.
GetOpenedDbConnection
<
InvoiceApply
>();
var
applys
=
conn
.
Select
<
InvoiceApply
>(
o
=>
Sql
.
In
(
o
.
Kvid
,
ApplyKvids
)
&&
o
.
OperateType
!=
InvoiceApplyType
.
Related
);
if
(
applys
==
null
)
throw
new
Exception
(
"无相关申请!"
);
var
applyRelations
=
conn
.
Select
<
InvoiceApply
>(
o
=>
Sql
.
In
(
o
.
ParentKvid
,
applys
.
ConvertAll
(
p
=>
p
.
Kvid
))
&&
o
.
OperateType
==
InvoiceApplyType
.
Related
);
var
rtns
=
new
RestfulExecutionResponse
<
InvoiceApply
>();
rtns
.
Results
=
new
List
<
InvoiceApply
>();
var
trans
=
conn
.
OpenTransaction
();
try
{
foreach
(
var
apply
in
applys
)
{
#
region
apply
驳回
//进入开票状态后不可驳回
(
apply
.
Status
>
(
int
)
InvoiceApplyStatus
.
FinancialExecute
).
ThrowIfTrue
(
"撤销失败,当前申请已进入开票列队或已完成开票!"
);
apply
.
Status
=
(
int
)
InvoiceApplyStatus
.
ApplyReject
;
apply
.
AddOnlyProperties
(
o
=>
o
.
Status
);
//apply.AmountUsed = 0;
//apply.AddOnlyProperties(o => o.AmountUsed);
apply
.
Summary
+=
" (驳回原因:"
+
Summary
+
")"
;
apply
.
AddOnlyProperties
(
o
=>
o
.
Summary
);
conn
.
UpdateOnly
(
apply
);
apply
.
RemoveAllOnlyProperties
();
rtns
.
Results
.
Add
(
apply
);
if
(
applyRelations
.
IsNullOrEmpty
())
continue
;
var
relations
=
applyRelations
.
Where
(
o
=>
o
.
ParentKvid
==
apply
.
Kvid
).
ToList
();
if
(
relations
.
IsNullOrEmpty
())
continue
;
#
endregion
#
region
关联
apply
删除
foreach
(
var
item
in
relations
)
{
item
.
Status
=
-
1
;
item
.
AddOnlyProperties
(
o
=>
o
.
Status
);
conn
.
UpdateOnly
(
item
);
}
#
endregion
}
trans
.
Commit
();
}
catch
(
Exception
ex
)
{
trans
.
Rollback
();
throw
ex
;
}
return
rtns
;
}
}
[
Api
(
Description
=
"执行开票"
)]
[
RequiresAnyRole
(
MemberRoles
.
Everyone
)]
public
class
InvoiceApplyExecute
:
RestfulExecution
<
InvoiceApply
>
{
public
Guid
Kvid
{
get
;
set
;
}
public
List
<
Guid
>
Kvids
{
get
;
set
;
}
public
override
object
OnExecution
(
IRequest
req
,
IResponse
res
)
{
(
Kvid
==
Guid
.
Empty
&&
Kvids
.
IsNullOrEmpty
()).
ThrowIfTrue
(
"Need Kvid Or Kvids!"
);
if
(
Kvids
.
IsNullOrEmpty
())
Kvids
=
new
List
<
Guid
>();
if
(
Kvid
!=
Guid
.
Empty
)
Kvids
.
Add
(
Kvid
);
if
(
Kvids
.
IsNullOrEmpty
())
throw
new
Exception
(
"请先选择申请条目!"
);
var
conn
=
KiviiContext
.
GetOpenedDbConnection
<
InvoiceApply
>();
var
applys
=
conn
.
SelectByIds
<
InvoiceApply
>(
Kvids
);
if
(
applys
.
IsNullOrEmpty
())
throw
new
Exception
(
"不存在的申请!"
);
(
applys
.
Exists
(
o
=>
o
.
OperateType
==
InvoiceApplyType
.
Related
)).
ThrowIfTrue
(
"申请类型不正确!"
);
if
(
applys
.
Exists
(
o
=>
o
.
Status
>=
(
int
)
InvoiceApplyStatus
.
FinancialExecute
))
throw
new
Exception
(
"请勿重复申请开票!"
);
if
(
applys
.
Exists
(
o
=>
o
.
Status
<
(
int
)
InvoiceApplyStatus
.
ProcessAdoption
))
throw
new
Exception
(
"此申请还在审批中..."
);
var
existDetails
=
conn
.
Select
<
InvoiceApplyDetail
>(
o
=>
Sql
.
In
(
o
.
ApplyKvid
,
applys
.
ConvertAll
(
p
=>
p
.
Kvid
)));
existDetails
.
ThrowIfNullOrEmpty
(
"未查到相关申请明细!"
);
if
(
applys
.
Sum
(
o
=>
o
.
Amount
)
!=
existDetails
.
Sum
(
p
=>
p
.
Amount
))
throw
new
Exception
(
"总金额和明细总额不一致!"
);
var
applyRelations
=
conn
.
Select
<
InvoiceApply
>(
o
=>
Sql
.
In
(
o
.
ParentKvid
,
applys
.
ConvertAll
(
p
=>
p
.
Kvid
))
&&
o
.
OperateType
==
InvoiceApplyType
.
Related
&&
o
.
OffsetKvid
==
Guid
.
Empty
);
var
payments
=
conn
.
Select
<
Payment
>(
o
=>
Sql
.
In
(
o
.
Kvid
,
applyRelations
.
ConvertAll
(
p
=>
p
.
BizKvid
)));
//Type:Split,Pos,Cash,WeChat...
(
conn
.
Exists
<
Invoice
>(
o
=>
o
.
OffsetKvid
==
Guid
.
Empty
&&
Sql
.
In
(
o
.
BizKvid
,
payments
.
ConvertAll
(
p
=>
p
.
RootKvid
)))).
ThrowIfTrue
(
"已有开票的到账,无法重复开票,请驳回!"
);
var
rtns
=
new
RestfulExecutionResponse
<
InvoiceApply
>();
rtns
.
Results
=
new
List
<
InvoiceApply
>();
var
trans
=
conn
.
OpenTransaction
();
try
{
#
region
申请状态进入开票状态
foreach
(
var
item
in
applys
)
{
item
.
Status
=
(
int
)
InvoiceApplyStatus
.
FinancialExecute
;
item
.
AddOnlyProperties
(
o
=>
o
.
Status
);
conn
.
UpdateOnly
(
item
);
rtns
.
Results
.
Add
(
item
);
}
#
endregion
trans
.
Commit
();
}
catch
(
Exception
ex
)
{
trans
.
Rollback
();
throw
ex
;
}
return
rtns
;
}
}
#
endregion
[
Api
(
Description
=
"录入发票结果"
)]
[
RequiresAnyRole
(
MemberRoles
.
Everyone
)]
public
class
InvoiceApplyExcuteResult
:
RestfulExecution
<
InvoiceApply
>
{
public
List
<
Invoice
>
Invoices
{
get
;
set
;
}
public
override
object
OnExecution
(
IRequest
req
,
IResponse
res
)
{
Invoices
.
ThrowIfNullOrEmpty
(
"请传入发票信息"
);
Invoices
.
Exists
(
o
=>
o
.
ApplyKvid
==
Guid
.
Empty
).
ThrowIfTrue
(
"缺少申请信息"
);
var
applyKvids
=
Invoices
.
ConvertAll
(
o
=>
o
.
ApplyKvid
).
Distinct
().
ToList
();
var
conn
=
KiviiContext
.
GetOpenedDbConnection
<
InvoiceApply
>();
var
applys
=
conn
.
SelectByIds
<
InvoiceApply
>(
applyKvids
);
applys
.
ThrowIfNullOrEmpty
(
"未找到对应申请信息"
);
applys
.
Exists
(
o
=>
o
.
OperateType
==
InvoiceApplyType
.
Related
).
ThrowIfTrue
(
"申请信息错误"
);
applys
.
Exists
(
o
=>
o
.
Status
<
(
int
)
InvoiceApplyStatus
.
ProcessAdoption
).
ThrowIfTrue
(
"此申请还在审批中"
);
(
applys
.
Count
!=
applyKvids
.
Count
).
ThrowIfTrue
(
"申请与发票对应数量不一致"
);
var
relations
=
conn
.
Select
<
InvoiceApply
>(
o
=>
Sql
.
In
(
o
.
ParentKvid
,
applyKvids
)
&&
o
.
OperateType
==
InvoiceApplyType
.
Related
&&
o
.
OffsetKvid
==
Guid
.
Empty
);
var
existDetails
=
conn
.
Select
<
InvoiceApplyDetail
>(
o
=>
Sql
.
In
(
o
.
ApplyKvid
,
applyKvids
));
var
rtns
=
new
RestfulUpdateResponse
<
InvoiceApply
>();
rtns
.
Results
=
new
List
<
InvoiceApply
>();
var
trans
=
conn
.
OpenTransaction
();
try
{
foreach
(
var
apply
in
applys
)
{
List
<
InvoiceApply
>
applyRelations
=
null
;
List
<
InvoiceApplyDetail
>
applyDetails
=
null
;
if
(!
relations
.
IsNullOrEmpty
())
applyRelations
=
relations
.
Where
(
o
=>
o
.
ParentKvid
==
apply
.
Kvid
).
ToList
();
if
(!
existDetails
.
IsNullOrEmpty
())
applyDetails
=
existDetails
.
Where
(
o
=>
o
.
ApplyKvid
==
apply
.
Kvid
).
ToList
();
var
currentInvoices
=
Invoices
.
Where
(
o
=>
o
.
ApplyKvid
==
apply
.
Kvid
).
ToList
();
if
(
currentInvoices
.
IsNullOrEmpty
())
continue
;
if
(
currentInvoices
.
Sum
(
o
=>
o
.
Amount
)
!=
apply
.
Amount
)
throw
new
Exception
(
$"
{
apply
.
PayerName
}
:发票金额
{
currentInvoices
.
Sum
(
o
=>
o
.
Amount
)}
和申请金额
{
apply
.
Amount
}
不一致"
);
#
region
处理申请明细
if
(!
existDetails
.
IsNullOrEmpty
())
{
foreach
(
var
exist
in
existDetails
)
{
exist
.
Status
=
-
1
;
exist
.
AddOnlyProperties
(
o
=>
o
.
Status
);
conn
.
UpdateOnly
(
exist
);
}
}
var
detail
=
new
InvoiceApplyDetail
();
detail
.
ApplyKvid
=
apply
.
Kvid
;
detail
.
GoodsFullName
=
currentInvoices
[
0
].
SerialNumber
;
detail
.
TaxRate
=
currentInvoices
[
0
].
TaxRate
;
detail
.
Amount
=
currentInvoices
.
Sum
(
o
=>
o
.
Amount
);
detail
.
Quantity
=
1
;
detail
.
AmountUntaxed
=
Math
.
Round
(
detail
.
Amount
/
(
1
+
detail
.
TaxRate
),
2
);
detail
.
AmountTax
=
detail
.
Amount
-
detail
.
AmountUntaxed
;
detail
.
QuantityUnitPriceUntaxed
=
Math
.
Round
(
detail
.
AmountUntaxed
/
detail
.
Quantity
,
2
);
detail
.
QuantityUnitPrice
=
Math
.
Round
(
detail
.
Amount
/
detail
.
Quantity
,
2
);
conn
.
Insert
(
detail
);
#
endregion
#
region
处理发票
foreach
(
var
invoice
in
currentInvoices
)
{
var
invoiceKvid
=
Guid
.
NewGuid
();
invoice
.
RootKvid
=
invoiceKvid
;
invoice
.
Kvid
=
invoiceKvid
;
invoice
.
AmountPayment
=
0
;
invoice
.
AmountUsed
=
0
;
invoice
.
AmountUntaxed
=
Math
.
Round
(
invoice
.
Amount
/
(
1
+
invoice
.
TaxRate
),
2
);
invoice
.
AmountTax
=
invoice
.
Amount
-
invoice
.
AmountUntaxed
;
invoice
.
Type
=
apply
.
Type
;
//"增值税普通发票";
invoice
.
OwnerKvid
=
apply
.
OwnerKvid
;
invoice
.
OwnerName
=
apply
.
OwnerName
;
invoice
.
Currency
=
apply
.
Currency
;
invoice
.
PayeeKvid
=
invoice
.
PayeeKvid
==
Guid
.
Empty
?
apply
.
PayeeKvid
:
invoice
.
PayeeKvid
;
invoice
.
PayeeName
=
invoice
.
PayeeName
.
IsNullOrEmpty
()
?
apply
.
PayeeName
:
invoice
.
PayeeName
;
invoice
.
PayeeTaxNumber
=
invoice
.
PayeeTaxNumber
.
IsNullOrEmpty
()
?
apply
.
PayeeTaxNumber
:
invoice
.
PayeeTaxNumber
;
invoice
.
PayeeCompanyAddress
=
invoice
.
PayeeCompanyAddress
.
IsNullOrEmpty
()
?
apply
.
PayeeCompanyAddress
:
invoice
.
PayeeCompanyAddress
;
invoice
.
PayeePhone
=
invoice
.
PayeePhone
.
IsNullOrEmpty
()
?
apply
.
PayeePhone
:
invoice
.
PayeePhone
;
invoice
.
PayeeRegisteredBank
=
invoice
.
PayeeRegisteredBank
.
IsNullOrEmpty
()
?
apply
.
PayeeRegisteredBank
:
invoice
.
PayeeRegisteredBank
;
invoice
.
PayeeBankAccount
=
invoice
.
PayeeBankAccount
.
IsNullOrEmpty
()
?
apply
.
PayeeBankAccount
:
invoice
.
PayeeBankAccount
;
invoice
.
PayerKvid
=
invoice
.
PayerKvid
==
Guid
.
Empty
?
apply
.
PayerKvid
:
invoice
.
PayerKvid
;
invoice
.
PayerName
=
invoice
.
PayerName
.
IsNullOrEmpty
()
?
apply
.
PayerName
:
invoice
.
PayerName
;
invoice
.
PayerTaxNumber
=
invoice
.
PayerTaxNumber
.
IsNullOrEmpty
()
?
apply
.
PayerTaxNumber
:
invoice
.
PayerTaxNumber
;
invoice
.
PayerCompanyAddress
=
invoice
.
PayerCompanyAddress
.
IsNullOrEmpty
()
?
apply
.
PayerCompanyAddress
:
invoice
.
PayerCompanyAddress
;
invoice
.
PayerPhone
=
invoice
.
PayerPhone
.
IsNullOrEmpty
()
?
apply
.
PayerPhone
:
invoice
.
PayerPhone
;
invoice
.
PayerRegisteredBank
=
invoice
.
PayerRegisteredBank
.
IsNullOrEmpty
()
?
apply
.
PayerRegisteredBank
:
invoice
.
PayerRegisteredBank
;
invoice
.
PayerBankAccount
=
invoice
.
PayerBankAccount
.
IsNullOrEmpty
()
?
apply
.
PayerBankAccount
:
invoice
.
PayerBankAccount
;
invoice
.
OperatorName
=
apply
.
OperatorName
;
//invoice.Remark = apply.Remark;
conn
.
Insert
(
invoice
);
#
region
插入发票明细
if
(
invoice
.
Details
.
IsNullOrEmpty
())
{
var
invoiceDetail
=
new
InvoiceDetail
();
invoiceDetail
.
InvoiceKvid
=
invoiceKvid
;
invoiceDetail
.
GoodsFullName
=
invoice
.
SerialNumber
;
//invoiceDetail.GoodsSpecifications = invoice.GoodsSpecifications;
invoiceDetail
.
Quantity
=
1
;
invoiceDetail
.
QuantityUnitPriceUntaxed
=
1
;
// quantityUnitPriceUntaxed;
invoiceDetail
.
AmountUntaxed
=
invoice
.
AmountUntaxed
;
invoiceDetail
.
Amount
=
invoice
.
Amount
;
invoiceDetail
.
AmountTax
=
invoice
.
AmountTax
;
invoiceDetail
.
TaxRate
=
invoice
.
TaxRate
;
conn
.
Insert
(
invoiceDetail
);
}
else
{
foreach
(
var
invoiceDetail
in
invoice
.
Details
)
{
invoiceDetail
.
InvoiceKvid
=
invoiceKvid
;
conn
.
Insert
(
invoiceDetail
);
}
}
#
endregion
#
region
更新申请状态
if
(!
applyRelations
.
IsNullOrEmpty
())
{
foreach
(
var
item
in
applyRelations
)
{
//无需更新
if
(
item
.
AmountInvoice
>=
item
.
Amount
)
continue
;
var
relationAmount
=
item
.
Amount
-
item
.
AmountInvoice
;
var
amountRelation
=
relationAmount
<=
invoice
.
Amount
?
relationAmount
:
invoice
.
Amount
;
item
.
AmountInvoice
+=
amountRelation
;
item
.
AddOnlyProperties
(
o
=>
o
.
AmountInvoice
);
if
(
item
.
AmountInvoice
==
item
.
Amount
)
{
item
.
Status
=
(
int
)
InvoiceApplyStatus
.
Completed
;
item
.
AddOnlyProperties
(
o
=>
o
.
Status
);
}
conn
.
UpdateOnly
(
item
);
}
}
apply
.
AmountInvoice
+=
invoice
.
Amount
;
apply
.
AddOnlyProperties
(
o
=>
o
.
AmountInvoice
);
if
(
apply
.
AmountInvoice
==
apply
.
Amount
)
{
apply
.
Status
=
(
int
)
InvoiceApplyStatus
.
Completed
;
apply
.
AddOnlyProperties
(
o
=>
o
.
Status
);
}
conn
.
UpdateOnly
(
apply
);
rtns
.
Results
.
Add
(
apply
);
#
endregion
}
#
endregion
//apply.Relation(conn);
}
trans
.
Commit
();
}
catch
(
Exception
ex
)
{
trans
.
Rollback
();
throw
ex
;
}
return
rtns
;
}
}
}
Src/Transforms/RestfulInvoice.cs
View file @
40c38680
...
@@ -55,7 +55,6 @@ namespace Kivii.Finances.Transforms
...
@@ -55,7 +55,6 @@ namespace Kivii.Finances.Transforms
(
Payments
.
Exists
(
o
=>
o
.
Amount
<=
0
)).
ThrowIfTrue
(
"未指定到账开票金额!"
);
(
Payments
.
Exists
(
o
=>
o
.
Amount
<=
0
)).
ThrowIfTrue
(
"未指定到账开票金额!"
);
(
Payments
.
Sum
(
o
=>
o
.
Amount
)
!=
Items
.
Sum
(
o
=>
o
.
Amount
)).
ThrowIfTrue
(
"到账开票金额和发票金额不一致!"
);
(
Payments
.
Sum
(
o
=>
o
.
Amount
)
!=
Items
.
Sum
(
o
=>
o
.
Amount
)).
ThrowIfTrue
(
"到账开票金额和发票金额不一致!"
);
}
}
#
region
启用缓存
,
将当前人创建批次数据存入
,
处理完毕或者接口报错后清除
,
确保不会重复创建
#
region
启用缓存
,
将当前人创建批次数据存入
,
处理完毕或者接口报错后清除
,
确保不会重复创建
var
cache
=
KiviiContext
.
GetCacheClient
();
var
cache
=
KiviiContext
.
GetCacheClient
();
var
cacheKey
=
KiviiContext
.
GetUrnKey
(
$"
{
this
.
GetType
().
FullName
}
_Request_
{
KiviiContext
.
CurrentMember
.
FullName
}
_
{
KiviiContext
.
CurrentMember
.
Kvid
}
"
);
var
cacheKey
=
KiviiContext
.
GetUrnKey
(
$"
{
this
.
GetType
().
FullName
}
_Request_
{
KiviiContext
.
CurrentMember
.
FullName
}
_
{
KiviiContext
.
CurrentMember
.
Kvid
}
"
);
...
@@ -72,6 +71,10 @@ namespace Kivii.Finances.Transforms
...
@@ -72,6 +71,10 @@ namespace Kivii.Finances.Transforms
// 数据库连接初始化(移到外层以确保异常时能正确关闭)
// 数据库连接初始化(移到外层以确保异常时能正确关闭)
var
conn
=
KiviiContext
.
GetOpenedDbConnection
<
Invoice
>();
var
conn
=
KiviiContext
.
GetOpenedDbConnection
<
Invoice
>();
var
applyKvids
=
Items
.
ConvertAll
(
o
=>
o
.
ApplyKvid
).
Distinct
().
ToList
();
var
applys
=
conn
.
SelectByIds
<
InvoiceApply
>(
applyKvids
);
var
trans
=
null
as
IDbTransaction
;
var
trans
=
null
as
IDbTransaction
;
var
lockAcquired
=
false
;
var
lockAcquired
=
false
;
var
lockName
=
$"invoice_lock_
{
KiviiContext
.
CurrentMember
.
Kvid
}
"
;
var
lockName
=
$"invoice_lock_
{
KiviiContext
.
CurrentMember
.
Kvid
}
"
;
...
@@ -144,7 +147,7 @@ namespace Kivii.Finances.Transforms
...
@@ -144,7 +147,7 @@ namespace Kivii.Finances.Transforms
var
invoice
=
new
Invoice
();
var
invoice
=
new
Invoice
();
invoice
.
RootKvid
=
invoiceKvid
;
invoice
.
RootKvid
=
invoiceKvid
;
invoice
.
Kvid
=
invoiceKvid
;
invoice
.
Kvid
=
invoiceKvid
;
//invoice.ApplyKvid =
ApplyKvid;
invoice
.
ApplyKvid
=
info
.
ApplyKvid
;
invoice
.
OwnerKvid
=
info
.
OwnerKvid
;
invoice
.
OwnerKvid
=
info
.
OwnerKvid
;
invoice
.
OwnerName
=
info
.
OwnerName
;
invoice
.
OwnerName
=
info
.
OwnerName
;
if
(
invoice
.
OwnerKvid
==
Guid
.
Empty
&&
invoice
.
OwnerName
.
IsNullOrEmpty
())
if
(
invoice
.
OwnerKvid
==
Guid
.
Empty
&&
invoice
.
OwnerName
.
IsNullOrEmpty
())
...
@@ -320,7 +323,21 @@ namespace Kivii.Finances.Transforms
...
@@ -320,7 +323,21 @@ namespace Kivii.Finances.Transforms
// 缓存清理失败仅记录警告
// 缓存清理失败仅记录警告
KiviiContext
.
Logger
.
Warn
(
$"缓存清理失败:
{
cacheEx
.
Message
}
"
);
KiviiContext
.
Logger
.
Warn
(
$"缓存清理失败:
{
cacheEx
.
Message
}
"
);
}
}
if
(!
applys
.
IsNullOrEmpty
())
{
try
{
var
th
=
KiviiContext
.
NewThread
(
"发票申请标记完成"
,
()
=>
{
applys
.
ExcuteCompleted
();
});
th
.
Start
();
}
catch
(
Exception
ex
)
{
throw
ex
;
}
}
return
rtns
;
return
rtns
;
}
}
catch
(
Exception
ex
)
catch
(
Exception
ex
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment