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
c587198b
Commit
c587198b
authored
Apr 23, 2025
by
Neo Turing
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
优化
parent
04819511
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
65 additions
and
54 deletions
+65
-54
InvoiceExtension.cs
Src/Extensions/InvoiceExtension.cs
+65
-54
No files found.
Src/Extensions/InvoiceExtension.cs
View file @
c587198b
...
...
@@ -40,79 +40,90 @@ namespace Kivii.Finances
/// <summary>
/// Payment与Invoice产生关联的方法
/// </summary>
/// <param name="invoices"></param>
/// <param name="payments"></param>
/// <returns></returns>
public
static
List
<
Invoice
>
Correlating
(
this
List
<
Invoice
>
invoices
,
List
<
Payment
>
payments
)
/// <param name="invoices">要关联的发票列表</param>
/// <param name="payments">要关联的支付列表</param>
/// <param name="decimalPrecision">金额计算精度,默认为2</param>
/// <returns>生成的关联发票记录列表</returns>
public
static
List
<
Invoice
>
Correlating
(
this
List
<
Invoice
>
invoices
,
List
<
Payment
>
payments
,
int
decimalPrecision
=
2
)
{
payments
.
ThrowIfNullOrEmpty
(
"要关联的Payments不能为空!"
);
invoices
.
ThrowIfNullOrEmpty
(
"要关联的Invoices不能为空!"
);
(
payments
.
Exists
(
o
=>
o
.
Type
!=
PaymentType
.
Bank
&&
o
.
Type
!=
PaymentType
.
AliPay
&&
o
.
Type
!=
PaymentType
.
Cash
&&
o
.
Type
!=
PaymentType
.
Pos
&&
o
.
Type
!=
PaymentType
.
Split
&&
o
.
Type
!=
PaymentType
.
WeChat
)).
ThrowIfTrue
(
"请选择正确收款进行关联"
);
var
payedTime
=
payments
.
Max
(
o
=>
o
.
OperateTime
);
// 检查货币类型是否一致
var
paymentCurrencies
=
payments
.
Select
(
p
=>
p
.
Currency
).
Distinct
().
ToList
();
var
invoiceCurrencies
=
invoices
.
Select
(
i
=>
i
.
Currency
).
Distinct
().
ToList
();
if
(
paymentCurrencies
.
Count
>
1
||
invoiceCurrencies
.
Count
>
1
)
throw
new
InvalidOperationException
(
"不同货币类型的支付或发票不能同时关联"
);
if
(
paymentCurrencies
.
FirstOrDefault
()
!=
invoiceCurrencies
.
FirstOrDefault
())
throw
new
InvalidOperationException
(
$"支付货币类型(
{
paymentCurrencies
.
FirstOrDefault
()}
)与发票货币类型(
{
invoiceCurrencies
.
FirstOrDefault
()}
)不匹配"
);
var
paymentDateTime
=
payments
.
Max
(
o
=>
o
.
OperateTime
);
var
rtns
=
new
List
<
Invoice
>();
foreach
(
var
payment
in
payments
)
// 使用锁来确保并发安全
lock
(
typeof
(
InvoiceExtension
))
{
//说明已经建立关联关系的payment 跳过
if
(
payment
.
AmountInvoice
>=
payment
.
Amount
)
continue
;
foreach
(
var
invoice
in
invoices
)
foreach
(
var
payment
in
payments
)
{
var
amountLeave
=
payment
.
Amount
-
payment
.
AmountInvoice
;
//可以开票的金额
if
(
amountLeave
<=
0
)
break
;
var
amountCorrelating
=
invoice
.
Amount
-
invoice
.
AmountPayment
;
//要关联的金额
if
(
amountCorrelating
<=
0
)
continue
;
var
amount
=
amountLeave
<=
amountCorrelating
?
amountLeave
:
amountCorrelating
;
//说明已经建立关联关系的payment 跳过
if
(
payment
.
AmountInvoice
>=
payment
.
Amount
)
continue
;
foreach
(
var
invoice
in
invoices
)
{
var
remainingPaymentAmount
=
Math
.
Round
(
payment
.
Amount
-
payment
.
AmountInvoice
,
decimalPrecision
);
//可以开票的金额
if
(
remainingPaymentAmount
<=
0
)
break
;
var
remainingInvoiceAmount
=
Math
.
Round
(
invoice
.
Amount
-
invoice
.
AmountPayment
,
decimalPrecision
);
//要关联的金额
if
(
remainingInvoiceAmount
<=
0
)
continue
;
var
allocatedAmount
=
remainingPaymentAmount
<=
remainingInvoiceAmount
?
remainingPaymentAmount
:
remainingInvoiceAmount
;
allocatedAmount
=
Math
.
Round
(
allocatedAmount
,
decimalPrecision
);
// 确保金额精度一致
invoice
.
PayedTime
=
payed
Time
;
invoice
.
AddOnlyProperties
(
o
=>
o
.
PayedTime
);
invoice
.
AmountPayment
+=
amount
;
invoice
.
AddOnlyProperties
(
o
=>
o
.
AmountPayment
);
invoice
.
PayedTime
=
paymentDate
Time
;
invoice
.
AddOnlyProperties
(
o
=>
o
.
PayedTime
);
invoice
.
AmountPayment
=
Math
.
Round
(
invoice
.
AmountPayment
+
allocatedAmount
,
decimalPrecision
)
;
invoice
.
AddOnlyProperties
(
o
=>
o
.
AmountPayment
);
#
region
建立关联关系
var
relationInvoice
=
new
Invoice
();
relationInvoice
.
PopulateInstance
(
invoice
);
relationInvoice
.
SerialNumber
=
string
.
Empty
;
relationInvoice
.
Kvid
=
Guid
.
NewGuid
();
relationInvoice
.
ParentKvid
=
invoice
.
Kvid
;
#
region
建立关联关系
var
invoicePaymentRelation
=
new
Invoice
();
invoicePaymentRelation
.
PopulateInstance
(
invoice
);
invoicePaymentRelation
.
SerialNumber
=
string
.
Empty
;
invoicePaymentRelation
.
Kvid
=
Guid
.
NewGuid
();
invoicePaymentRelation
.
ParentKvid
=
invoice
.
Kvid
;
relationInvoice
.
BizId
=
payment
.
SerialNumber
;
relationInvoice
.
BizKvid
=
payment
.
RootKvid
;
//记录根的Kvid
relationInvoice
.
BizType
=
typeof
(
Payment
).
FullName
;
invoicePaymentRelation
.
BizId
=
payment
.
SerialNumber
;
invoicePaymentRelation
.
BizKvid
=
payment
.
RootKvid
;
//记录根的Kvid
invoicePaymentRelation
.
BizType
=
typeof
(
Payment
).
FullName
;
relationInvoice
.
Type
=
"Relation"
;
invoicePaymentRelation
.
Type
=
"Relation"
;
relationInvoice
.
PayedTime
=
payed
Time
;
relationInvoice
.
Amount
=
a
mount
;
relationInvoice
.
AmountPayment
=
a
mount
;
//不含税金额
relationInvoice
.
AmountUntaxed
=
Math
.
Round
(
relationInvoice
.
Amount
/
(
1
+
relationInvoice
.
TaxRate
),
2
);
//税
额
relationInvoice
.
AmountTax
=
relationInvoice
.
Amount
-
relationInvoice
.
AmountUntaxed
;
relationInvoice
.
Summary
=
payment
.
PayerName
;
rtns
.
Add
(
relationInvoice
);
#
endregion
invoicePaymentRelation
.
PayedTime
=
paymentDate
Time
;
invoicePaymentRelation
.
Amount
=
allocatedA
mount
;
invoicePaymentRelation
.
AmountPayment
=
allocatedA
mount
;
//不含税金额,统一使用指定精度
invoicePaymentRelation
.
AmountUntaxed
=
Math
.
Round
(
invoicePaymentRelation
.
Amount
/
(
1
+
invoicePaymentRelation
.
TaxRate
),
decimalPrecision
);
//税额,确保税额 + 不含税金额 = 总金
额
invoicePaymentRelation
.
AmountTax
=
Math
.
Round
(
invoicePaymentRelation
.
Amount
-
invoicePaymentRelation
.
AmountUntaxed
,
decimalPrecision
)
;
invoicePaymentRelation
.
Summary
=
payment
.
PayerName
;
rtns
.
Add
(
invoicePaymentRelation
);
#
endregion
payment
.
AmountInvoice
+=
amount
;
if
(
payment
.
InvoiceTime
==
null
)
{
payment
.
InvoiceTime
=
invoice
.
OperateTime
;
payment
.
AddOnlyProperties
(
o
=>
o
.
InvoiceTime
);
}
else
{
if
(
payment
.
InvoiceTime
.
Value
<
invoice
.
OperateTime
)
payment
.
AmountInvoice
=
Math
.
Round
(
payment
.
AmountInvoice
+
allocatedAmount
,
decimalPrecision
);
if
(
payment
.
InvoiceTime
==
null
)
{
payment
.
InvoiceTime
=
invoice
.
OperateTime
;
payment
.
AddOnlyProperties
(
o
=>
o
.
InvoiceTime
);
}
else
{
if
(
payment
.
InvoiceTime
.
Value
<
invoice
.
OperateTime
)
{
payment
.
InvoiceTime
=
invoice
.
OperateTime
;
payment
.
AddOnlyProperties
(
o
=>
o
.
InvoiceTime
);
}
}
}
payment
.
AddOnlyProperties
(
o
=>
o
.
AmountInvoice
);
if
(
payment
.
Metadata
.
IsNullOrEmpty
())
payment
.
Metadata
=
new
Dictionary
<
string
,
string
>();
payment
.
Metadata
[
"InvoiceOperateTime"
]
=
DateTime
.
Now
.
ToString
(
"yyyy-MM-dd HH:mm:ss"
);
//记录关联发票的操作日期
payment
.
AddOnlyProperties
(
o
=>
o
.
Metadata
);
}
if
(
payment
.
Metadata
==
null
)
payment
.
Metadata
=
new
Dictionary
<
string
,
string
>();
payment
.
AddOnlyProperties
(
o
=>
o
.
AmountInvoice
);
if
(
payment
.
Metadata
.
IsNullOrEmpty
())
payment
.
Metadata
=
new
Dictionary
<
string
,
string
>();
payment
.
Metadata
[
"InvoiceOperateTiime"
]
=
DateTime
.
Now
.
ToString
(
"yyyy-MM-dd HH:mm:ss"
);
//记录关联发票的操作日期
payment
.
AddOnlyProperties
(
o
=>
o
.
Metadata
);
}
return
rtns
;
...
...
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