Commit c56bed1e by 陶然

init

parent 71e4d546
......@@ -106,24 +106,14 @@ namespace Kivii.Finances.Entities
/// </summary>
Unsupported = 0,
/// <summary>
///银行账户,可清零或调帐,不用于客户,只用于组织内
/// </summary>
Bank,
/// <summary>
///现金账户,用于收到的现金,只用于组织内,个人业务员使用,不用于客户,如业务员收取现金
/// </summary>
Cash,
/// <summary>
///刷卡账户,用于收到的刷卡,只用于组织内,个人业务员使用
/// </summary>
Pos,
///// <summary>
/////银行账户,可清零或调帐,不用于客户,只用于组织内
///// </summary>
//Bank,
AliPay,
//AliPay,
WeChat,
//WeChat,
/// <summary>
///存款账户,指客户的存款账户,同部门只能拥有一个, 多部门可存在多个账户
......@@ -151,6 +141,16 @@ namespace Kivii.Finances.Entities
Balance,
/// <summary>
///现金账户,用于收到的现金,只用于组织内,个人业务员使用,不用于客户,如业务员收取现金
/// </summary>
Cash,
/// <summary>
///刷卡账户,用于收到的刷卡,只用于组织内,个人业务员使用
/// </summary>
Pos,
/// <summary>
/// 折扣账户,各部门仅有一个,也可所属到个人
/// </summary>
Discount,
......
......@@ -105,6 +105,9 @@ namespace Kivii.Finances.Entities
[IgnoreUpdate]
[StringLength(100), Default("")]
public string SerialNumber { get; set; }
[Ignore]
public List<Settlement> Details { get; set; }
#endregion
#region 金额相关
......@@ -183,11 +186,4 @@ namespace Kivii.Finances.Entities
public string UpdaterName { get; set; }
#endregion
}
public class BillWithSettlements:Bill
{
[Ignore]
public List<Settlement> Settlements { get; set; }
}
}
......@@ -155,10 +155,10 @@ namespace Kivii.Finances.Entities
[DecimalLength(15, 2), Default(0)]
public decimal AmountInvoice { get; set; }
[ApiMember(Description = "已关联金额,关联的收款或者刷卡现金账户金额")]
[InternalSetter]
[DecimalLength(15, 2), Default(0)]
public decimal AmountUsed { get; set; }
//[ApiMember(Description = "已关联金额,关联的收款或者刷卡现金账户金额")]
//[InternalSetter]
//[DecimalLength(15, 2), Default(0)]
//public decimal AmountUsed { get; set; }
[ApiMember(Description = "单位")]
[IgnoreUpdate]
......
......@@ -7,7 +7,12 @@ using System.Threading.Tasks;
namespace Kivii.Finances.Entities
{
[Api(Description = "付款单")]
/// <summary>
/// Pay对象是 Payment与Account之间互相转变的动作
/// 或者Account与Account之间转账
/// 此动作可附带Biz相关内容,比如Settlement
/// </summary>
[Api(Description = "支付")]
[Alias(Configs.TableNamePay)]
public class Pay : EntityWithMetadata, IEntityInAssemblyDb, IEntityHasBiz,
IEntityHasOffset, IEntityHasSummary,
......@@ -39,7 +44,6 @@ namespace Kivii.Finances.Entities
[InternalSetter]
[StringLength(100)]
public string BizType { get; set; }
#endregion
#region 收付双方
......@@ -52,6 +56,14 @@ namespace Kivii.Finances.Entities
[StringLength(100), Required]
public string PayerName { get; set; }
[ApiMember(Description = "付方来源")]
[StringLength(50), Required]
public PayType FromType { get; set; }
[ApiMember(Description = "付方来源Kvid")]
[IgnoreUpdate]
[Required]
public Guid FromKvid { get; set; }
[IgnoreUpdate]
[DefaultEmptyGuid]
......@@ -61,6 +73,15 @@ namespace Kivii.Finances.Entities
[IgnoreUpdate]
[StringLength(100), Required]
public string PayeeName { get; set; }
[ApiMember(Description = "收方来源")]
[StringLength(50), Required]
public PayType ToType { get; set; }
[ApiMember(Description = "收方来源Kvid")]
[IgnoreUpdate]
[Required]
public Guid ToKvid { get; set; }
#endregion
#region 基本信息
......@@ -69,41 +90,32 @@ namespace Kivii.Finances.Entities
[StringLength(100), Default("")]
public string SerialNumber { get; set; }
[ApiMember(Description = "消费类型")]
[ApiMember(Description = "支付类型")]
[StringLength(50), Default("")]
public string Type { get; set; }
//[ApiMember(Description = "付款Kvid")]
//[InternalSetter]
//[DefaultEmptyGuid]
//public Guid PaymentKvid { get; set; }
[ApiMember(Description = "支付日期")]
[InternalSetter]
public DateTime? PayedTime { get; set; }
#endregion
#region 费用相关
/// <summary>
/// 结算金额,结算明细统计
/// </summary>
[ApiMember(Description = "结算金额,结算明细统计")]
[InternalSetter]
[DecimalLength(15, 2), Default(0)]
public decimal AmountSettlement { get; set; }
//[ApiMember(Description = "结算金额,结算明细统计")]
//[InternalSetter]
//[DecimalLength(15, 2), Default(0)]
//public decimal AmountSettlement { get; set; }
[ApiMember(Description = "实付金额,客户实际支付的金额")]
[ApiMember(Description = "发生金额")]
[InternalSetter]
[DecimalLength(15, 2), Default(0)]
public decimal Amount { get; set; }
[ApiMember(Description = "折扣金额,客户实际支付的金额少于结算金额时补齐的金额")]
[ApiMember(Description = "折扣金额,发生金额-实付金额")]
[InternalSetter]
[DecimalLength(15, 2), Default(0)]
public decimal AmountDiscount { get; set; }
[ApiMember(Description = "已付金额,实付金额和折扣金额的和")]
[ApiMember(Description = "实付金额")]
[InternalSetter]
[DecimalLength(15, 2), Default(0)]
public decimal AmountPayment { get; set; }
......
......@@ -63,7 +63,7 @@ namespace Kivii.Finances.Entities
#region 收付双方 Payer付款单位,贷方 Payee收款单位,借方,账号相关
[IgnoreUpdate]
[DefaultEmptyGuid, Required]
[DefaultEmptyGuid]
public Guid PayerKvid { get; set; }
[ApiMember(Description = "付款单位,贷方")]
......@@ -91,7 +91,7 @@ namespace Kivii.Finances.Entities
public string PayerAccountSerialNumber { get; set; }
[IgnoreUpdate]
[DefaultEmptyGuid, Required]
[DefaultEmptyGuid]
public Guid PayeeKvid { get; set; }
[ApiMember(Description = "收款单位,借方")]
......@@ -261,19 +261,14 @@ namespace Kivii.Finances.Entities
WeChat,
/// <summary>
/// 动态拆分,必有Biz,即为用于关联支付Pay业务,子集Pay用于结算,当有Pay冲销则此状态Amount AmountUsed AmountSplited都发生变化
/// </summary>
DynamicSplit,
/// <summary>
/// 刷卡,直接从刷卡内部账户拨款到Payment的类型(区别于Account类型[消费使用],开票申请使用)
/// </summary>
Pos,
/// <summary>
/// 支付,此类型必有Biz,即为动态拆分的子集用于关联具体Settlement业务
/// 动态支付,当收款登记时被用于关联Pay
/// </summary>
Pay,
DynamicPay,
/// <summary>
/// 转账,必有Biz
......
......@@ -95,10 +95,10 @@ namespace Kivii.Finances.Entities
[DecimalLength(15, 2), Default(0)]
public decimal AmountPayment { get; set; }
[ApiMember(Description = "支付Kvid")]
[InternalSetter]
[DefaultEmptyGuid]
public Guid PayKvid { get; set; }
//[ApiMember(Description = "支付Kvid")]
//[InternalSetter]
//[DefaultEmptyGuid]
//public Guid PayKvid { get; set; }
[ApiMember(Description = "单位")]
[IgnoreUpdate]
......
......@@ -23,7 +23,8 @@ namespace Kivii.Finances
public static Account GetBalanceAccount(this CurrencyUnit currency)
{
(currency == CurrencyUnit.Unsupported).ThrowIfTrue("不支持的货币单位,不能查询平衡账户");
var key = KiviiContext.GetUrnKey(currency.ToString());
var key = KiviiContext.GetUrnKey($"{currency}{KiviiContext.CurrentMember.OrganizationKvid}");
//var key = KiviiContext.GetUrnKey(currency.ToString());
//如果包含这个币种,直接返回
if (_balanceAccounts.ContainsKey(key))
{
......@@ -36,7 +37,7 @@ namespace Kivii.Finances
var balanceAccounts = conn.Select<Account>(o => o.Type == AccountType.Balance);
foreach (var account in balanceAccounts)
{
_balanceAccounts[KiviiContext.GetUrnKey(account.Currency.ToString())] = account;
_balanceAccounts[KiviiContext.GetUrnKey($"{currency}{KiviiContext.CurrentMember.OrganizationKvid}")] = account;
}
//如果从数据库中得到了,直接返回
if (_balanceAccounts.ContainsKey(key))
......@@ -44,15 +45,15 @@ namespace Kivii.Finances
return _balanceAccounts[key];
}
//每个币种只有一个平衡帐户,通过自定义的Kvid防止多系统或多线程冲突引起在数据库中创建多个平衡帐户,Kvid的开头为BALANCE的象形写法
var currencyString = ((int)currency).ToString().PadLeft(4, '0');
var balanceKvid = new Guid($"BA1A0CE0-{currencyString}-0000-0000-000000000000");
////每个币种只有一个平衡帐户,通过自定义的Kvid防止多系统或多线程冲突引起在数据库中创建多个平衡帐户,Kvid的开头为BALANCE的象形写法
//var currencyString = ((int)currency).ToString().PadLeft(4, '0');
var balanceKvid = Guid.NewGuid();//new Guid($"BA1A0CE0-{currencyString}-0000-0000-000000000000");
Account rtns = new Account();
rtns.Kvid = balanceKvid;
rtns.Type = AccountType.Balance;
rtns.Currency = currency;
rtns.OwnerKvid = Guid.Empty;
rtns.OwnerName = "K5平台";
rtns.OwnerKvid = KiviiContext.CurrentMember.OrganizationKvid;
rtns.OwnerName = KiviiContext.CurrentMember.OrganizationName;
rtns.Name = "系统平衡帐户";
rtns.SerialNumber = "";
rtns.CreditLine = 0;
......@@ -61,7 +62,7 @@ namespace Kivii.Finances
rtns.Remark = "";
if (conn.Insert(rtns) == 1)
{
_balanceAccounts[KiviiContext.GetUrnKey(rtns.Currency.ToString())] = rtns;
_balanceAccounts[KiviiContext.GetUrnKey($"{rtns.Currency}{KiviiContext.CurrentMember.OrganizationKvid}")] = rtns;
return rtns;
}
throw new Exception("系统创建平衡帐户失败,请联系系统管理员。");
......@@ -105,7 +106,7 @@ namespace Kivii.Finances
rtns.OwnerName = KiviiContext.CurrentMember.DepartmentName;
rtns.Name = $"折扣帐户({rtns.OwnerName})";
rtns.SerialNumber = "";
rtns.CreditLine = 0;
rtns.CreditLine = 10000000000;
rtns.Amount = 0;
rtns.Summary = "";
rtns.Remark = "";
......@@ -215,6 +216,7 @@ namespace Kivii.Finances
}
/// <summary>
/// complate!
/// 新增账户明细
/// </summary>
/// <param name="accountDetail"></param>
......@@ -226,8 +228,8 @@ namespace Kivii.Finances
(accountDetail.Amount == 0).ThrowIfFalse("账户余额不能被赋除0之外的值!");
(accountDetail.AmountPayment <= 0).ThrowIfTrue("账户明细发生金额不能少于0!");
accountDetail.AccountKvid.ThrowIfEmpty("账户Kvid不能为空!");
accountDetail.PayeeAccountKvid.ThrowIfEmpty("收款账户不能为空!");
accountDetail.PayerAccountKvid.ThrowIfEmpty("付款账户不能为空!");
//accountDetail.PayeeAccountKvid.ThrowIfEmpty("收款账户不能为空!");
//accountDetail.PayerAccountKvid.ThrowIfEmpty("付款账户不能为空!");
bool useTransaction = conn == null;//是否启用事务,如果外部未传入conn,启用内部事务
if (conn == null) conn = KiviiContext.GetOpenedDbConnection<AccountDetail>();
......
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;
......
......@@ -49,14 +49,16 @@ namespace Kivii.Finances
if (payment.AmountInvoice >= payment.Amount) continue;
foreach (var invoice in invoices)
{
var amountLeave = payment.Amount - payment.AmountInvoice;//可以开票的金额
if (amountLeave <= 0) break;
var amountCorrelating = invoice.Amount - invoice.AmountPayment;//要关联的金额
if (amountCorrelating <= 0) continue;
var amountLeave = payment.Amount - payment.AmountInvoice;//可以开票的金额
if (amountLeave <= 0) continue;
var amount = amountLeave <= amountCorrelating ? amountLeave : amountCorrelating;
invoice.PayedTime = payedTime;
invoice.AddOnlyProperties(o => o.PayedTime);
invoice.AmountPayment += amount;
invoice.AddOnlyProperties(o => o.AmountPayment);
#region 建立关联关系
var relationInvoice = new Invoice();
......
using Kivii.Finances.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Kivii.Finances
{
public static class InvoiceExtension
{
public static Invoice Offset(this Invoice invoice, string remark)
{
invoice.ThrowIfNull("发票不能为空!");
(invoice.Currency == CurrencyUnit.Unsupported).ThrowIfTrue("不支持的货币单位");
(invoice.OffsetKvid != Guid.Empty).ThrowIfTrue("发票已作废,无需重复操作!");
#region invoice冲账
var newInvoiceKvid = Guid.NewGuid();
invoice.OffsetKvid = newInvoiceKvid;
invoice.AddOnlyProperties(o => o.OffsetKvid);
invoice.Remark = $"{remark}";
invoice.AddOnlyProperties(o => o.Remark);
//新建一个和原来一样的
var offsetInvoice = new Invoice();
offsetInvoice.PopulateWith(invoice);
offsetInvoice.OffsetKvid = invoice.Kvid;//新的冲帐关联用原来的Kvid
offsetInvoice.BizId = string.Empty;
offsetInvoice.BizKvid = Guid.Empty;
offsetInvoice.BizType = string.Empty;
offsetInvoice.Kvid = newInvoiceKvid;
offsetInvoice.RootKvid = newInvoiceKvid;
offsetInvoice.ParentKvid = Guid.Empty;
offsetInvoice.SerialNumber = invoice.SerialNumber.IsNullOrEmpty() ? "" : ("-" + invoice.SerialNumber);
offsetInvoice.Remark = $"{remark}";
offsetInvoice.Amount = 0 - offsetInvoice.Amount;//反向值
offsetInvoice.AmountPayment = 0 - offsetInvoice.AmountPayment;
offsetInvoice.OperateTime = DateTime.Now;
#endregion
return offsetInvoice;
}
}
}
......@@ -11,187 +11,227 @@ namespace Kivii.Finances
public static class PayExtension
{
/// <summary>
/// 使用单笔到账 付款登记
/// complate!
/// 使用到账进行收款登记
/// </summary>
/// <param name="pay"></param>
/// <param name="payment"></param>
/// <param name="payerAccount"></param>
/// <param name="payeeAccount"></param>
/// <returns></returns>
public static Payment Paying(this Pay pay, Payment payment, Account payerAccount, Account payeeAccount, decimal amount = 0)
/// <param name="settlements">要被收款登记的结算列表</param>
/// <param name="payment">用于收款登记的到账</param>
/// <param name="accountPayee">收入账户</param>
/// <param name="pays">生成的pay清单,Biz记录结算信息</param>
/// <param name="accountDetail">生成的账户明细清单</param>
/// <param name="amount">指定的费用,若不指定金额则默认全部</param>
/// <returns>生成用于收款登记的到账子项</returns>
public static Payment Paying(this List<Settlement> settlements, Payment payment, Account accountPayee, out List<Pay> pays, out AccountDetail accountDetail, decimal amount = 0)
{
pay.ThrowIfNull("未传入付款登记信息!");
(pay.AmountPayment >= pay.AmountSettlement).ThrowIfTrue("已完成付款登记,无需重复登记!");
payment.ThrowIfNull("未传入到账付款信息!");
payerAccount.ThrowIfNull("请传入付款账户!");
payeeAccount.ThrowIfNull("请传入收款账户!");
(payment.Currency != pay.Currency).ThrowIfTrue("存在不相符的货币单位!");
settlements.ThrowIfNullOrEmpty("未传入结算信息!");
payment.ThrowIfNull("未传入到账信息!");
accountPayee.ThrowIfNull("未传入指定收款账户!");
(settlements.Exists(o => o.Currency != payment.Currency || o.Currency != accountPayee.Currency)).ThrowIfTrue("存在不相符的货币单位!");
if (payment.Type != PaymentType.Split && payment.Type != PaymentType.Pos && payment.Type != PaymentType.Cash && payment.Type != PaymentType.AliPay && payment.Type != PaymentType.WeChat) throw new Exception("请选择正确的付款方式!");
var amountSettlement = settlements.Sum(o => o.Amount - o.AmountPayment);
if (amount <= 0 || amount > amountSettlement) amount = amountSettlement;
(payment.Amount - payment.AmountUsed < amount).ThrowIfTrue($"付款编号[{payment.SerialNumber}]余额不足!可用余额:{ payment.Amount - payment.AmountUsed}");
if (amount <= 0 || amount > pay.AmountSettlement - pay.AmountPayment) amount = pay.AmountSettlement - pay.AmountPayment;//付款单所需付款的总金额
var amountCanUsed = payment.Amount - payment.AmountUsed;//到账可使用金额
(amountCanUsed < amount).ThrowIfTrue($"付款编号[{payment.SerialNumber}]余额不足!可用余额:{amountCanUsed}");
pay.AmountPayment += amount;
pay.Amount = pay.AmountPayment - pay.AmountDiscount;
pay.PayedTime = payment.OperateTime;
var dynamicSplitPaymentKvid = Guid.NewGuid();
#region 生成DynamicSplit类型的子payment(Biz记录Pay),调用paymentAccept方法 同时对收付账户进行变化
var dynamicPayKvid = Guid.NewGuid();
#region 创建入账Payment
var rtns = new Payment();
rtns.OwnerKvid = payment.OwnerKvid;
rtns.OwnerName = payment.OwnerName;
rtns.Kvid = dynamicSplitPaymentKvid;
rtns.OwnerKvid = KiviiContext.CurrentMember.DepartmentKvid;
rtns.OwnerName = KiviiContext.CurrentMember.DepartmentName;
rtns.SerialNumber = payment.SerialNumber;
rtns.Kvid = dynamicPayKvid;
rtns.RootKvid = payment.RootKvid;
rtns.ParentKvid = payment.Kvid;
rtns.BizId = pay.SerialNumber;
rtns.BizKvid = pay.Kvid;
rtns.BizType = typeof(Pay).FullName;
rtns.Type = PaymentType.DynamicSplit;
//payment直接用于消费 PayerAccount记录Balance
rtns.PayerKvid = payment.PayerKvid;
rtns.Type = PaymentType.DynamicPay;
rtns.BizId = accountPayee.Name;
rtns.BizKvid = accountPayee.Kvid;
rtns.BizType = typeof(Account).FullName;
rtns.PayerName = payment.PayerName;
rtns.PayerAccountKvid = payerAccount.Kvid;
rtns.PayerAccountName = payerAccount.Name;
rtns.PayerAccountOwnerName = payerAccount.OwnerName;
rtns.PayerAccountSerialNumber = payerAccount.SerialNumber;
//Payee为系统内部的默认业务账户收款
rtns.PayeeKvid = payment.PayeeKvid;
rtns.PayeeName = payment.PayeeName;
rtns.PayeeAccountKvid = payeeAccount.Kvid;
rtns.PayeeAccountName = payeeAccount.Name;
rtns.PayeeAccountOwnerName = payeeAccount.OwnerName;
rtns.PayeeAccountSerialNumber = payeeAccount.SerialNumber;
rtns.PayerKvid = payment.PayerKvid;
rtns.PayeeName = accountPayee.Name;
rtns.PayeeKvid = accountPayee.Kvid;
rtns.PayeeAccountName = accountPayee.Name;
rtns.PayeeAccountKvid = accountPayee.Kvid;
rtns.PayeeAccountOwnerName = accountPayee.OwnerName;
rtns.PayeeAccountSerialNumber = accountPayee.SerialNumber;
rtns.Amount = amount;
rtns.AmountSplited = 0;
rtns.AmountUsed = amount;
rtns.AmountSplited = amount;//已消费了,就不能再拆分了 所以已拆分金额要填充上
rtns.Summary = "收款登记";
rtns.OperateTime = DateTime.Now;
rtns.OperatorKvid = KiviiContext.CurrentMember.Kvid;
rtns.OperatorName = KiviiContext.CurrentMember.FullName;
rtns.Currency = pay.Currency;
rtns.OperatorKvid = KiviiContext.CurrentMember.Kvid;
rtns.Currency = payment.Currency;
#endregion
return rtns;
}
#region 收款账户变动
accountDetail = new AccountDetail();
accountDetail.AccountKvid = accountPayee.Kvid;
accountDetail.BizId = payment.SerialNumber;
accountDetail.BizKvid = payment.Kvid;
accountDetail.BizType = typeof(Payment).FullName;
accountDetail.PayerKvid = payment.PayerKvid;
accountDetail.PayerName = payment.PayerName;
accountDetail.PayeeKvid = payment.PayeeKvid;
accountDetail.PayeeName = payment.PayeeName;
accountDetail.PayeeAccountKvid = accountPayee.Kvid;
accountDetail.PayeeAccountName = accountPayee.Name;
accountDetail.PayeeAccountSerialNumber = accountPayee.SerialNumber;
accountDetail.AmountPayment = amount;
accountDetail.Summary = "收款登记";
#endregion
/// <summary>
/// 使用单个账户 付款登记
/// </summary>
/// <param name="pay"></param>
/// <param name="payerAccount"></param>
/// <param name="payeeAccount"></param>
/// <returns></returns>
public static Payment Paying(this Pay pay, Account payerAccount, Account payeeAccount, decimal amount = 0)
pays = new List<Pay>();
foreach (var settlement in settlements)
{
pay.ThrowIfNull("未传入付款登记信息!");
(pay.AmountPayment >= pay.AmountSettlement).ThrowIfTrue("已完成付款登记,无需重复登记!");
payerAccount.ThrowIfNull("请传入付款账户!");
payeeAccount.ThrowIfNull("请传入收款账户!");
(payerAccount.Currency != pay.Currency).ThrowIfTrue("存在不相符的货币单位!");
(payeeAccount.Currency != pay.Currency).ThrowIfTrue("存在不相符的货币单位!");
(payerAccount.Type != AccountType.Deposit && payerAccount.Type != AccountType.Discount).ThrowIfTrue("请选择正确的付款账户!");
if (amount <= 0 || amount > pay.AmountSettlement - pay.AmountPayment) amount = pay.AmountSettlement - pay.AmountPayment;//付款单所需付款的总金额
var amountCanUsed = payerAccount.Amount + payerAccount.CreditLine;//账户可使用金额
(amountCanUsed < amount).ThrowIfTrue($"账户[{payerAccount.Name}]余额不足!可用余额:{amountCanUsed}");
pay.AmountPayment += amount;
pay.Amount = pay.AmountPayment - pay.AmountDiscount;
pay.PayedTime = DateTime.Now;
if (settlement.AmountPayment >= settlement.Amount) continue;
if (amount <= 0) continue;
var currentAmount = amount <= (settlement.Amount - settlement.AmountPayment) ? amount : (settlement.Amount - settlement.AmountPayment);
var dynamicSplitPaymentKvid = Guid.NewGuid();
#region 生成DynamicSplit类型的子payment(Biz记录Pay),调用paymentAccept方法 同时对收付账户进行变化
var rtns = new Payment();
rtns.OwnerKvid = KiviiContext.CurrentMember.DepartmentKvid;
rtns.OwnerName = KiviiContext.CurrentMember.DepartmentName;
rtns.Kvid = dynamicSplitPaymentKvid;
rtns.RootKvid = dynamicSplitPaymentKvid;
rtns.ParentKvid = Guid.Empty;
rtns.BizId = pay.SerialNumber;
rtns.BizKvid = pay.Kvid;
rtns.BizType = typeof(Pay).FullName;
rtns.Type = PaymentType.DynamicSplit;
//payment直接用于消费 PayerAccount记录Balance
rtns.PayerKvid = pay.PayerKvid;
rtns.PayerName = pay.PayerName;
rtns.PayerAccountKvid = payerAccount.Kvid;
rtns.PayerAccountName = payerAccount.Name;
rtns.PayerAccountOwnerName = payerAccount.OwnerName;
rtns.PayerAccountSerialNumber = payerAccount.SerialNumber;
//Payee为系统内部的默认业务账户收款
rtns.PayeeKvid = pay.PayeeKvid;
rtns.PayeeName = pay.PayeeName;
rtns.PayeeAccountKvid = payeeAccount.Kvid;
rtns.PayeeAccountName = payeeAccount.Name;
rtns.PayeeAccountOwnerName = payeeAccount.OwnerName;
rtns.PayeeAccountSerialNumber = payeeAccount.SerialNumber;
rtns.Amount = amount;
rtns.AmountUsed = amount;
rtns.AmountSplited = amount;//已消费了,就不能再拆分了 所以已拆分金额要填充上
var pay = new Pay();
pay.BizId = settlement.SerialNumber;
pay.BizKvid = settlement.Kvid;
pay.BizType = typeof(Settlement).FullName;
pay.OwnerKvid = KiviiContext.CurrentMember.DepartmentKvid;
pay.OwnerName = KiviiContext.CurrentMember.DepartmentName;
pay.PayerKvid = rtns.PayerKvid;
pay.PayerName = rtns.PayerName;
pay.FromKvid = rtns.Kvid;
pay.FromType = PayType.Payment;
pay.PayeeKvid = accountPayee.Kvid;
pay.PayeeName = accountPayee.Name;
pay.ToKvid = accountPayee.Kvid;
pay.ToType = PayType.Account;
pay.Type = "DynamicPay";
pay.PayedTime = DateTime.Now;
pay.Amount = currentAmount;
pay.AmountPayment = currentAmount;
pay.AmountDiscount = 0;
pay.Currency = rtns.Currency;
pay.OperateTime = DateTime.Now;
pay.OperatorName = KiviiContext.CurrentMember.FullName;
pay.OperatorKvid = KiviiContext.CurrentMember.Kvid;
pays.Add(pay);
rtns.OperateTime = DateTime.Now;
rtns.OperatorKvid = KiviiContext.CurrentMember.Kvid;
rtns.OperatorName = KiviiContext.CurrentMember.FullName;
rtns.Currency = pay.Currency;
#endregion
settlement.AmountPayment += currentAmount;
settlement.AddOnlyProperties(o => o.AmountPayment);
amount -= currentAmount;
}
return rtns;
}
/// <summary>
/// 付款登记折扣金额记录
/// complate!
/// 使用账户进行收款登记
/// </summary>
/// <param name="pay"></param>
/// <param name="discountAccount"></param>
/// <param name="amount"></param>
/// <param name="remark"></param>
/// <returns></returns>
public static Discount Discount(this Pay pay, Account discountAccount, decimal amount, string remark)
/// <param name="settlements">要被收款登记的结算列表</param>
/// <param name="accountPayer">用于收款登记的账户</param>
/// <param name="accountPayee">收入账户</param>
/// <param name="pays">生成的pay清单,Biz记录结算信息</param>
/// <param name="amount">指定的费用,若不指定金额则默认全部</param>
/// <returns>生成的账户明细清单</returns>
public static List<AccountDetail> Paying(this List<Settlement> settlements, Account accountPayer, Account accountPayee, out List<Pay> pays, decimal amount = 0)
{
pay.ThrowIfNull("未传入付款登记信息!");
discountAccount.ThrowIfNull("请传入收款账户!");
(discountAccount.Type != AccountType.Discount).ThrowIfTrue("请选择正确的折扣账户!");
(discountAccount.Currency != pay.Currency).ThrowIfTrue("存在不相符的货币单位!");
(amount <= 0).ThrowIfTrue("抹零抵扣金额不能少于0!");
(amount > pay.AmountSettlement - pay.AmountPayment).ThrowIfTrue("折扣金额超过付款登记金额!");
pay.AmountPayment += amount;
pay.AmountDiscount = amount;
pay.Amount = pay.AmountPayment - pay.AmountDiscount;
pay.Remark = remark;
#region 记录折扣抹零操作
var rtns = new Discount();
rtns.OwnerKvid = KiviiContext.CurrentMember.DepartmentKvid;
rtns.OwnerName = KiviiContext.CurrentMember.DepartmentName;
rtns.PayKvid = pay.Kvid;
rtns.AccountKvid = discountAccount.Kvid;
rtns.AccountName = discountAccount.Name;
rtns.AccountSerialNumber = discountAccount.SerialNumber;
rtns.Amount = amount;
rtns.Currency = pay.Currency;
rtns.OperateTime = DateTime.Now;
rtns.OperatorKvid = KiviiContext.CurrentMember.Kvid;
rtns.OperatorName = KiviiContext.CurrentMember.FullName;
rtns.Summary = $"{rtns.OperatorName}{rtns.OperateTime}{pay.PayerName}[{pay.SerialNumber}]进行抹零折扣操作,金额为:{amount} {pay.Currency}";
rtns.Remark = remark;
settlements.ThrowIfNullOrEmpty("未传入结算信息!");
accountPayer.ThrowIfNull("未传入指定付款账户!");
accountPayee.ThrowIfNull("未传入指定收款账户!");
(settlements.Exists(o => o.Currency != accountPayer.Currency || o.Currency != accountPayee.Currency)).ThrowIfTrue("存在不相符的货币单位!");
(accountPayer.Type != AccountType.Deposit && accountPayer.Type != AccountType.Discount).ThrowIfTrue("请选择正确的付款账户!");
var amountSettlement = settlements.Sum(o => o.Amount - o.AmountPayment);
if (amount <= 0 || amount > amountSettlement) amount = amountSettlement;
(accountPayer.Amount + accountPayer.CreditLine < amount).ThrowIfTrue($"账户[{accountPayer.Name}]余额不足!可用余额:{accountPayer.Amount + accountPayer.CreditLine}");
var rtns = new List<AccountDetail>();
#region 收款账户变动
var payeeDetail = new AccountDetail();
payeeDetail.AccountKvid = accountPayee.Kvid;
payeeDetail.BizId = accountPayee.SerialNumber;
payeeDetail.BizKvid = accountPayee.Kvid;
payeeDetail.BizType = typeof(Account).FullName;
payeeDetail.PayerKvid = accountPayer.Kvid;
payeeDetail.PayerName = accountPayer.Name;
payeeDetail.PayerAccountKvid = accountPayer.Kvid;
payeeDetail.PayerAccountName = accountPayer.Name;
payeeDetail.PayerAccountSerialNumber = accountPayer.SerialNumber;
payeeDetail.PayeeKvid = accountPayee.Kvid;
payeeDetail.PayeeName = accountPayee.Name;
payeeDetail.PayeeAccountKvid = accountPayee.Kvid;
payeeDetail.PayeeAccountName = accountPayee.Name;
payeeDetail.PayeeAccountSerialNumber = accountPayee.SerialNumber;
payeeDetail.AmountPayment = amount;
payeeDetail.Summary = "收款登记";
rtns.Add(payeeDetail);
var payerDetail = new AccountDetail();
payerDetail.AccountKvid = accountPayer.Kvid;
payerDetail.BizId = accountPayee.SerialNumber;
payerDetail.BizKvid = accountPayee.Kvid;
payerDetail.BizType = typeof(Account).FullName;
payerDetail.PayerKvid = accountPayer.Kvid;
payerDetail.PayerName = accountPayer.Name;
payerDetail.PayerAccountKvid = accountPayer.Kvid;
payerDetail.PayerAccountName = accountPayer.Name;
payerDetail.PayerAccountSerialNumber = accountPayer.SerialNumber;
payerDetail.PayeeKvid = accountPayee.Kvid;
payerDetail.PayeeName = accountPayee.Name;
payerDetail.PayeeAccountKvid = accountPayee.Kvid;
payerDetail.PayeeAccountName = accountPayee.Name;
payerDetail.PayeeAccountSerialNumber = accountPayee.SerialNumber;
payerDetail.AmountPayment = amount;
payerDetail.Summary = "收款登记";
rtns.Add(payerDetail);
#endregion
pays = new List<Pay>();
foreach (var settlement in settlements)
{
if (settlement.AmountPayment >= settlement.Amount) continue;
if (amount <= 0) continue;
var currentAmount = amount <= (settlement.Amount - settlement.AmountPayment) ? amount : (settlement.Amount - settlement.AmountPayment);
var pay = new Pay();
pay.BizId = settlement.SerialNumber;
pay.BizKvid = settlement.Kvid;
pay.BizType = typeof(Settlement).FullName;
pay.OwnerKvid = KiviiContext.CurrentMember.DepartmentKvid;
pay.OwnerName = KiviiContext.CurrentMember.DepartmentName;
pay.PayerKvid = accountPayer.Kvid;
pay.PayerName = accountPayer.Name;
pay.FromKvid = accountPayer.Kvid;
pay.FromType = PayType.Account;
pay.PayeeKvid = accountPayee.Kvid;
pay.PayeeName = accountPayee.Name;
pay.ToKvid = accountPayee.Kvid;
pay.ToType = PayType.Account;
pay.Type = "DynamicPay";
pay.PayedTime = DateTime.Now;
pay.Amount = currentAmount;
if (accountPayer.Type == AccountType.Discount)//要是 折扣账户 则记录到AmountDiscount
{
pay.AmountPayment = 0;
pay.AmountDiscount = currentAmount;
}
else
{
pay.AmountPayment = currentAmount;
pay.AmountDiscount = 0;
}
pay.Currency = accountPayer.Currency;
pay.OperateTime = DateTime.Now;
pay.OperatorName = KiviiContext.CurrentMember.FullName;
pay.OperatorKvid = KiviiContext.CurrentMember.Kvid;
pays.Add(pay);
settlement.AmountPayment += currentAmount;
settlement.AddOnlyProperties(o => o.AmountPayment);
amount -= currentAmount;
}
return rtns;
}
/// <summary>
/// complate!
/// 作废
/// </summary>
/// <param name="pay"></param>
......@@ -200,10 +240,10 @@ namespace Kivii.Finances
public static Pay Offset(this Pay pay, string remark)
{
pay.ThrowIfNull("付款记录不能为空!");
(pay.Currency == CurrencyUnit.Unsupported).ThrowIfTrue("不支持的货币单位");
(pay.OffsetKvid != Guid.Empty).ThrowIfTrue("收项已冲账");
(pay.Currency == CurrencyUnit.Unsupported).ThrowIfTrue("不支持的货币单位");
#region payment冲账
#region pay冲账
var newPayKvid = Guid.NewGuid();
pay.OffsetKvid = newPayKvid;
pay.AddOnlyProperties(o => o.OffsetKvid);
......@@ -219,11 +259,52 @@ namespace Kivii.Finances
offsetPay.Remark = $"{remark}";
offsetPay.AmountDiscount = 0 - offsetPay.AmountDiscount;
offsetPay.AmountPayment = 0 - offsetPay.AmountPayment;
offsetPay.AmountSettlement = 0 - offsetPay.AmountSettlement;
offsetPay.Amount = 0 - offsetPay.Amount;//反向值
#endregion
return offsetPay;
}
///// <summary>
///// 付款登记折扣金额记录
///// </summary>
///// <param name="pay"></param>
///// <param name="discountAccount"></param>
///// <param name="amount"></param>
///// <param name="remark"></param>
///// <returns></returns>
//public static Discount Discount(this Pay pay, Account discountAccount, decimal amount, string remark)
//{
// pay.ThrowIfNull("未传入付款登记信息!");
// discountAccount.ThrowIfNull("请传入收款账户!");
// (discountAccount.Type != AccountType.Discount).ThrowIfTrue("请选择正确的折扣账户!");
// (discountAccount.Currency != pay.Currency).ThrowIfTrue("存在不相符的货币单位!");
// (amount <= 0).ThrowIfTrue("抹零抵扣金额不能少于0!");
// (amount > pay.AmountSettlement - pay.AmountPayment).ThrowIfTrue("折扣金额超过付款登记金额!");
// pay.AmountPayment += amount;
// pay.AmountDiscount = amount;
// pay.Amount = pay.AmountPayment - pay.AmountDiscount;
// pay.Remark = remark;
// #region 记录折扣抹零操作
// var rtns = new Discount();
// rtns.OwnerKvid = KiviiContext.CurrentMember.DepartmentKvid;
// rtns.OwnerName = KiviiContext.CurrentMember.DepartmentName;
// rtns.PayKvid = pay.Kvid;
// rtns.AccountKvid = discountAccount.Kvid;
// rtns.AccountName = discountAccount.Name;
// rtns.AccountSerialNumber = discountAccount.SerialNumber;
// rtns.Amount = amount;
// rtns.Currency = pay.Currency;
// rtns.OperateTime = DateTime.Now;
// rtns.OperatorKvid = KiviiContext.CurrentMember.Kvid;
// rtns.OperatorName = KiviiContext.CurrentMember.FullName;
// rtns.Summary = $"{rtns.OperatorName}于{rtns.OperateTime} 对{pay.PayerName}[{pay.SerialNumber}]进行抹零折扣操作,金额为:{amount} {pay.Currency}";
// rtns.Remark = remark;
// #endregion
// return rtns;
//}
}
}
......@@ -12,6 +12,7 @@ namespace Kivii.Finances
public static class PaymentExtension
{
/// <summary>
/// complate!
/// 获取子付款记录的流水号
/// </summary>
/// <param name="payment"></param>
......@@ -30,14 +31,196 @@ namespace Kivii.Finances
}
/// <summary>
/// complate!
/// 接受一个从系统外来的新付款记录
/// </summary>
/// <param name="payment"></param>
/// <param name="conn"></param>
/// <returns></returns>
public static AccountDetail Accept(this Payment payment, out Pay pay)
{
payment.ThrowIfNull("付款记录不能为空!");
(payment.Currency == CurrencyUnit.Unsupported).ThrowIfTrue("不支持的货币单位");
(payment.PayerAccountKvid == Guid.Empty && payment.PayeeAccountKvid == Guid.Empty).ThrowIfTrue("收付款账户不能同时为空!");
(payment.PayerAccountKvid != Guid.Empty && payment.PayeeAccountKvid != Guid.Empty).ThrowIfTrue("收付款账户不能同时指定!");
(payment.Amount <= 0).ThrowIfTrue("付款记录发生金额不能少于0!");
(payment.AmountInvoice == 0).ThrowIfFalse("付款记录开票金额不为0!");
(payment.AmountUsed == 0).ThrowIfFalse("付款记录使用金额不为0!");
(payment.Type != PaymentType.Cash && payment.Type != PaymentType.Pos && payment.Type != PaymentType.Bank).ThrowIfTrue("仅支持接受现金刷卡或者银行流水记录");
if (payment.Type == PaymentType.Bank) (payment.AmountSplited != 0).ThrowIfTrue("付款记录拆分不为0!");
else (payment.AmountSplited != payment.Amount).ThrowIfTrue("现金刷卡拆分金额错误!");
if (payment.ParentKvid != Guid.Empty) payment.ParentKvid = Guid.Empty;
if (payment.OffsetKvid != Guid.Empty) payment.OffsetKvid = Guid.Empty;
if (payment.Kvid == Guid.Empty) payment.Kvid = Guid.NewGuid();
if (payment.RootKvid != payment.Kvid) payment.RootKvid = payment.Kvid;
#region 付款账户变动
var rtns = new AccountDetail();
rtns.AccountKvid = payment.PayerAccountKvid;
rtns.BizId = payment.SerialNumber;
rtns.BizKvid = payment.Kvid;
rtns.BizType = typeof(Payment).FullName;
rtns.PayerKvid = payment.PayerKvid;
rtns.PayerName = payment.PayerName;
rtns.PayerAccountKvid = payment.PayerAccountKvid;
rtns.PayerAccountName = payment.PayerAccountName;
rtns.PayerAccountSerialNumber = payment.PayerAccountSerialNumber;
rtns.PayeeKvid = payment.PayeeKvid;
rtns.PayeeName = payment.PayeeName;
rtns.PayeeAccountKvid = Guid.Empty;//接受外部的钱到payment,所以收款账户为空
rtns.PayeeAccountName = payment.PayeeAccountName;
rtns.PayeeAccountSerialNumber = payment.PayeeAccountSerialNumber;
rtns.AmountPayment = payment.Amount;
rtns.Summary = payment.Summary;
rtns.Summary = payment.Summary;
rtns.Remark = payment.Remark;
#endregion
pay = new Pay();
pay.OwnerKvid = KiviiContext.CurrentMember.DepartmentKvid;
pay.OwnerName = KiviiContext.CurrentMember.DepartmentName;
pay.PayerKvid = payment.PayerKvid;
pay.PayerName = payment.PayerName;
pay.FromType = PayType.Account;//付款来源记录 是账户还是Payment
pay.FromKvid = payment.PayerAccountKvid;
pay.PayeeKvid = payment.PayeeKvid;
pay.PayeeName = payment.PayeeName;
pay.ToType = PayType.Payment;//收款来源记录
pay.ToKvid = payment.Kvid;
pay.Type = "Accept";
pay.PayedTime = DateTime.Now;
pay.Amount = payment.Amount;
pay.AmountPayment = pay.Amount;
pay.AmountDiscount = 0;
pay.Currency = payment.Currency;
pay.OperateTime = DateTime.Now;
pay.OperatorName = KiviiContext.CurrentMember.FullName;
pay.OperatorKvid = KiviiContext.CurrentMember.Kvid;
return rtns;
}
/// <summary>
/// complate!
/// 到账转账至账户
/// </summary>
/// <param name="payment"></param>
/// <param name="accountPayee"></param>
/// <param name="amount"></param>
/// <param name="remark"></param>
/// <param name="pay"></param>
/// <param name="accountDetail"></param>
/// <returns></returns>
public static Payment Transfer(this Payment payment, Account accountPayee, decimal amount, string remark, out Pay pay, out AccountDetail accountDetail)
{
payment.ThrowIfNull("到账不能为空!");
accountPayee.ThrowIfNull("账户不能为空!");
(amount <= 0).ThrowIfTrue("入账金额不能小于等0!");
(payment.OffsetKvid != Guid.Empty).ThrowIfTrue("此项已冲账!");
if (payment.Amount - payment.AmountUsed < amount) throw new Exception($"此到账可使用金额不足,仅剩:{payment.Amount - payment.AmountUsed}元");
(payment.Currency != accountPayee.Currency).ThrowIfTrue("账户的货币单位不一致!");
var transferPaymentKvid = Guid.NewGuid();
#region 创建入账Payment
var rtns = new Payment();
rtns.OwnerKvid = KiviiContext.CurrentMember.DepartmentKvid;
rtns.OwnerName = KiviiContext.CurrentMember.DepartmentName;
rtns.Kvid = transferPaymentKvid;
rtns.SerialNumber = payment.SerialNumber;
rtns.RootKvid = payment.RootKvid;
rtns.ParentKvid = payment.Kvid;
rtns.Type = PaymentType.Transfer;
rtns.BizId = accountPayee.Name;
rtns.BizKvid = accountPayee.Kvid;
rtns.BizType = typeof(Account).FullName;
rtns.PayerName = payment.PayerName;
rtns.PayerKvid = payment.PayerKvid;
//rtns.PayerAccountName = accountPayer.Name;
//rtns.PayerAccountKvid = accountPayer.Kvid;
//rtns.PayerAccountOwnerName = accountPayer.OwnerName;
//rtns.PayerAccountSerialNumber = accountPayer.SerialNumber;
rtns.PayeeName = accountPayee.Name;
rtns.PayeeKvid = accountPayee.Kvid;
rtns.PayeeAccountName = accountPayee.Name;
rtns.PayeeAccountKvid = accountPayee.Kvid;
rtns.PayeeAccountOwnerName = accountPayee.OwnerName;
rtns.PayeeAccountSerialNumber = accountPayee.SerialNumber;
rtns.Amount = amount;
rtns.AmountSplited = 0;
rtns.AmountUsed = amount;
rtns.OperateTime = DateTime.Now;
rtns.OperatorName = KiviiContext.CurrentMember.FullName;
rtns.OperatorKvid = KiviiContext.CurrentMember.Kvid;
rtns.Currency = payment.Currency;
rtns.Summary = $"{remark}";
rtns.Remark = $"{remark}";
#endregion
//此处不更新父级AmountUsed,因为在事务中 调用RecalculateAmountUsed方法即可
//payment.AmountUsed += amount;
//payment.AddOnlyProperties(o => o.AmountSplited);
#region 收款账户变动
accountDetail = new AccountDetail();
accountDetail.AccountKvid = accountPayee.Kvid;
accountDetail.BizId = payment.SerialNumber;
accountDetail.BizKvid = payment.Kvid;
accountDetail.BizType = typeof(Payment).FullName;
accountDetail.PayerKvid = payment.PayerKvid;
accountDetail.PayerName = payment.PayerName;
//rtns.PayerAccountKvid = payerAccount.Kvid;
//rtns.PayerAccountName = payerAccount.Name;
//rtns.PayerAccountSerialNumber = payerAccount.SerialNumber;
accountDetail.PayeeKvid = payment.PayeeKvid;
accountDetail.PayeeName = payment.PayeeName;
accountDetail.PayeeAccountKvid = accountPayee.Kvid;
accountDetail.PayeeAccountName = accountPayee.Name;
accountDetail.PayeeAccountSerialNumber = accountPayee.SerialNumber;
accountDetail.AmountPayment = amount;
accountDetail.Summary = payment.Summary;
accountDetail.Remark = remark;
#endregion
pay = new Pay();
pay.OwnerKvid = KiviiContext.CurrentMember.DepartmentKvid;
pay.OwnerName = KiviiContext.CurrentMember.DepartmentName;
pay.PayerKvid = rtns.PayerKvid;
pay.PayerName = rtns.PayerName;
pay.FromKvid = rtns.Kvid;
pay.FromType = PayType.Payment;
pay.PayeeKvid = accountPayee.Kvid;
pay.PayeeName = accountPayee.Name;
pay.ToKvid = accountPayee.Kvid;
pay.ToType = PayType.Account;
pay.Type = "Transfer";
pay.PayedTime = DateTime.Now;
pay.Amount = rtns.Amount;
pay.AmountPayment = pay.Amount;
pay.AmountDiscount = 0;
pay.Currency = rtns.Currency;
pay.OperateTime = DateTime.Now;
pay.OperatorName = KiviiContext.CurrentMember.FullName;
pay.OperatorKvid = KiviiContext.CurrentMember.Kvid;
return rtns;
}
/// <summary>
/// complate!
/// 重新计算Payment的 AmountUsed
/// </summary>
/// <param name="payment"></param>
/// <param name="conn"></param>
/// <returns></returns>
public static Payment RecalculateAmountUsed(this Payment payment,IDbConnection conn = null)
public static Payment RecalculateAmountUsed(this Payment payment, IDbConnection conn = null)
{
payment.ThrowIfNull("要更新的付款记录不能为空!");
if (payment.Type == PaymentType.Unsupported || payment.Type == PaymentType.Transfer || payment.Type == PaymentType.DynamicPay) throw new Exception("不支持的类型!");
bool useTransaction = conn == null;//是否启用事务,如果外部未传入conn,启用内部事务
if (conn == null)
......@@ -73,29 +256,39 @@ namespace Kivii.Finances
}
/// <summary>
/// 重新计算Payment的 AmountInvoice
/// 只针对Bank等根级Payment
/// complate!
/// 重新计算Payment的 AmountSplit
/// </summary>
/// <param name="payment"></param>
/// <param name="conn"></param>
/// <returns></returns>
public static Payment RecalculateAmountInvoice(this Payment payment, IDbConnection conn = null)
public static Payment RecalculateAmountSplit(this Payment payment, IDbConnection conn = null)
{
payment.ThrowIfNull("要更新的付款记录不能为空!");
(payment.OffsetKvid != Guid.Empty).ThrowIfTrue("此到账已作废 无法重新计算开票金额");
(payment.RootKvid != payment.Kvid).ThrowIfTrue("不支持的类型");
(payment.Type != PaymentType.Bank).ThrowIfTrue("不支持的类型");
bool useTransaction = conn == null;//是否启用事务,如果外部未传入conn,启用内部事务
if (conn == null) conn = KiviiContext.GetOpenedDbConnection<Payment>();
if (conn == null)
{
conn = KiviiContext.GetOpenedDbConnection<Payment>();
}
var amountInvoiced = conn.Scalar<Payment, decimal>(o => Sql.Sum(o.AmountInvoice), p => p.Type == PaymentType.Split && p.ParentKvid == payment.Kvid && p.OffsetKvid == Guid.Empty);
//var amountInvoiced = conn.Scalar<Payment, decimal>(o => Sql.Sum(o.AmountInvoice), p => p.ParentKvid == payment.Kvid && p.OffsetKvid == Guid.Empty);
var amountSplit = conn.Scalar<Payment, decimal>(o => Sql.Sum(o.Amount), p => p.ParentKvid == payment.Kvid && p.OffsetKvid == Guid.Empty);
Payment parentPayment = null;
if (payment.ParentKvid != Guid.Empty) parentPayment = conn.SingleById<Payment>(payment.ParentKvid);
IDbTransaction trans = null;//事务,如果外部来了Connection,不生成事务
if (useTransaction) trans = conn.OpenTransaction();
try
{
payment.AmountInvoice = amountInvoiced;
payment.AddOnlyProperties(o => o.AmountInvoice);
if (payment.OffsetKvid == Guid.Empty)
{
//payment.AmountInvoice = amountInvoiced;
//payment.AddOnlyProperties(o => o.AmountInvoice);
payment.AmountSplited = amountSplit;
payment.AddOnlyProperties(o => o.AmountSplited);
conn.UpdateOnly(payment);
}
if (parentPayment != null) parentPayment.RecalculateAmountSplit(conn);
trans?.Commit();
return payment;
}
......@@ -107,87 +300,40 @@ namespace Kivii.Finances
}
/// <summary>
/// 接受一个从系统外来的新付款记录,收付款账户中增加和减小
/// complate!
/// 到账冲账,此方法不做业务判断,传过来的Payment均可Offset,除已经冲账过的
/// </summary>
/// <param name="payment"></param>
/// <param name="conn"></param>
/// <param name="remark"></param>
/// <returns></returns>
public static List<AccountDetail> Accept(this Payment payment)
public static Payment Offset(this Payment payment, string remark)
{
payment.ThrowIfNull("付款记录不能为空!");
(payment.Currency == CurrencyUnit.Unsupported).ThrowIfTrue("不支持的货币单位");
(payment.PayerAccountKvid == Guid.Empty).ThrowIfTrue("付款账户不能为空!");
(payment.PayeeAccountKvid == Guid.Empty).ThrowIfTrue("收款账户不能为空!");
(payment.Amount <= 0).ThrowIfTrue("付款记录发生金额不能少于0!");
(payment.AmountInvoice == 0).ThrowIfFalse("付款记录开票金额不为0!");
(payment.AmountUsed == 0).ThrowIfFalse("付款记录使用金额不为0!");
(payment.Type != PaymentType.Cash && payment.Type != PaymentType.Pos && payment.Type != PaymentType.Bank).ThrowIfTrue("仅支持接受现金刷卡或者银行流水记录");
if (payment.Type == PaymentType.Bank) (payment.AmountSplited != 0).ThrowIfTrue("付款记录拆分不为0!");
else (payment.AmountSplited != payment.Amount).ThrowIfTrue("现金刷卡拆分金额错误!");
if (payment.ParentKvid != Guid.Empty) payment.ParentKvid = Guid.Empty;
if (payment.OffsetKvid != Guid.Empty) payment.OffsetKvid = Guid.Empty;
if (payment.Kvid == Guid.Empty) payment.Kvid = Guid.NewGuid();
if (payment.RootKvid != payment.Kvid) payment.RootKvid = payment.Kvid;
var rtns = new List<AccountDetail>();
#region 付款账户变动
var payerAccountDetail = new AccountDetail();
payerAccountDetail.AccountKvid = payment.PayerAccountKvid;
payerAccountDetail.BizId = payment.SerialNumber;
payerAccountDetail.BizKvid = payment.Kvid;
payerAccountDetail.BizType = typeof(Payment).FullName;
payerAccountDetail.PayerKvid = payment.PayerKvid;
payerAccountDetail.PayerName = payment.PayerName;
payerAccountDetail.PayerAccountKvid = payment.PayerAccountKvid;
payerAccountDetail.PayerAccountName = payment.PayerAccountName;
payerAccountDetail.PayerAccountSerialNumber = payment.PayerAccountSerialNumber;
payerAccountDetail.PayeeKvid = payment.PayeeKvid;
payerAccountDetail.PayeeName = payment.PayeeName;
payerAccountDetail.PayeeAccountKvid = payment.PayeeAccountKvid;
payerAccountDetail.PayeeAccountName = payment.PayeeAccountName;
payerAccountDetail.PayeeAccountSerialNumber = payment.PayeeAccountSerialNumber;
payerAccountDetail.AmountPayment = payment.Amount;
payerAccountDetail.Summary = payment.Summary;
payerAccountDetail.Summary = payment.Summary;
payerAccountDetail.Remark = payment.Remark;
rtns.Add(payerAccountDetail);
#endregion
#region 收款账户变动
var payeeAccountDetail = new AccountDetail();
payeeAccountDetail.AccountKvid = payment.PayeeAccountKvid;
payeeAccountDetail.BizId = payment.SerialNumber;
payeeAccountDetail.BizKvid = payment.Kvid;
payeeAccountDetail.BizType = typeof(Payment).FullName;
payeeAccountDetail.PayerKvid = payment.PayerKvid;
payeeAccountDetail.PayerName = payment.PayerName;
payeeAccountDetail.PayerAccountKvid = payment.PayerAccountKvid;
payeeAccountDetail.PayerAccountName = payment.PayerAccountName;
payeeAccountDetail.PayerAccountSerialNumber = payment.PayerAccountSerialNumber;
payeeAccountDetail.PayeeKvid = payment.PayeeKvid;
payeeAccountDetail.PayeeName = payment.PayeeName;
payeeAccountDetail.PayeeAccountKvid = payment.PayeeAccountKvid;
payeeAccountDetail.PayeeAccountName = payment.PayeeAccountName;
payeeAccountDetail.PayeeAccountSerialNumber = payment.PayeeAccountSerialNumber;
(payment.OffsetKvid != Guid.Empty).ThrowIfTrue("收项已冲账");
payeeAccountDetail.AmountPayment = payment.Amount;
#region payment冲账
var newPaymentKvid = Guid.NewGuid();
payment.OffsetKvid = newPaymentKvid;
payment.AddOnlyProperties(o => o.OffsetKvid);
payment.Remark = $"{remark}";
payment.AddOnlyProperties(o => o.Remark);
payeeAccountDetail.Summary = payment.Summary;
payeeAccountDetail.Summary = payment.Summary;
payeeAccountDetail.Remark = payment.Remark;
rtns.Add(payeeAccountDetail);
//新建一个和原来一样的
var offsetPayment = new Payment();
offsetPayment.PopulateWith(payment);
offsetPayment.OffsetKvid = payment.Kvid;//新的冲帐关联用原来的Kvid
offsetPayment.Kvid = newPaymentKvid;
offsetPayment.SerialNumber = payment.SerialNumber.IsNullOrEmpty() ? "" : ("-" + payment.SerialNumber);
offsetPayment.Remark = $"{remark}";
offsetPayment.Amount = 0 - offsetPayment.Amount;//反向值
#endregion
return rtns;
return offsetPayment;
}
/// <summary>
/// complate!
/// 到账拆分,并且更新原payment.AmountSplit字段
/// </summary>
/// <param name="payment"></param>
......@@ -210,13 +356,17 @@ namespace Kivii.Finances
{
if (conn == null) conn = KiviiContext.GetOpenedDbConnection<Payment>();
//查看已经拆分的项目分得的已经开票金额
var existSplits = conn.Select<Payment>(o => o.RootKvid == payment.RootKvid && o.Type == PaymentType.Split && o.OffsetKvid == Guid.Empty);
var existSplits = conn.Select<Payment>(o => o.RootKvid == payment.RootKvid && o.OffsetKvid == Guid.Empty && Sql.In(o.Type, PaymentType.Split, PaymentType.UnBiz, PaymentType.Refund));
if (!existSplits.IsNullOrEmpty())
{
//剩余的开票金额
var remainAmountInvoice = payment.AmountInvoice - existSplits.Sum(o => o.AmountInvoice);
if (remainAmountInvoice > 0) amountInvoice = remainAmountInvoice > amountSplit ? amountSplit : remainAmountInvoice;
}
else
{
amountInvoice = payment.AmountInvoice > amountSplit ? amountSplit : payment.AmountInvoice;
}
}
else amountInvoice = amountSplit;//否则直接记录拆分项完全开票
}
......@@ -249,15 +399,11 @@ namespace Kivii.Finances
//splitPayment.Status = 1;
#endregion
#region 更新主项字段
payment.AmountSplited += amountSplit;
payment.AddOnlyProperties(o => o.AmountSplited);
#endregion
return splitPayment;
}
/// <summary>
/// complate!
/// 非业务收款拆分处理,非业务收款或退款
/// </summary>
/// <param name="payment"></param>
......@@ -265,7 +411,7 @@ namespace Kivii.Finances
/// <param name="ownerKvid"></param>
/// <param name="ownerName"></param>
/// <returns></returns>
public static Payment UnBizSplit(this Payment payment, decimal amountSplit, PaymentType paymentType)
public static Payment UnBizSplit(this Payment payment, decimal amountSplit, PaymentType paymentType, IDbConnection conn = null)
{
payment.ThrowIfNull($"传入payment参数为空");
if (payment.Type != PaymentType.Bank) throw new Exception("非银行到账不可以操作!");
......@@ -274,7 +420,27 @@ namespace Kivii.Finances
if (payment.AmountSplited == payment.Amount) throw new Exception("无剩余收款可操作!");
if (payment.AmountSplited + amountSplit > payment.Amount) throw new Exception("操作金额超出范围!");
if (paymentType != PaymentType.UnBiz && paymentType != PaymentType.Refund) throw new Exception("此方法只支持非业务拆分或退款拆分!");
decimal amountInvoice = 0;
if (payment.AmountInvoice > 0)//如果要拆分的到账已经开过票 就要计算拆分项的开票金额
{
if (payment.AmountInvoice < payment.Amount)//到账的部分进行了开票 就需要计算拆分项的开票金额
{
if (conn == null) conn = KiviiContext.GetOpenedDbConnection<Payment>();
//查看已经拆分的项目分得的已经开票金额
var existSplits = conn.Select<Payment>(o => o.RootKvid == payment.RootKvid && o.OffsetKvid == Guid.Empty && Sql.In(o.Type, PaymentType.Split, PaymentType.UnBiz, PaymentType.Refund));
if (!existSplits.IsNullOrEmpty())
{
//剩余的开票金额
var remainAmountInvoice = payment.AmountInvoice - existSplits.Sum(o => o.AmountInvoice);
if (remainAmountInvoice > 0) amountInvoice = remainAmountInvoice > amountSplit ? amountSplit : remainAmountInvoice;
}
else
{
amountInvoice = payment.AmountInvoice > amountSplit ? amountSplit : payment.AmountInvoice;
}
}
else amountInvoice = amountSplit;//否则直接记录拆分项完全开票
}
#region 新增拆分项目
var splitPayment = new Payment();
splitPayment.PopulateWith(payment);//先从父级中拷贝所有参数
......@@ -295,7 +461,7 @@ namespace Kivii.Finances
splitPayment.Amount = amountSplit;
splitPayment.AmountSplited = 0;
splitPayment.AmountUsed = 0;
splitPayment.AmountInvoice = 0;
splitPayment.AmountInvoice = amountInvoice;
splitPayment.Summary = string.Empty;
splitPayment.Remark = string.Empty;
splitPayment.OperateTime = payment.OperateTime;
......@@ -304,240 +470,41 @@ namespace Kivii.Finances
//splitPayment.Status = 1;
#endregion
#region 更新主项字段
payment.AmountSplited += amountSplit;
payment.AddOnlyProperties(o => o.AmountSplited);
#endregion
return splitPayment;
}
/// <summary>
/// 到账冲账,此方法不做业务判断,传过来的Payment均可Offset,除已经冲账过的
/// complate!
/// 重新计算Payment的 AmountInvoice
/// 只针对Bank等根级Payment
/// </summary>
/// <param name="payment"></param>
/// <param name="remark"></param>
/// <param name="conn"></param>
/// <returns></returns>
public static Payment Offset(this Payment payment, string remark)
public static Payment RecalculateAmountInvoice(this Payment payment, IDbConnection conn = null)
{
payment.ThrowIfNull("付款记录不能为空!");
(payment.Currency == CurrencyUnit.Unsupported).ThrowIfTrue("不支持的货币单位");
(payment.OffsetKvid != Guid.Empty).ThrowIfTrue("收项已冲账");
#region payment冲账
var newPaymentKvid = Guid.NewGuid();
payment.OffsetKvid = newPaymentKvid;
payment.AddOnlyProperties(o => o.OffsetKvid);
payment.Remark = $"{remark}";
payment.AddOnlyProperties(o => o.Remark);
//新建一个和原来一样的
var offsetPayment = new Payment();
offsetPayment.PopulateWith(payment);
offsetPayment.OffsetKvid = payment.Kvid;//新的冲帐关联用原来的Kvid
offsetPayment.Kvid = newPaymentKvid;
offsetPayment.SerialNumber = payment.SerialNumber.IsNullOrEmpty() ? "" : ("-" + payment.SerialNumber);
offsetPayment.Remark = $"{remark}";
offsetPayment.Amount = 0 - offsetPayment.Amount;//反向值
#endregion
return offsetPayment;
}
payment.ThrowIfNull("要更新的付款记录不能为空!");
(payment.OffsetKvid != Guid.Empty).ThrowIfTrue("此到账已作废 无法重新计算开票金额");
(payment.Type != PaymentType.Bank).ThrowIfTrue("不支持的类型");
bool useTransaction = conn == null;//是否启用事务,如果外部未传入conn,启用内部事务
if (conn == null) conn = KiviiContext.GetOpenedDbConnection<Payment>();
/// <summary>
/// 到账转账至账户
/// </summary>
/// <param name="payment"></param>
/// <param name="accountPayee"></param>
/// <param name="accountPayer"></param>
/// <param name="amount"></param>
/// <param name="remark"></param>
/// <returns></returns>
public static Payment Transfer(this Payment payment, Account accountPayee, Account accountPayer, decimal amount, string remark)
var amountInvoiced = conn.Scalar<Payment, decimal>(o => Sql.Sum(o.AmountInvoice), p => p.Type == PaymentType.Split && p.ParentKvid == payment.Kvid && p.OffsetKvid == Guid.Empty);
IDbTransaction trans = null;//事务,如果外部来了Connection,不生成事务
if (useTransaction) trans = conn.OpenTransaction();
try
{
payment.ThrowIfNull("到账不能为空!");
accountPayee.ThrowIfNull("账户不能为空!");
accountPayer.ThrowIfNull("账户不能为空!");
(amount <= 0).ThrowIfTrue("入账金额不能小于等0!");
(payment.OffsetKvid != Guid.Empty).ThrowIfTrue("此项已冲账!");
if (payment.Amount - payment.AmountUsed < amount) throw new Exception($"此到账可使用金额不足,仅剩:{payment.Amount - payment.AmountUsed}元");
(payment.Currency != accountPayee.Currency && accountPayee.Currency != accountPayer.Currency).ThrowIfTrue("账户的货币单位不一致!");
var transferPaymentKvid = Guid.NewGuid();
#region 创建入账Payment
var transferPayment = new Payment();
transferPayment.OwnerKvid = KiviiContext.CurrentMember.DepartmentKvid;
transferPayment.OwnerName = KiviiContext.CurrentMember.DepartmentName;
transferPayment.Kvid = transferPaymentKvid;
transferPayment.RootKvid = payment.RootKvid;
transferPayment.ParentKvid = payment.Kvid;
transferPayment.Type = PaymentType.Transfer;
transferPayment.BizId = accountPayee.Name;
transferPayment.BizKvid = accountPayee.Kvid;
transferPayment.BizType = typeof(Account).FullName;
transferPayment.PayerName = payment.PayerName;
transferPayment.PayerKvid = payment.PayerKvid;
transferPayment.PayerAccountName = accountPayer.Name;
transferPayment.PayerAccountKvid = accountPayer.Kvid;
transferPayment.PayerAccountOwnerName = accountPayer.OwnerName;
transferPayment.PayerAccountSerialNumber = accountPayer.SerialNumber;
transferPayment.PayeeName = accountPayee.Name;
transferPayment.PayeeKvid = accountPayee.Kvid;
transferPayment.PayeeAccountName = accountPayee.Name;
transferPayment.PayeeAccountKvid = accountPayee.Kvid;
transferPayment.PayeeAccountOwnerName = accountPayee.OwnerName;
transferPayment.PayeeAccountSerialNumber = accountPayee.SerialNumber;
transferPayment.Amount = amount;
transferPayment.AmountSplited = 0;
transferPayment.AmountUsed = amount;
transferPayment.OperateTime = DateTime.Now;
transferPayment.OperatorName = KiviiContext.CurrentMember.FullName;
transferPayment.OperatorKvid = KiviiContext.CurrentMember.Kvid;
transferPayment.Currency = payment.Currency;
transferPayment.Summary = $"{remark}";
transferPayment.Remark = $"{remark}";
#endregion
payment.AmountUsed += amount;
payment.AddOnlyProperties(o => o.AmountSplited);
return transferPayment;
payment.AmountInvoice = amountInvoiced;
payment.AddOnlyProperties(o => o.AmountInvoice);
conn.UpdateOnly(payment);
trans?.Commit();
return payment;
}
/// <summary>
/// Payment与Settlement产生关联的方法
/// </summary>
/// <param name="payments"></param>
/// <param name="settlements"></param>
/// <returns></returns>
public static List<Payment> Correlating(this List<Payment> payments,List<Settlement> settlements)
{
payments.ThrowIfNullOrEmpty("要关联的Payments不能为空!");
settlements.ThrowIfNullOrEmpty("要关联的Settlements不能为空!");
payments.Exists(o => o.Type != PaymentType.DynamicSplit).ThrowIfTrue("请选择正确收款类型进行关联结算");
var currentPayments = new List<Payment>();//不使用传入的List 防止修改了原List的数据
currentPayments.AddRange(payments);
var rtns = new List<Payment>();
foreach (var settlement in settlements)
{
//说明已经建立关联关系的settlement
if (settlement.AmountPayment >= settlement.Amount) continue;
foreach (var payment in currentPayments)
catch (Exception ex)
{
var settlementAmount = settlement.Amount - settlement.AmountPayment;
if (settlementAmount <= 0) break;
if (payment.Amount <= 0) continue;
var amount = settlementAmount <= payment.Amount ? settlementAmount : payment.Amount;
var payPayment = new Payment();
payPayment.PopulateInstance(payment);
payPayment.SerialNumber = string.Empty;
payPayment.Kvid = Guid.NewGuid();
payPayment.ParentKvid = payment.Kvid;
payPayment.BizId = settlement.SerialNumber;
payPayment.BizType = typeof(Settlement).FullName;
payPayment.BizKvid = settlement.Kvid;
payPayment.Type = PaymentType.Pay;
payPayment.Amount = amount;
payPayment.AmountUsed = amount;
payPayment.AmountSplited = amount;
rtns.Add(payPayment);
payment.Amount -= amount;
settlement.AmountPayment += amount;
}
settlement.AddOnlyProperties(o => o.AmountPayment);
}
return rtns;
trans?.Rollback();
throw ex;
}
/// <summary>
/// 到账 支付或充值 调用方法
/// </summary>
/// <param name="payment"></param>
/// <param name="payerAccount"></param>
/// <param name="payeeAccount"></param>
/// <returns></returns>
internal static List<AccountDetail> Using(this Payment payment, Account payerAccount, Account payeeAccount, string remark = null)
{
payment.ThrowIfNull("付款记录不能为空!");
payerAccount.ThrowIfNull("未找到付款账户!");
payeeAccount.ThrowIfNull("未找到收款账户!");
(payment.Currency == CurrencyUnit.Unsupported).ThrowIfTrue("不支持的货币单位");
(payment.Type == PaymentType.DynamicSplit || payment.Type == PaymentType.Transfer).ThrowIfFalse("此方法仅支持支付或充值");
(payment.Amount <= 0).ThrowIfTrue("付款记录发生金额不能少于0!");
(payment.PayerAccountKvid == Guid.Empty || payment.PayeeAccountKvid == Guid.Empty).ThrowIfTrue("收付款账户不能为空!");
(payment.AmountUsed != payment.Amount).ThrowIfTrue("已使用金额不等于支付金额!");
//(payment.PayerAccountKvid != payerAccount.Kvid).ThrowIfTrue("传入付款账户不一致!");
//(payment.PayeeAccountKvid != payeeAccount.Kvid).ThrowIfTrue("传入收款账户不一致!");
(payerAccount.Currency != payment.Currency).ThrowIfTrue($"付款账户({payerAccount.Currency})与此付款({payment.Currency})的货币单位不一致!");
(payeeAccount.Currency != payment.Currency).ThrowIfTrue($"收款账户({payeeAccount.Currency})与此付款({payment.Currency})的货币单位不一致!");
var rtns = new List<AccountDetail>();
#region 付款账户变动
var payerAccountDetail = new AccountDetail();
payerAccountDetail.AccountKvid = payerAccount.Kvid;
payerAccountDetail.BizId = payment.SerialNumber;
payerAccountDetail.BizKvid = payment.Kvid;
payerAccountDetail.BizType = typeof(Payment).FullName;
payerAccountDetail.PayerKvid = payment.PayerKvid;
payerAccountDetail.PayerName = payment.PayerName;
payerAccountDetail.PayerAccountKvid = payerAccount.Kvid;
payerAccountDetail.PayerAccountName = payerAccount.Name;
payerAccountDetail.PayerAccountSerialNumber = payerAccount.SerialNumber;
payerAccountDetail.PayeeKvid = payment.PayeeKvid;
payerAccountDetail.PayeeName = payment.PayeeName;
payerAccountDetail.PayeeAccountKvid = payeeAccount.Kvid;
payerAccountDetail.PayeeAccountName = payeeAccount.Name;
payerAccountDetail.PayeeAccountSerialNumber = payeeAccount.SerialNumber;
payerAccountDetail.AmountPayment = payment.Amount;
payerAccountDetail.Summary = payment.Summary;
payerAccountDetail.Remark = remark;
rtns.Add(payerAccountDetail);
#endregion
#region 收款账户变动
var payeeAccountDetail = new AccountDetail();
payeeAccountDetail.AccountKvid = payeeAccount.Kvid;
payeeAccountDetail.BizId = payment.SerialNumber;
payeeAccountDetail.BizKvid = payment.Kvid;
payeeAccountDetail.BizType = typeof(Payment).FullName;
payeeAccountDetail.PayerKvid = payment.PayerKvid;
payeeAccountDetail.PayerName = payment.PayerName;
payeeAccountDetail.PayerAccountKvid = payerAccount.Kvid;
payeeAccountDetail.PayerAccountName = payerAccount.Name;
payeeAccountDetail.PayerAccountSerialNumber = payerAccount.SerialNumber;
payeeAccountDetail.PayeeKvid = payment.PayeeKvid;
payeeAccountDetail.PayeeName = payment.PayeeName;
payeeAccountDetail.PayeeAccountKvid = payeeAccount.Kvid;
payeeAccountDetail.PayeeAccountName = payeeAccount.Name;
payeeAccountDetail.PayeeAccountSerialNumber = payeeAccount.SerialNumber;
payeeAccountDetail.AmountPayment = payment.Amount;
payeeAccountDetail.Summary = payment.Summary;
payeeAccountDetail.Remark = remark;
rtns.Add(payeeAccountDetail);
#endregion
return rtns;
}
}
}
using Kivii.Finances.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Kivii.Finances
{
public static class SettlementExtension
{
public static Settlement Offset (this Settlement settlement,string remark)
{
settlement.ThrowIfNull("付款记录不能为空!");
(settlement.OffsetKvid != Guid.Empty).ThrowIfTrue("收项已冲账");
(settlement.Currency == CurrencyUnit.Unsupported).ThrowIfTrue("不支持的货币单位");
#region pay冲账
var newSettlementKvid = Guid.NewGuid();
settlement.OffsetKvid = newSettlementKvid;
settlement.AddOnlyProperties(o => o.OffsetKvid);
settlement.Remark = $"{remark}";
settlement.AddOnlyProperties(o => o.Remark);
//新建一个和原来一样的
var offsetSettlement = new Settlement();
offsetSettlement.PopulateWith(settlement);
offsetSettlement.OffsetKvid = settlement.Kvid;//新的冲帐关联用原来的Kvid
offsetSettlement.Kvid = newSettlementKvid;
offsetSettlement.SerialNumber = settlement.SerialNumber.IsNullOrEmpty() ? "" : ("-" + settlement.SerialNumber);
offsetSettlement.Remark = $"{remark}";
offsetSettlement.AmountPlan = 0 - offsetSettlement.AmountPlan;
offsetSettlement.AmountPayment = 0 - offsetSettlement.AmountPayment;
offsetSettlement.Amount = 0 - offsetSettlement.Amount;//反向值
#endregion
return offsetSettlement;
}
}
}
......@@ -72,12 +72,15 @@
<Compile Include="Extensions\AccountExtension.cs" />
<Compile Include="Extensions\BillExtension.cs" />
<Compile Include="Extensions\InvoiceApplyExtension.cs" />
<Compile Include="Extensions\InvoiceExtension.cs" />
<Compile Include="Extensions\PayExtension.cs" />
<Compile Include="Extensions\PaymentExtension.cs" />
<Compile Include="Extensions\SettlementExtension.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Transforms\RestfulAccount.cs" />
<Compile Include="Transforms\RestfulAccountDetail.cs" />
<Compile Include="Transforms\RestfulBill.cs" />
<Compile Include="Transforms\RestfulInvoice.cs" />
<Compile Include="Transforms\RestfulInvoice.Debit.cs" />
<Compile Include="Transforms\RestfulInvoice.Offset.Deficit.cs" />
<Compile Include="Transforms\RestfulInvoiceApply.Apply.cs" />
......@@ -91,6 +94,7 @@
<Compile Include="Transforms\RestfulPayment.Split.cs" />
<Compile Include="Transforms\RestfulPayment.UnBiz.Refund.cs" />
<Compile Include="Transforms\RestfulSettlement.cs" />
<Compile Include="Transforms\RestfulSettlement.Offset.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
......
......@@ -23,9 +23,9 @@ namespace Kivii.Finances.Transforms
if (Item.Amount != 0) throw new Exception("开户时,户内金额只能为零!");
if (Item.Type == AccountType.Deposit && dbConnection.Exists<Account>(o => o.Name == Item.Name && o.OwnerKvid == Item.OwnerKvid && o.Type == AccountType.Deposit && o.OrganizationKvid == KiviiContext.CurrentMember.OrganizationKvid)) throw new Exception("当前组织已存在此客户的存款账户");
if (Item.Type == AccountType.WeChat && dbConnection.Exists<Account>(o => o.OwnerKvid == Item.OwnerKvid && o.Type == AccountType.WeChat && o.OrganizationKvid == KiviiContext.CurrentMember.OrganizationKvid)) throw new Exception("当前组织已存在微信账户!");
if (Item.Type == AccountType.AliPay && dbConnection.Exists<Account>(o => o.OwnerKvid == Item.OwnerKvid && o.Type == AccountType.AliPay && o.OrganizationKvid == KiviiContext.CurrentMember.OrganizationKvid)) throw new Exception("当前组织已存在支付宝账户!");
if (Item.Type == AccountType.Bank && dbConnection.Exists<Account>(o => o.OwnerKvid == Item.OwnerKvid && o.Type == AccountType.Bank && o.OrganizationKvid == KiviiContext.CurrentMember.OrganizationKvid)) throw new Exception("当前组织已存在银行账户!");
//if (Item.Type == AccountType.WeChat && dbConnection.Exists<Account>(o => o.OwnerKvid == Item.OwnerKvid && o.Type == AccountType.WeChat && o.OrganizationKvid == KiviiContext.CurrentMember.OrganizationKvid)) throw new Exception("当前组织已存在微信账户!");
//if (Item.Type == AccountType.AliPay && dbConnection.Exists<Account>(o => o.OwnerKvid == Item.OwnerKvid && o.Type == AccountType.AliPay && o.OrganizationKvid == KiviiContext.CurrentMember.OrganizationKvid)) throw new Exception("当前组织已存在支付宝账户!");
//if (Item.Type == AccountType.Bank && dbConnection.Exists<Account>(o => o.OwnerKvid == Item.OwnerKvid && o.Type == AccountType.Bank && o.OrganizationKvid == KiviiContext.CurrentMember.OrganizationKvid)) throw new Exception("当前组织已存在银行账户!");
_trans = dbConnection.OpenTransaction();
return base.OnPreRestfulCreate(req, res, dbConnection, rtns);
......@@ -66,7 +66,7 @@ namespace Kivii.Finances.Transforms
[Api(Description = "账户查询")]
[RequiresAnyRole(SystemRoles.Everyone)]
public class AccountQuery : RestfulExecution<Account>
public class AccountQueryEx : RestfulExecution<Account>
{
#region QueryArgs
public virtual int? Skip { get; set; }
......@@ -103,7 +103,7 @@ namespace Kivii.Finances.Transforms
}
[RequiresAnyRole(SystemRoles.Everyone)]
public class AccountQueryEx : RestfulQuery<Account>
public class AccountQuery : RestfulQuery<Account>
{
}
......@@ -135,4 +135,21 @@ namespace Kivii.Finances.Transforms
return rtns;
}
}
[Api(Description = "获取平衡账户")]
[RequiresAnyRole(SystemRoles.Everyone)]
public class AccountGetBalance : RestfulExecution<Account>
{
public CurrencyUnit Currency { get; set; }
public override object OnExecution(IRequest req, IResponse res)
{
(Currency == CurrencyUnit.Unsupported).ThrowIfTrue("不支持的货币单位!");
var rtns = new RestfulReadResponse<Account>();
rtns.Result = Currency.GetBalanceAccount();
return rtns;
}
}
}
......@@ -89,23 +89,33 @@ namespace Kivii.Finances.Transforms
[RequiresAnyRole(SystemRoles.Everyone)]
public class BillRead : RestfulRead<Bill>
{
public bool IncludeDetail { get; set; }
public override bool OnPostRestfulRead(IRequest req, IResponse res, IDbConnection dbConnection, IRestfulReadResponse<Bill> rtns)
{
if (!IncludeDetail) return base.OnPostRestfulRead(req, res, dbConnection, rtns);
var queryDetails = dbConnection.From<BillDetail>();
queryDetails.Where(o => o.BillKvid == rtns.Result.Kvid);
queryDetails.Select(o => o.BizKvid);
rtns.Result.Details = dbConnection.Select<Settlement>(o => Sql.In(o.Kvid, queryDetails));
return base.OnPostRestfulRead(req, res, dbConnection, rtns);
}
}
[RequiresAnyRole(SystemRoles.Everyone)]
public class BillQuery : RestfulQuery<Bill>
{
/// <summary>
/// true:只查已经归档的账单
/// false:只查未支付的账单
/// true:只查已经付款的账单
/// false:只查未付款的账单
/// 不传入: 全部账单
/// </summary>
public bool? Payed { get; set; }
public bool? IsPayed { get; set; }
public override bool OnPreRestfulQuery(IRequest req, IResponse res, IDbConnection dbConnection, IRestfulQueryResponse<Bill> rtns, ref Expression<Func<Bill, bool>> where)
{
if (Payed == null) return base.OnPreRestfulQuery(req, res, dbConnection, rtns, ref where);
if (Payed.Value) where = o => o.Amount == o.AmountPayment;
if (!Payed.Value) where = o => o.Amount > o.AmountPayment;
if (IsPayed == null) return base.OnPreRestfulQuery(req, res, dbConnection, rtns, ref where);
else if (IsPayed.Value) where = o => o.Amount == o.AmountPayment;
else where = o => o.Amount > o.AmountPayment || o.AmountPayment == 0;
return base.OnPreRestfulQuery(req, res, dbConnection, rtns, ref where);
}
}
......
......@@ -9,154 +9,69 @@ using System.Threading.Tasks;
namespace Kivii.Finances.Transforms
{
[Api(Description = "借票查询")]
[RequiresAnyRole(SystemRoles.Everyone)]
public class InvoiceDebitQuery : RestfulExecution<Invoice>
{
#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 bool? Debited { get; set; }
public override object OnExecution(IRequest req, IResponse res)
{
(BeginTime != null && EndTime != null && BeginTime.Value > EndTime.Value).ThrowIfTrue("开始日期不能大于结束时间!");
var conn = KiviiContext.GetOpenedDbConnection<Invoice>();
var dynamicParams = Request.GetRequestParams();
var autoQuery = Request.TryResolve<IAutoQueryDb>();
autoQuery.IncludeTotal = true;
var request = new RestfulQuery<Invoice>();
request = request.PopulateWith(this);
var sqlExpress = autoQuery.CreateQuery(Request, conn, request, dynamicParams);
sqlExpress.Where(o => o.RootKvid == o.Kvid && o.OffsetKvid == Guid.Empty && o.Category == InvoiceApplyType.Debit.ToString());
if (BeginTime != null) sqlExpress.And(o => o.OperateTime >= BeginTime.Value);
if (EndTime != null) sqlExpress.And(o => o.OperateTime < EndTime.Value);
if (Debited != null)
{
if (Debited.Value) sqlExpress.And(o => o.AmountPayment == o.Amount);
else sqlExpress.And(o => o.AmountPayment < o.Amount);
}
var rtns = autoQuery.Execute(Request, conn, request, sqlExpress);
if (Debited != null)
{
if (!Debited.Value)
{
var queryBankAccount = conn.From<Account>();
queryBankAccount.Where(o => o.OrganizationKvid == KiviiContext.CurrentMember.OrganizationKvid && Sql.In(o.Type, AccountType.Bank, AccountType.WeChat, AccountType.AliPay));
queryBankAccount.Select(o => o.Kvid);
var queryCashAccount = conn.From<Account>();
queryCashAccount.Where(o => o.OrganizationKvid == KiviiContext.CurrentMember.OrganizationKvid && Sql.In(o.Type, AccountType.Cash, AccountType.Pos));
queryCashAccount.Select(o => o.Kvid);
var queryPayment = conn.From<Payment>();
queryPayment.Where(o => o.RootKvid == o.Kvid && o.OffsetKvid == Guid.Empty && o.AmountInvoice < o.Amount && (Sql.In(o.PayeeAccountKvid, queryBankAccount) || Sql.In(o.PayerAccountKvid, queryCashAccount)));
queryPayment.Select(o => o.PayerName);
var paymentNames = conn.Column<string>(queryPayment).Distinct().ToList();
foreach (var item in rtns.Results)
{
if (paymentNames.Exists(o => o == item.PayerName))
{
item.Type = "Debit";
}
}
rtns.Results = rtns.Results.OrderBy(o => o.Type).ToList();
}
}
return rtns;
}
}
[Api(Description = "借票冲销")]
[RequiresAnyRole(SystemRoles.Everyone)]
public class InvoiceDebiting : RestfulExecution<Invoice>
{
public Guid ApplyKvid { get; set; }
//public Guid ApplyKvid { get; set; }
public Guid InvoiceKvid { get; set; }
public List<Guid> InvoiceKvids { get; set; }
public Guid PaymentKvid { get; set; }
//public AccountType Type { get; set; }
public decimal Amount { get; set; }
//public decimal Amount { get; set; }
public override object OnExecution(IRequest req, IResponse res)
{
if (ApplyKvid == Guid.Empty) throw new Exception("请传入借票申请对象!");
if (PaymentKvid == Guid.Empty) throw new Exception("请传入到账信息!");
if (InvoiceKvid == Guid.Empty && InvoiceKvids.IsNullOrEmpty()) throw new Exception("请传入要冲销的发票!");
if (InvoiceKvids.IsNullOrEmpty()) InvoiceKvids = new List<Guid>();
if (InvoiceKvid != Guid.Empty) InvoiceKvids.Add(InvoiceKvid);
//if (Type != AccountType.Bank && Type != AccountType.Cash && Type != AccountType.Pos) throw new Exception("冲销类型不正确!");
//if (Type != AccountType.Bank && Amount <= 0) throw new Exception("冲销金额不能小于0!");
//if (Type == AccountType.Bank && PaymentKvid == Guid.Empty) throw new Exception("请选择到账进行冲销!");
var conn = KiviiContext.GetOpenedDbConnection<InvoiceApply>();
var apply = conn.SingleById<InvoiceApply>(ApplyKvid);
apply.ThrowIfNull("未找到所选借票申请数据!");
(apply.OperateType != InvoiceApplyType.Debit).ThrowIfTrue("非借票不可冲销!");
(apply.OffsetKvid != Guid.Empty).ThrowIfTrue("当前借票申请已冲账,无法继续操作!");
(apply.Status != (int)InvoiceApplyStatus.Completed).ThrowIfTrue("当前借票申请未执行完毕,无法冲销!");
var existInvoices = conn.Select<Invoice>(o => o.ApplyKvid == apply.Kvid && o.OffsetKvid == Guid.Empty && o.RootKvid == o.Kvid);
if (existInvoices.IsNullOrEmpty()) throw new Exception("未找到所选申请对应的发票信息!");
var unDebitAmount = existInvoices.Sum(o => o.Amount) - existInvoices.Sum(o => o.AmountPayment);
(unDebitAmount <= 0).ThrowIfTrue("此申请无需再冲销!");
var applyRelations = conn.Select<InvoiceApply>(o => o.ParentKvid == apply.Kvid && o.OperateType == InvoiceApplyType.Related && o.OffsetKvid == Guid.Empty);
var conn = KiviiContext.GetOpenedDbConnection<Invoice>();
var invoices = conn.SelectByIds<Invoice>(InvoiceKvids);
if (invoices.IsNullOrEmpty()) throw new Exception("未找到所选发票信息!");
if (invoices.Exists(o => o.OffsetKvid != Guid.Empty || o.RootKvid != o.Kvid || o.Amount <= 0)) throw new Exception("存在不正确的发票类型");
if (invoices.Count != InvoiceKvids.Count) throw new Exception("所选发票信息与查询后结果不一致!");
var unDebitAmount = invoices.Sum(o => o.Amount) - invoices.Sum(o => o.AmountPayment);
(unDebitAmount <= 0).ThrowIfTrue("此发票已冲销,请勿重复操作!");
//var applyKvids = invoices.ConvertAll(o => o.ApplyKvid).Distinct().ToList();
//var applys = conn.SelectByIds<InvoiceApply>(applyKvids);
////applys.ThrowIfNullOrEmpty("未找到所选借票申请数据!");
////(applys.OperateType != InvoiceApplyType.Debit).ThrowIfTrue("非借票不可冲销!");
////(applys.OffsetKvid != Guid.Empty).ThrowIfTrue("当前借票申请已冲账,无法继续操作!");
////(applys.Status != (int)InvoiceApplyStatus.Completed).ThrowIfTrue("当前借票申请未执行完毕,无法冲销!");
//var applyRelations = new List<InvoiceApply>();
//if (!applys.IsNullOrEmpty()) applyRelations = conn.Select<InvoiceApply>(o => o.OperateType == InvoiceApplyType.Related && o.OffsetKvid == Guid.Empty && Sql.In(o.ParentKvid, applyKvids));
var rtns = new RestfulUpdateResponse<Invoice>();
rtns.Results = new List<Invoice>();
var payment = conn.SingleById<Payment>(PaymentKvid);
if (payment == null) throw new Exception("未找到收款信息!");
if (payment.Type != PaymentType.Bank && payment.Type != PaymentType.Cash && payment.Type != PaymentType.Pos && payment.Type != PaymentType.AliPay && payment.Type != PaymentType.WeChat) throw new Exception("请选择正确银行到账进行冲销!");
if (payment.AmountInvoice >= payment.Amount) throw new Exception("当前到账已开票,无法冲销当前借票!");
var splitPayments = conn.Select<Payment>(o => o.ParentKvid == payment.Kvid && o.OffsetKvid == Guid.Empty && o.Type == PaymentType.Split);
if (Amount <= 0 || Amount > (payment.Amount - payment.AmountInvoice)) Amount = payment.Amount - payment.AmountInvoice;
decimal amount = Amount >= unDebitAmount ? unDebitAmount : Amount;
var relation = new InvoiceApply();//apply关联Payment
relation.PopulateWith(apply);
relation.Kvid = Guid.NewGuid();
relation.RootKvid = apply.Kvid;
relation.ParentKvid = apply.Kvid;
relation.SerialNumber = string.Empty;
relation.OperateType = InvoiceApplyType.Related;
relation.OwnerKvid = apply.OwnerKvid;
relation.OwnerName = apply.OwnerName;
relation.BizId = payment.SerialNumber;
relation.BizKvid = payment.Kvid;
relation.BizType = typeof(Payment).FullName;
relation.Type = apply.OperateType.ToString();
relation.Amount = amount;
relation.OperatorName = KiviiContext.CurrentMember.FullName;
relation.OperatorKvid = KiviiContext.CurrentMember.Kvid;
relation.AmountInvoice = amount;
relation.AmountUsed = amount;
apply.AmountUsed = applyRelations.Sum(o => o.Amount) + amount;//更新apply的值
apply.AddOnlyProperties(o => o.AmountUsed);
var splitPayments = conn.Select<Payment>(o => o.ParentKvid == payment.Kvid && o.OffsetKvid == Guid.Empty &&Sql.In( o.Type, PaymentType.UnBiz, PaymentType.Refund, PaymentType.Split));
if (!splitPayments.IsNullOrEmpty())
{
var queryApplying = conn.From<InvoiceApply>();
//只查询存在 申请中的 apply,查看当前正在申请中的金额 用作判断是否允许被冲销
queryApplying.Where(o => o.AmountInvoice == 0 && o.OperateType == InvoiceApplyType.Related && o.OffsetKvid == Guid.Empty && Sql.In(o.BizKvid, splitPayments.ConvertAll(p => p.Kvid)));
var existApplyings = conn.Select(queryApplying);
(!existApplyings.IsNullOrEmpty()).ThrowIfTrue("所选到账,存在开票中的申请!请开票完成后再操作!");
}
//if (Amount <= 0 || Amount > (payment.Amount - payment.AmountInvoice)) Amount = payment.Amount - payment.AmountInvoice;
//decimal amount = Amount >= unDebitAmount ? unDebitAmount : Amount;
var payments = new List<Payment>();
payments.Add(payment);
var correlatedInvoices = existInvoices.Correlating(payments);//生成payment和invoice之间的关联,同事原Invoices也要更新相关数据
var correlatedInvoices = invoices.Correlating(payments);//生成payment和invoice之间的关联,同事原Invoices也要更新相关数据
#region 优化
if (!splitPayments.IsNullOrEmpty())//要是所选Payment存在拆分项,满足条件就要更新AmountInvoice
{
decimal amountInvoice = 0;
amountInvoice.PopulateWith(payment.AmountInvoice);// = payment.AmountInvoice;
decimal amountInvoice = payment.AmountInvoice;
foreach (var item in splitPayments)
{
if (amountInvoice <= 0) continue;
......@@ -165,13 +80,12 @@ namespace Kivii.Finances.Transforms
amountInvoice -= item.AmountInvoice;
}
}
#endregion
var trans = conn.OpenTransaction();
try
{
conn.Insert(relation);
conn.UpdateOnly(apply);
//conn.Insert(relation);
//conn.UpdateOnly(applys);
conn.UpdateOnly(payment);
if (!splitPayments.IsNullOrEmpty())
{
......@@ -181,12 +95,7 @@ namespace Kivii.Finances.Transforms
conn.UpdateOnly(item);
}
}
foreach (var item in correlatedInvoices)
{
item.SerialNumber = item.GetSubSerialNumber(conn);
conn.Insert(item);
}
foreach (var item in existInvoices)
foreach (var item in invoices)
{
if (item.OnlyProperties.Count > 0)
{
......@@ -194,6 +103,11 @@ namespace Kivii.Finances.Transforms
rtns.Results.Add(item);
}
}
foreach (var item in correlatedInvoices)
{
item.SerialNumber = item.GetSubSerialNumber(conn);
conn.Insert(item);
}
trans.Commit();
}
catch (Exception ex)
......@@ -210,86 +124,80 @@ namespace Kivii.Finances.Transforms
[RequiresAnyRole(SystemRoles.Everyone)]
public class InvoiceDebitCancel : RestfulExecution<Invoice>
{
public Guid ApplyKvid { get; set; }
public Guid InvoiceKvid { get; set; }
public List<Guid> InvoiceKvids { get; set; }
public override object OnExecution(IRequest req, IResponse res)
{
if (ApplyKvid == Guid.Empty) throw new Exception("请传入借票申请对象!");
var conn = KiviiContext.GetOpenedDbConnection<InvoiceApply>();
var apply = conn.SingleById<InvoiceApply>(ApplyKvid);
apply.ThrowIfNull("未找到所选发票申请信息!");
(apply.OperateType != InvoiceApplyType.Debit).ThrowIfTrue("非借票不可撤销!");
(apply.OffsetKvid != Guid.Empty).ThrowIfTrue("当前借票申请已冲账,无法继续操作!");
(apply.Status != (int)InvoiceApplyStatus.Completed).ThrowIfTrue("当前借票申请未完成开票,无法继续操作!");
var allInvoices = conn.Select<Invoice>(o => o.ApplyKvid == apply.Kvid && o.OffsetKvid == Guid.Empty);
if (allInvoices.IsNullOrEmpty()) throw new Exception("未找到所选申请对应的发票信息!");
var existInvoices = allInvoices.Where(o => o.RootKvid == o.Kvid).ToList();//发票信息
if (existInvoices.IsNullOrEmpty()) throw new Exception("未找到所选申请对应的发票信息!");
var relationInvoices = allInvoices.Where(o => o.Type == "Relation" && o.OffsetKvid == Guid.Empty).ToList();//关联Payment的发票数据
var applyRelations = conn.Select<InvoiceApply>(o => o.ParentKvid == apply.Kvid && o.OperateType == InvoiceApplyType.Related && o.OffsetKvid == Guid.Empty);//关联Payment的申请数据
if (applyRelations.IsNullOrEmpty()) throw new Exception("当前申请无需冲销撤销");
var existPayments = conn.Select<Payment>(o => Sql.In(o.Kvid, applyRelations.ConvertAll(p => p.BizKvid)));//Type:Bank,Split,Pos,Cash,WeChat...
if (existPayments.IsNullOrEmpty()) throw new Exception("当前申请未找到到账冲销,无需撤销!");
List<Payment> parentOrNodePayments = new List<Payment>();//父级或子级payment也要更新AmountInvoice
var existPaymentRootKvids = existPayments.Where(o => o.RootKvid != o.Kvid).ToList().ConvertAll(p => p.RootKvid);
if (!existPaymentRootKvids.IsNullOrEmpty())
if (InvoiceKvid == Guid.Empty && InvoiceKvids.IsNullOrEmpty()) throw new Exception("请传入要撤销冲销的发票!");
if (InvoiceKvids.IsNullOrEmpty()) InvoiceKvids = new List<Guid>();
if (InvoiceKvid != Guid.Empty) InvoiceKvids.Add(InvoiceKvid);
var conn = KiviiContext.GetOpenedDbConnection<Invoice>();
var invoices = conn.SelectByIds<Invoice>(InvoiceKvids);
if (invoices.IsNullOrEmpty()) throw new Exception("未找到所选发票信息!");
if (invoices.Exists(o => o.OffsetKvid != Guid.Empty || o.RootKvid != o.Kvid || o.Amount <= 0)) throw new Exception("存在不正确的发票类型");
if (invoices.Count != InvoiceKvids.Count) throw new Exception("所选发票信息与查询后结果不一致!");
var relationInvoices = conn.Select<Invoice>(o => Sql.In(o.ParentKvid, InvoiceKvids) && o.OffsetKvid == Guid.Empty && o.Type == "Relation");
if (relationInvoices.IsNullOrEmpty()) throw new Exception("所选发票未找到冲销记录,无需冲销!");
var existPayments = conn.Select<Payment>(o => Sql.In(o.Kvid, relationInvoices.ConvertAll(p => p.BizKvid)));//Type:Bank,Pos,Cash,WeChat...
if (existPayments.IsNullOrEmpty()) throw new Exception("所选发票未找到冲销记录,无需撤销!");
var splitPayments = conn.Select<Payment>(o => o.OffsetKvid == Guid.Empty && o.Type == PaymentType.Split && Sql.In(o.ParentKvid, existPayments.ConvertAll(p => p.Kvid)));
foreach (var item in existPayments)
{
var relations = relationInvoices.Where(o => o.BizKvid == item.Kvid).ToList();
if (!relations.IsNullOrEmpty())
{
item.AmountInvoice -= relations.Sum(o => o.Amount);
if (item.AmountInvoice < 0) item.AmountInvoice = 0;
item.AddOnlyProperties(o => o.AmountInvoice);
}
if (!splitPayments.IsNullOrEmpty())//要是所选Payment存在拆分项,满足条件就要更新AmountInvoice
{
var parents = conn.Select<Payment>(o => o.OffsetKvid == Guid.Empty && Sql.In(o.Kvid, existPaymentRootKvids));
if (!parents.IsNullOrEmpty()) parentOrNodePayments.AddRange(parents);
decimal amountInvoice = 0;
amountInvoice.PopulateWith(item.AmountInvoice);// = payment.AmountInvoice;
foreach (var split in splitPayments)
{
if (amountInvoice <= 0) split.AmountInvoice = 0;
else split.AmountInvoice = split.Amount >= amountInvoice ? amountInvoice : split.Amount;
split.AddOnlyProperties(o => o.AmountInvoice);
amountInvoice -= split.AmountInvoice;
}
}
}
var nodes = conn.Select<Payment>(o => Sql.In(o.ParentKvid, existPayments.ConvertAll(p => p.Kvid)) && o.OffsetKvid == Guid.Empty && o.Type == PaymentType.Split);
if (!nodes.IsNullOrEmpty()) parentOrNodePayments.AddRange(nodes);
var rtns = new RestfulUpdateResponse<Invoice>();
rtns.Results = new List<Invoice>();
var trans = conn.OpenTransaction();
try
{
//删除关联payment的申请数据
var updateApplyRelations = conn.From<InvoiceApply>();
updateApplyRelations = updateApplyRelations.Update(o => o.Status);
updateApplyRelations = updateApplyRelations.Where(o => Sql.In(o.Kvid, applyRelations.ConvertAll(p => p.Kvid)));
conn.UpdateOnly<InvoiceApply>(new InvoiceApply { Status = -1 }, updateApplyRelations);
//删除关联Payment的发票数据
if (!relationInvoices.IsNullOrEmpty())
{
var updateRelationInvoices = conn.From<Invoice>();
updateRelationInvoices = updateRelationInvoices.Update(o => o.Status);
updateRelationInvoices = updateRelationInvoices.Where(o => Sql.In(o.Kvid, relationInvoices.ConvertAll(p => p.Kvid)));
conn.UpdateOnly<Invoice>(new Invoice { Status = -1 }, updateRelationInvoices);
}
//更新申请的到账金额
apply.AmountUsed = 0;
apply.AddOnlyProperties(o => o.AmountUsed);
conn.UpdateOnly(apply);
//更新发票的付款时间和到账金额
var updateExistInvoices = conn.From<Invoice>();
updateExistInvoices = updateExistInvoices.Update(o => new { o.PayedTime, o.AmountPayment });
updateExistInvoices = updateExistInvoices.Where(o => Sql.In(o.Kvid, existInvoices.ConvertAll(p => p.Kvid)));
updateExistInvoices = updateExistInvoices.Where(o => Sql.In(o.Kvid, invoices.ConvertAll(p => p.Kvid)));
conn.UpdateOnly<Invoice>(new Invoice { PayedTime = null, AmountPayment = 0 }, updateExistInvoices);
//更新已关联的payment的AmountInvoice
var updateExistPayments = conn.From<Payment>();
updateExistPayments = updateExistPayments.Update(o => o.AmountInvoice);
updateExistPayments = updateExistPayments.Where(o => Sql.In(o.Kvid, existPayments.ConvertAll(p => p.Kvid)));
conn.UpdateOnly<Payment>(new Payment { AmountInvoice = 0 }, updateExistPayments);
if (!parentOrNodePayments.IsNullOrEmpty())
foreach (var item in existPayments)
{
if (item.OnlyProperties.Count > 0) conn.UpdateOnly(item);
}
//更新已关联的payment的父级或子级AmountInvoice
var updateParentOrNodePayments = conn.From<Payment>();
updateParentOrNodePayments = updateParentOrNodePayments.Update(o => o.AmountInvoice);
updateParentOrNodePayments = updateParentOrNodePayments.Where(o => Sql.In(o.Kvid, parentOrNodePayments.ConvertAll(p => p.Kvid)));
conn.UpdateOnly<Payment>(new Payment { AmountInvoice = 0 }, updateParentOrNodePayments);
if (!splitPayments.IsNullOrEmpty())
{
foreach (var item in splitPayments)
{
if (item.OnlyProperties.Count > 0) conn.UpdateOnly(item);
}
}
rtns.Results.AddRange(invoices);
rtns.Results.AddRange(existInvoices);
trans.Commit();
}
catch (Exception ex)
{
......
......@@ -12,23 +12,114 @@ namespace Kivii.Finances.Transforms
[Api(Description = "发票作废")]
[RequiresAnyRole(SystemRoles.Everyone)]
public class InvoiceOffset:RestfulExecution<Invoice>
public class InvoiceOffset : RestfulExecution<Invoice>
{
public Guid Kvid { get; set; }
public List<Guid> Kvids { get; set; }
public string Remark { get; set; }
public override object OnExecution(IRequest req, IResponse res)
{
Kvid.ThrowIfEmpty("请传入要冲销的发票Kvid!");
if (Kvid == Guid.Empty && Kvids.IsNullOrEmpty()) throw new Exception("请传入要作废的发票Kvid!");
if (Kvids.IsNullOrEmpty()) Kvids = new List<Guid>();
if (Kvid != Guid.Empty) Kvids.Add(Kvid);
var conn = KiviiContext.GetOpenedDbConnection<Invoice>();
var invoice = conn.SingleById<Invoice>(Kvid);
invoice.ThrowIfNull("未找到对应发票!");
invoice.BizKvid.ThrowIfNotEmpty("发票已关联业务! 请先解除关联!");
invoice.OffsetKvid.ThrowIfNotEmpty("发票已作废!");
var apply = conn.SingleById<InvoiceApply>(invoice.ApplyKvid);
var invoices = conn.SelectByIds<Invoice>(Kvids);
if (invoices.IsNullOrEmpty()) throw new Exception("未找到所选发票信息!");
if (invoices.Exists(o => o.BizKvid != Guid.Empty || o.OffsetKvid != Guid.Empty || o.RootKvid != o.Kvid || o.Amount <= 0)) throw new Exception("存在不正确的发票类型");
if (invoices.Count != Kvids.Count) throw new Exception("所选发票信息与查询后结果不一致!");
var relationInvoices = conn.Select<Invoice>(o => Sql.In(o.ParentKvid, Kvids) && o.OffsetKvid == Guid.Empty && o.Type == "Relation");
List<Payment> existPayments = null;
List<Payment> splitPayments = null;
List<Invoice> offsets = new List<Invoice>();
if (!relationInvoices.IsNullOrEmpty())
{
existPayments = conn.Select<Payment>(o => Sql.In(o.Kvid, relationInvoices.ConvertAll(p => p.BizKvid)));//Type:Bank,Pos,Cash,WeChat...
if (!existPayments.IsNullOrEmpty())
{
splitPayments = conn.Select<Payment>(o => o.OffsetKvid == Guid.Empty && o.Type == PaymentType.Split && Sql.In(o.ParentKvid, existPayments.ConvertAll(p => p.Kvid)));
foreach (var item in existPayments)
{
var relations = relationInvoices.Where(o => o.BizKvid == item.Kvid).ToList();
if (!relations.IsNullOrEmpty())
{
item.AmountInvoice -= relations.Sum(o => o.Amount);
if (item.AmountInvoice < 0) item.AmountInvoice = 0;
item.AddOnlyProperties(o => o.AmountInvoice);
}
if (!splitPayments.IsNullOrEmpty())//要是所选Payment存在拆分项,满足条件就要更新AmountInvoice
{
decimal amountInvoice = 0;
amountInvoice.PopulateWith(item.AmountInvoice);// = payment.AmountInvoice;
foreach (var split in splitPayments)
{
if (amountInvoice <= 0) split.AmountInvoice = 0;
else split.AmountInvoice = split.Amount >= amountInvoice ? amountInvoice : split.Amount;
split.AddOnlyProperties(o => o.AmountInvoice);
amountInvoice -= split.AmountInvoice;
}
}
}
}
foreach (var item in relationInvoices)
{
var offset = item.Offset($"发票作废:{Remark}");
offsets.Add(offset);
}
}
foreach (var item in invoices)
{
var offset = item.Offset($"发票作废:{Remark}");
offsets.Add(offset);
}
var rtns = new RestfulUpdateResponse<Invoice>();
rtns.Results = new List<Invoice>();
return base.OnExecution(req, res);
var trans = conn.OpenTransaction();
try
{
foreach (var item in invoices)
{
conn.UpdateOnly(item);
rtns.Results.Add(item);
}
//删除关联Payment的发票数据
if (!relationInvoices.IsNullOrEmpty())
{
foreach (var item in relationInvoices)
{
conn.UpdateOnly(item);
}
}
foreach (var item in offsets)
{
conn.Insert(item);
}
//更新已关联的payment的AmountInvoice
if (!existPayments.IsNullOrEmpty())
{
foreach (var item in existPayments)
{
if (item.OnlyProperties.Count > 0) conn.UpdateOnly(item);
}
}
//更新已关联的payment的父级或子级AmountInvoice
if (!splitPayments.IsNullOrEmpty())
{
foreach (var item in splitPayments)
{
if (item.OnlyProperties.Count > 0) conn.UpdateOnly(item);
}
}
trans.Commit();
}
catch (Exception ex)
{
trans.Rollback();
throw ex;
}
return rtns;
}
}
......@@ -36,19 +127,70 @@ namespace Kivii.Finances.Transforms
[RequiresAnyRole(SystemRoles.Everyone)]
public class InvoiceOffsetCancel : RestfulExecution<Invoice>
{
}
public Guid Kvid { get; set; }
public List<Guid> Kvids { get; set; }
[Api(Description = "发票红冲")]
[RequiresAnyRole(SystemRoles.Everyone)]
public class InvoiceDeficit : RestfulExecution<Invoice>
public override object OnExecution(IRequest req, IResponse res)
{
if (Kvid == Guid.Empty && Kvids.IsNullOrEmpty()) throw new Exception("请传入要作废的发票Kvid!");
if (Kvids.IsNullOrEmpty()) Kvids = new List<Guid>();
if (Kvid != Guid.Empty) Kvids.Add(Kvid);
var conn = KiviiContext.GetOpenedDbConnection<Invoice>();
var invoices = conn.SelectByIds<Invoice>(Kvids);
if (invoices.IsNullOrEmpty()) throw new Exception("未找到所选发票信息!");
if (invoices.Exists(o => o.OffsetKvid == Guid.Empty)) throw new Exception("存在不正确的未作废发票,无法撤回!");
if (invoices.Exists(o => o.Amount <= 0)) throw new Exception("请选择原作废发票信息进行撤销!");
if (invoices.Count != Kvids.Count) throw new Exception("所选发票信息与查询后结果不一致!");
//发票作废后 想要撤销操作,不管当初此发票是否已经有到账,都会变成借票的发票,需要冲销抵扣才行
var offsetInvoices = conn.Select<Invoice>(o => Sql.In(o.OffsetKvid, invoices.ConvertAll(p => p.OffsetKvid)));
offsetInvoices.ThrowIfNullOrEmpty("未找到原作废项目!");
}
var rtns = new RestfulExecutionResponse<Invoice>();
rtns.Results = new List<Invoice>();
[Api(Description = "红冲撤回")]
[RequiresAnyRole(SystemRoles.Everyone)]
public class InvoiceDeficitCancel : RestfulExecution<Invoice>
var trans = conn.OpenTransaction();
try
{
//原发票还原
var updateInvoices = conn.From<Invoice>();
updateInvoices = updateInvoices.Update(o => new { o.OffsetKvid, o.PayedTime, o.AmountPayment, o.Remark });
updateInvoices = updateInvoices.Where(o => Sql.In(o.Kvid, invoices.ConvertAll(p => p.Kvid)));
conn.UpdateOnly<Invoice>(new Invoice { OffsetKvid = Guid.Empty, PayedTime = null, AmountPayment = 0, Remark = string.Empty }, updateInvoices);
foreach (var item in invoices)
{
item.OffsetKvid = Guid.Empty;
item.PayedTime = null;
item.AmountPayment = 0;
item.Remark = string.Empty;
item.RemoveAllOnlyProperties();
rtns.Results.Add(item);
}
//删除Offset发票数据
var updateOffsetInvoices = conn.From<Invoice>();
updateOffsetInvoices = updateOffsetInvoices.Update(o => o.Status);
updateOffsetInvoices = updateOffsetInvoices.Where(o => Sql.In(o.Kvid, offsetInvoices.ConvertAll(p => p.Kvid)));
conn.UpdateOnly<Invoice>(new Invoice { Status = -1 }, updateOffsetInvoices);
trans.Commit();
}
catch (Exception ex)
{
trans.Rollback();
throw ex;
}
return base.OnExecution(req, res);
}
}
//[Api(Description = "发票红冲")]
//[RequiresAnyRole(SystemRoles.Everyone)]
//public class InvoiceDeficit : RestfulExecution<Invoice>
//{
//}
//[Api(Description = "红冲撤回")]
//[RequiresAnyRole(SystemRoles.Everyone)]
//public class InvoiceDeficitCancel : RestfulExecution<Invoice>
//{
//}
}
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
{
[Api(Description = "发票查询")]
[RequiresAnyRole(SystemRoles.Everyone)]
public class InvoiceQueryEx : RestfulExecution<Invoice>
{
#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 bool? Debited { get; set; }//借票到账未到账查询
public override object OnExecution(IRequest req, IResponse res)
{
(BeginTime != null && EndTime != null && BeginTime.Value > EndTime.Value).ThrowIfTrue("开始日期不能大于结束时间!");
var conn = KiviiContext.GetOpenedDbConnection<Invoice>();
var dynamicParams = Request.GetRequestParams();
var autoQuery = Request.TryResolve<IAutoQueryDb>();
autoQuery.IncludeTotal = true;
var request = new RestfulQuery<Invoice>();
request = request.PopulateWith(this);
var sqlExpress = autoQuery.CreateQuery(Request, conn, request, dynamicParams);
sqlExpress.Where(o => o.RootKvid == o.Kvid);
//sqlExpress.Where(o => o.RootKvid == o.Kvid && o.OffsetKvid == Guid.Empty && o.Category == InvoiceApplyType.Debit.ToString());
if (BeginTime != null) sqlExpress.And(o => o.OperateTime >= BeginTime.Value);
if (EndTime != null) sqlExpress.And(o => o.OperateTime < EndTime.Value);
if (Debited != null)
{
if (Debited.Value) sqlExpress.And(o => o.AmountPayment == o.Amount);
else sqlExpress.And(o => o.AmountPayment < o.Amount);
}
var rtns = autoQuery.Execute(Request, conn, request, sqlExpress);
if (Debited != null)
{
if (!Debited.Value)
{
var queryAccount = conn.From<Account>();
queryAccount.Where(o => o.OrganizationKvid == KiviiContext.CurrentMember.OrganizationKvid && Sql.In(o.Type, AccountType.Balance, AccountType.Cash, AccountType.Pos));
queryAccount.Select(o => o.Kvid);
var queryPayment = conn.From<Payment>();
queryPayment.Where(o => o.RootKvid == o.Kvid && o.OffsetKvid == Guid.Empty && o.AmountInvoice < o.Amount && (Sql.In(o.PayerAccountKvid, queryAccount)));
queryPayment.Select(o => o.PayerName);
var paymentNames = conn.Column<string>(queryPayment).Distinct().ToList();
foreach (var item in rtns.Results)
{
if (paymentNames.Exists(o => o == item.PayerName))
{
item.Type = "Debit";
}
}
rtns.Results = rtns.Results.OrderBy(o => o.Type).ToList();
}
}
return rtns;
}
}
[RequiresAnyRole(SystemRoles.Everyone)]
public class InvoiceQuery : RestfulQuery<Invoice>
{ }
[RequiresAnyRole(SystemRoles.Everyone)]
public class InvoiceRead : RestfulRead<Invoice>
{ }
}
......@@ -44,7 +44,7 @@ namespace Kivii.Finances.Transforms
var applyKvid = Guid.NewGuid();
Item.RootKvid = applyKvid;
Item.ParentKvid = Guid.Empty;
Item.AmountUsed = 0;
//Item.AmountUsed = 0;
Item.OperateTime = DateTime.Now;
Item.Status = (int)InvoiceApplyStatus.FinancialApproval;
Item.Kvid = applyKvid;
......@@ -57,11 +57,11 @@ namespace Kivii.Finances.Transforms
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("申请金额与所选到账金额不一致!");
(conn.Exists<InvoiceApply>(o => o.OperateType == InvoiceApplyType.Related && o.OffsetKvid == Guid.Empty && Sql.In(o.BizKvid, payments.ConvertAll(p => p.Kvid)))).ThrowIfTrue("已有申请开票中的到账!");
(conn.Exists<Invoice>(o => o.OffsetKvid != Guid.Empty && Sql.In(o.BizKvid, payments.ConvertAll(p => p.RootKvid)))).ThrowIfTrue("已有开票的到账!");
//(conn.Exists<Invoice>(o => o.OffsetKvid == Guid.Empty && Sql.In(o.BizKvid, payments.ConvertAll(p => p.RootKvid)))).ThrowIfTrue("已有开票的到账!");
var trans = conn.OpenTransaction();
try
......@@ -69,7 +69,7 @@ namespace Kivii.Finances.Transforms
var applyKvid = Guid.NewGuid();
Item.RootKvid = applyKvid;
Item.ParentKvid = Guid.Empty;
Item.AmountUsed = Item.Amount;
//Item.AmountUsed = Item.Amount;
Item.OperateTime = DateTime.Now;
Item.Status = (int)InvoiceApplyStatus.FinancialApproval;
Item.Kvid = applyKvid;
......@@ -80,20 +80,20 @@ namespace Kivii.Finances.Transforms
{
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.BizId = item.SerialNumber;
relation.BizKvid = item.Kvid;
relation.BizType = typeof(Payment).FullName;
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;
//relation.AmountUsed = relation.Amount;
conn.Insert(relation);
}
......@@ -148,7 +148,7 @@ namespace Kivii.Finances.Transforms
item.OwnerName = KiviiContext.CurrentMember.DepartmentName;
item.RootKvid = applyKvid;
item.ParentKvid = Guid.Empty;
item.AmountUsed = 0;
//item.AmountUsed = 0;
item.OperateTime = DateTime.Now;
item.Status = (int)InvoiceApplyStatus.FinancialApproval;
item.Kvid = applyKvid;
......@@ -192,8 +192,8 @@ namespace Kivii.Finances.Transforms
(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.AmountUsed = 0;
//apply.AddOnlyProperties(o => o.AmountUsed);
apply.Summary += " (驳回原因:" + Summary + ")";
apply.AddOnlyProperties(o => o.Summary);
conn.UpdateOnly(apply);
......@@ -265,6 +265,7 @@ namespace Kivii.Finances.Transforms
if (apply.Status >= (int)InvoiceApplyStatus.FinancialExecute) throw new Exception("请勿重复申请开票!");
if (apply.Status < (int)InvoiceApplyStatus.ProcessAdoption) throw new Exception("此申请还在审批中...");
if (apply.Amount != Details.Sum(o => o.Amount)) throw new Exception("总金额和明细总额不一致!");
conn.InitEntityType<InvoiceApplyDetail>();
var existDetails = conn.Select<InvoiceApplyDetail>(o => o.ApplyKvid == apply.Kvid);
var applyRelations = conn.Select<InvoiceApply>(o => o.ParentKvid == apply.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...
......@@ -340,7 +341,6 @@ namespace Kivii.Finances.Transforms
public List<InvoiceApplyDetail> Details { get; set; }
//发票开具最大额度限制 默认10万
public decimal Limit { get; set; } = 100000;
......@@ -392,6 +392,7 @@ namespace Kivii.Finances.Transforms
detail.QuantityUnitPrice = Math.Round(detail.Amount / detail.Quantity, 2);
}
#endregion
var relationApplys = conn.Select<InvoiceApply>(o => Sql.In(o.ParentKvid, applys.Select(p => p.Kvid)) && o.OperateType == InvoiceApplyType.Related && o.OffsetKvid == Guid.Empty);
var rtns = new RestfulExecutionResponse<InvoiceApply>();
rtns.Results = new List<InvoiceApply>();
......@@ -408,7 +409,7 @@ namespace Kivii.Finances.Transforms
newApply.ParentKvid = Guid.Empty;
newApply.Kvid = newInvoiceApplyKvid;
newApply.Amount = applys.Sum(o => o.Amount);
newApply.AmountUsed = applys.Sum(o => o.AmountUsed);
//newApply.AmountUsed = applys.Sum(o => o.AmountUsed);
newApply.Status = (int)InvoiceApplyStatus.FinancialApproval;
newApply.Summary = Item.Summary;
newApply.Remark = remark;
......@@ -429,8 +430,8 @@ namespace Kivii.Finances.Transforms
#region Apply更新(更改状态和biz记录新生产的Apply)
foreach (var item in applys)
{
item.AmountUsed = 0;
item.AddOnlyProperties(o => o.AmountUsed);
//item.AmountUsed = 0;
//item.AddOnlyProperties(o => o.AmountUsed);
item.BizType = typeof(InvoiceApply).FullName;
item.AddOnlyProperties(o => o.BizType);
item.BizKvid = newInvoiceApplyKvid;
......@@ -442,8 +443,6 @@ namespace Kivii.Finances.Transforms
#endregion
#region 对应收款关联的ApplyKvid变更
var relationApplys = conn.Select<InvoiceApply>(o => Sql.In(o.ParentKvid, applys.Select(p => p.Kvid)) && o.OperateType == InvoiceApplyType.Related && o.OffsetKvid == Guid.Empty);
//var relationApplys = conn.Select<InvoiceApply>(o => Sql.In(o.ParentKvid, applys.Select(p => p.Kvid).ToList()) && o.OperateType == InvoiceApplyType.Related);
if (!relationApplys.IsNullOrEmpty())
{
foreach (var relation in relationApplys)
......@@ -520,7 +519,6 @@ namespace Kivii.Finances.Transforms
[Api(Description = "获取一条")]
public class InvoiceApplyExecuting : RestfulExecution<InvoiceApply>
{
/// <summary>
/// 优先级OperatorKvid>OwnerKvid>OrganizationKvid
/// </summary>
......@@ -616,8 +614,8 @@ namespace Kivii.Finances.Transforms
apply.AddOnlyProperties(o => o.Status);
apply.Remark = $"开票失败! {info.Join(",")}";
apply.AddOnlyProperties(o => o.Remark);
apply.AmountUsed = 0;
apply.AddOnlyProperties(o => o.AmountUsed);
//apply.AmountUsed = 0;
//apply.AddOnlyProperties(o => o.AmountUsed);
updateApplys.Add(apply);
//conn.UpdateOnly(apply);
......@@ -750,7 +748,7 @@ namespace Kivii.Finances.Transforms
{
var correlatedInvoices = insertInvoices.Correlating(payments);
insertInvoices.AddRange(correlatedInvoices);
var currentRootKvids = payments.Where(o => o.RootKvid != o.Kvid).ToList().ConvertAll(p => p.RootKvid);
var currentRootKvids = payments.Where(o => o.Type==PaymentType.Split).ToList().ConvertAll(p => p.RootKvid);
if (!currentRootKvids.IsNullOrEmpty()) parentPayments = conn.Select<Payment>(o => o.OffsetKvid == Guid.Empty && Sql.In(o.Kvid, currentRootKvids));
}
#endregion
......@@ -796,7 +794,6 @@ namespace Kivii.Finances.Transforms
return rtns;
}
}
#endregion
}
......@@ -11,7 +11,7 @@ namespace Kivii.Finances.Transforms
{
[Api(Description = "开票申请查询")]
[RequiresAnyRole(SystemRoles.Everyone)]
public class InvoiceApplyQueryEx:RestfulExecution<InvoiceApply>
public class InvoiceApplyQueryEx : RestfulExecution<InvoiceApply>
{
#region QueryArgs
public virtual int? Skip { get; set; }
......@@ -54,4 +54,8 @@ namespace Kivii.Finances.Transforms
[RequiresAnyRole(SystemRoles.Everyone)]
public class InvoiceApplyRead : RestfulRead<InvoiceApply>
{ }
[RequiresAnyRole(SystemRoles.Everyone)]
public class InvoiceApplyDetailQuery : RestfulQuery<InvoiceApplyDetail>
{ }
}
......@@ -17,16 +17,11 @@ namespace Kivii.Finances.Transforms
{
public List<Guid> SettlementKvids { get; set; }
public List<PayingMethod> PayingMethods { get; set; }//付款方式,支持组合付款
public Pay Item { get; set; }
private static MethodInfo _realMethod = null;
public override object OnExecution(IRequest req, IResponse res)
{
SettlementKvids.ThrowIfNullOrEmpty("未传入结算信息,无法付款登记!");
Item.ThrowIfNull("未传入付款登记信息!");
Item.PayerName.ThrowIfNullOrEmpty("未传入付款单位!");
Item.PayeeName.ThrowIfNullOrEmpty("未传入收款单位!");
Item.Currency.ThrowIfNull("货币单位不能为空!");
PayingMethods.ThrowIfNullOrEmpty("未传入付款登记方式!");
PayingMethods.Exists(o => o.Type == PayType.Unsupported).ThrowIfTrue("存在不支持的付款登记方式!");
PayingMethods.Exists(o => o.Kvid == Guid.Empty).ThrowIfTrue("付款登记Kvid不能为空!");
......@@ -38,7 +33,11 @@ namespace Kivii.Finances.Transforms
settlements.ThrowIfNullOrEmpty("未找到结算单!");
if (settlements.Count != SettlementKvids.Count) throw new Exception("所选结算项与实际结算项不符合!");
if (settlements.Exists(o => o.OffsetKvid != Guid.Empty)) throw new Exception("所选结算项存在已作废项!");
if (settlements.Exists(o => o.PayKvid != Guid.Empty)) throw new Exception("所选结算项存在已付款登记!");
if (settlements.Exists(o => o.AmountPayment == o.Amount)) throw new Exception("所选结算项存在已付款登记!");
(settlements.ConvertAll(o => o.Currency).Distinct().ToList().Count != 1).ThrowIfTrue("存在不相符的货币单位!");
var currency = settlements.ConvertAll(o => o.Currency).Distinct().ToList()[0];
(currency == CurrencyUnit.Unsupported).ThrowIfTrue("不支持的货币单位!");
var amountSettlement = settlements.Sum(o => o.Amount);
var amountSettlementPlan = settlements.Sum(o => o.AmountPlan);
(amountMethod != amountSettlement).ThrowIfTrue("所选结算总金额与付款总金额不等!");
......@@ -46,29 +45,8 @@ namespace Kivii.Finances.Transforms
var rtns = new RestfulExecutionResponse<Pay>();
rtns.Results = new List<Pay>();
var payKvid = Guid.NewGuid();
#region 创建支付单
Item.OwnerKvid = KiviiContext.CurrentMember.DepartmentKvid;
Item.OwnerName = KiviiContext.CurrentMember.DepartmentName;
Item.OperateTime = DateTime.Now;
Item.OperatorKvid = KiviiContext.CurrentMember.Kvid;
Item.OperatorName = KiviiContext.CurrentMember.FullName;
Item.Kvid = payKvid;
Item.SerialNumber = string.Empty;
Item.AmountSettlement = amountSettlement;
Item.Amount = 0;
Item.AmountDiscount = 0;
Item.AmountPayment = 0;
#endregion
foreach (var item in settlements)//更新PayKvid
{
item.PayKvid = payKvid;
item.AddOnlyProperties(o => o.PayKvid);
}
var accountBiz = Item.Currency.GetBizAccount();//conn.Single<Account>(o => o.OwnerKvid == KiviiContext.CurrentMember.OrganizationKvid && o.Type == AccountType.Biz && o.Currency == Item.Currency);
accountBiz.ThrowIfNull($"未能正确获取系统{Item.Currency}业务账户!请联系管理员!");
var accountBalance = accountBiz.Currency.GetBalanceAccount();
accountBalance.ThrowIfNull($"未能正确获取系统{accountBiz.Currency}平衡账户!请联系管理员!");
var accountBiz = currency.GetBizAccount();//conn.Single<Account>(o => o.OwnerKvid == KiviiContext.CurrentMember.OrganizationKvid && o.Type == AccountType.Biz && o.Currency == Item.Currency);
accountBiz.ThrowIfNull($"未能正确获取系统{currency}业务账户!请联系管理员!");
if (PayingMethods.Count == 1)//单笔付款登记
{
......@@ -77,37 +55,30 @@ namespace Kivii.Finances.Transforms
{
var payment = conn.SingleById<Payment>(payingMethod.Kvid);
payment.ThrowIfNull("所选付款数据不存在!");
(payment.Currency != Item.Currency).ThrowIfTrue("存在不相符的货币单位!");
(payment.Currency != currency).ThrowIfTrue("存在不相符的货币单位!");
if (payment.Type != PaymentType.Split && payment.Type != PaymentType.Pos && payment.Type != PaymentType.Cash && payment.Type != PaymentType.AliPay && payment.Type != PaymentType.WeChat) throw new Exception("请选择正确的付款方式!");
if (payment.Amount - payment.AmountUsed < amountSettlement) throw new Exception($"所选付款方式余额不足,可用余额:{payment.Amount - payment.AmountUsed}");
(payment.AmountInvoice != payment.Amount).ThrowIfTrue("所选到账尚未开票,请先开票后再分摊!");
var dynamicSplitPayment = Item.Paying(payment, accountBalance, accountBiz);//insert
var accountDetails = dynamicSplitPayment.Using(accountBalance, accountBiz);//insert
var payments = new List<Payment>();
payments.Add(dynamicSplitPayment);
var payPayments = payments.Correlating(settlements);//建立Payment和Settlement关系,更新Settlement的AmountPayment值
var dynamicPayPayment = settlements.Paying(payment, accountBiz, out var pays, out var accountDetail);
var trans = conn.OpenTransaction();
List<IDbTransaction> subTrans = new List<IDbTransaction>();
try
{
conn.Insert(Item);//创建付款单
rtns.Results.Add(Item);
dynamicSplitPayment.SerialNumber = payment.GetSubSerialNumber(conn);
conn.Insert(dynamicSplitPayment);//创建DynamicSplitPayment
accountDetails.ForEach(o => o.Insert(conn));//创建账户明细
payment.RecalculateAmountUsed(conn);//重新统计到账的使用情况
foreach (var item in payPayments)
foreach (var item in pays)
{
item.SerialNumber = payment.GetSubSerialNumber(conn);
conn.Insert(item);
rtns.Results.Add(item);
}
dynamicPayPayment.SerialNumber = payment.GetSubSerialNumber(conn);
conn.Insert(dynamicPayPayment);//创建DynamicSplitPayment
accountDetail.Insert(conn);
payment.RecalculateAmountUsed(conn);//重新统计到账的使用情况
#region 同步更新泛型Settlement表中数据
foreach (var item in settlements)
{
conn.UpdateOnly(item);//更新了Paykvid和AmountPayment
conn.UpdateOnly(item);//更新了AmountPayment
}
var groupSettlement = settlements.GroupBy(o => o.BizType);
if (_realMethod == null)
......@@ -139,29 +110,21 @@ namespace Kivii.Finances.Transforms
{
var account = conn.SingleById<Account>(payingMethod.Kvid);
account.ThrowIfNull("未找到所选账户!");
(account.Currency != Item.Currency).ThrowIfTrue("存在不相符的货币单位!");
(account.Currency != currency).ThrowIfTrue("存在不相符的货币单位!");
(account.Type != AccountType.Deposit).ThrowIfTrue("请选择正确的客户存款账户!");
(account.Amount + account.CreditLine < amountSettlement).ThrowIfTrue($"所选付款方式余额不足,可用余额:{account.Amount + account.CreditLine}");
var dynamicSplitPayment = Item.Paying(account, accountBiz);//insert
var accountDetails = dynamicSplitPayment.Using(account, accountBiz);//insert
var payments = new List<Payment>();
payments.Add(dynamicSplitPayment);
var payPayments = payments.Correlating(settlements);//建立Payment和Settlement关系,更新Settlement的AmountPayment值
var accountDetails = settlements.Paying(account, accountBiz, out var pays);
var trans = conn.OpenTransaction();
List<IDbTransaction> subTrans = new List<IDbTransaction>();
try
{
conn.Insert(Item);//创建付款单
rtns.Results.Add(Item);
conn.Insert(dynamicSplitPayment);//创建DynamicSplitPayment
accountDetails.ForEach(o => o.Insert(conn));//创建账户明细
foreach (var item in payPayments)
foreach (var item in pays)
{
item.SerialNumber = dynamicSplitPayment.GetSubSerialNumber(conn);
conn.Insert(item);
rtns.Results.Add(item);
}
accountDetails.ForEach(o => o.Insert(conn));//创建账户明细
#region 同步更新泛型Settlement表中数据
foreach (var item in settlements)
......@@ -198,31 +161,21 @@ namespace Kivii.Finances.Transforms
{
var discountAccount = conn.SingleById<Account>(payingMethod.Kvid);
discountAccount.ThrowIfNull("未找到所选账户!");
(discountAccount.Currency != Item.Currency).ThrowIfTrue("存在不相符的货币单位!");
(discountAccount.Currency != currency).ThrowIfTrue("存在不相符的货币单位!");
(discountAccount.Type != AccountType.Discount).ThrowIfTrue("请选择正确的折扣账户!");
(discountAccount.OwnerKvid != KiviiContext.CurrentMember.DepartmentKvid).ThrowIfTrue("存在非本部门的折扣账户!");
var dynamicSplitPayment = Item.Paying(discountAccount, accountBiz);//insert
var discount = Item.Discount(discountAccount, amountSettlement, payingMethod.Remark);
var accountDetails = dynamicSplitPayment.Using(discountAccount, accountBiz);//insert
var payments = new List<Payment>();
payments.Add(dynamicSplitPayment);
var payPayments = payments.Correlating(settlements);//建立Payment和Settlement关系,更新Settlement的AmountPayment值
var accountDetails = settlements.Paying(discountAccount, accountBiz, out var pays);
var trans = conn.OpenTransaction();
List<IDbTransaction> subTrans = new List<IDbTransaction>();
try
{
conn.Insert(Item);//创建付款单
conn.Insert(discount);//创建折扣日志
rtns.Results.Add(Item);
conn.Insert(dynamicSplitPayment);//创建DynamicSplitPayment
accountDetails.ForEach(o => o.Insert(conn));//创建账户明细
foreach (var item in payPayments)
foreach (var item in pays)
{
item.SerialNumber = dynamicSplitPayment.GetSubSerialNumber(conn);
conn.Insert(item);
rtns.Results.Add(item);
}
accountDetails.ForEach(o => o.Insert(conn));//创建账户明细
#region 同步更新泛型Settlement表中数据
foreach (var item in settlements)
......@@ -259,18 +212,18 @@ namespace Kivii.Finances.Transforms
}
else//组合付款登记
{
var paymentKvids = PayingMethods.Where(o => o.Type == PayType.Payment).ToList();
var accountKvids = PayingMethods.Where(o => o.Type == PayType.Account).ToList();
var discountKvids = PayingMethods.Where(o => o.Type == PayType.Discount).ToList();
var paymentKvids = PayingMethods.Where(o => o.Type == PayType.Payment).ToList().ConvertAll(o => o.Kvid);
var accountKvids = PayingMethods.Where(o => o.Type == PayType.Account).ToList().ConvertAll(o => o.Kvid);
var discountKvids = PayingMethods.Where(o => o.Type == PayType.Discount).ToList().ConvertAll(o => o.Kvid);
List<Payment> payments = null;
if (!paymentKvids.IsNullOrEmpty())
{
payments = conn.SelectByIds<Payment>(paymentKvids);
payments.ThrowIfNullOrEmpty("未找到所选付款数据!");
payments.Exists(o => o.Currency != Item.Currency).ThrowIfTrue("存在不相符的货币单位!");
payments.Exists(o => o.Currency != currency).ThrowIfTrue("存在不相符的货币单位!");
if (payments.Exists(o => o.Type != PaymentType.Split && o.Type != PaymentType.Pos && o.Type != PaymentType.Cash && o.Type != PaymentType.AliPay && o.Type != PaymentType.WeChat)) throw new Exception("请选择正确的付款方式!");
if (payments.Exists(o => (o.Amount - o.AmountUsed) <= 0)) throw new Exception($"所选付款方式余额不足!");
if (payments.Exists(o => (o.AmountInvoice != o.Amount))) throw new Exception($"所选付款方式余额不足!");
if (payments.Exists(o => (o.AmountInvoice != o.Amount))) throw new Exception($"所选付款尚未开票!");
}
List<Account> accounts = null;
......@@ -278,7 +231,7 @@ namespace Kivii.Finances.Transforms
{
accounts = conn.SelectByIds<Account>(accountKvids);
accounts.ThrowIfNullOrEmpty("未找到所选账户!");
accounts.Exists(o => o.Currency != Item.Currency).ThrowIfTrue("存在不相符的货币单位!");
accounts.Exists(o => o.Currency != currency).ThrowIfTrue("存在不相符的货币单位!");
if (accounts.Exists(o => o.Type != AccountType.Deposit)) throw new Exception("请选择正确的客户存款账户!");
if (accounts.Exists(o => (o.Amount + o.CreditLine) <= 0)) throw new Exception($"所选付款方式余额不足!");
......@@ -288,15 +241,16 @@ namespace Kivii.Finances.Transforms
{
discounts = conn.SelectByIds<Account>(discountKvids);
discounts.ThrowIfNullOrEmpty("未找到所选账户!");
discounts.Exists(o => o.Currency != Item.Currency).ThrowIfTrue("存在不相符的货币单位!");
discounts.Exists(o => o.Currency != currency).ThrowIfTrue("存在不相符的货币单位!");
if (discounts.Exists(o => o.Type != AccountType.Discount)) throw new Exception("请选择正确的折扣账户!");
if (discounts.Exists(o => o.OwnerKvid != KiviiContext.CurrentMember.DepartmentKvid)) throw new Exception($"存在非本部门的折扣账户!");
}
var dynamicSplitPayments = new List<Payment>();
var allPays = new List<Pay>();
var allAccountDetails = new List<AccountDetail>();
var allDiscounts = new List<Discount>();
//var allDiscounts = new List<Discount>();
if (!payments.IsNullOrEmpty())
{
......@@ -304,10 +258,10 @@ namespace Kivii.Finances.Transforms
{
var payingMethod = PayingMethods.FirstOrDefault(o => o.Kvid == item.Kvid);
if (payingMethod == null) continue;
var dynamicSplitPayment = Item.Paying(item, accountBalance, accountBiz, payingMethod.Amount);//insert
var accountDetails = dynamicSplitPayment.Using(accountBalance, accountBiz);//insert
dynamicSplitPayments.Add(dynamicSplitPayment);
allAccountDetails.AddRange(accountDetails);
var dynamicPayPayment = settlements.Paying(item, accountBiz, out var pays, out var accountDetail, payingMethod.Amount);
allPays.AddRange(pays);
dynamicSplitPayments.Add(dynamicPayPayment);
allAccountDetails.Add(accountDetail);
}
}
if (!accounts.IsNullOrEmpty())
......@@ -316,9 +270,8 @@ namespace Kivii.Finances.Transforms
{
var payingMethod = PayingMethods.FirstOrDefault(o => o.Kvid == item.Kvid);
if (payingMethod == null) continue;
var dynamicSplitPayment = Item.Paying(item, accountBiz, payingMethod.Amount);//insert
var accountDetails = dynamicSplitPayment.Using(item, accountBiz);//insert
dynamicSplitPayments.Add(dynamicSplitPayment);
var accountDetails = settlements.Paying(item, accountBiz, out var pays, payingMethod.Amount);
allPays.AddRange(pays);
allAccountDetails.AddRange(accountDetails);
}
}
......@@ -328,40 +281,31 @@ namespace Kivii.Finances.Transforms
{
var payingMethod = PayingMethods.FirstOrDefault(o => o.Kvid == item.Kvid);
if (payingMethod == null) continue;
var dynamicSplitPayment = Item.Paying(item, accountBiz, payingMethod.Amount);//insert
var discount = Item.Discount(item, amountSettlement, payingMethod.Remark);
var accountDetails = dynamicSplitPayment.Using(item, accountBiz);//insert
allDiscounts.Add(discount);
dynamicSplitPayments.Add(dynamicSplitPayment);
var accountDetails = settlements.Paying(item, accountBiz, out var pays, payingMethod.Amount);
allPays.AddRange(pays);
allAccountDetails.AddRange(accountDetails);
//allDiscounts.Add(discount);
}
}
var payPayments = dynamicSplitPayments.Correlating(settlements);//建立Payment和Settlement关系,更新Settlement的AmountPayment值
var trans = conn.OpenTransaction();
List<IDbTransaction> subTrans = new List<IDbTransaction>();
try
{
conn.Insert(Item);//创建付款单
rtns.Results.Add(Item);
foreach (var item in allDiscounts)
foreach (var item in allPays)
{
conn.Insert(item);//创建折扣日志
conn.Insert(item);
rtns.Results.Add(item);
}
foreach (var item in dynamicSplitPayments)
{
item.SerialNumber = item.GetSubSerialNumber(conn);
conn.Insert(item);//创建DynamicSplitPayment
if (item.RootKvid != item.Kvid) item.RecalculateAmountUsed(conn);//重新统计到账的使用情况
}
allAccountDetails.ForEach(o => o.Insert(conn));//创建账户明细
foreach (var item in payPayments)
foreach (var item in payments)
{
item.SerialNumber = item.GetSubSerialNumber(conn);
conn.Insert(item);
item.RecalculateAmountUsed(conn);
}
#region 同步更新泛型Settlement表中数据
foreach (var item in settlements)
{
......@@ -419,7 +363,6 @@ namespace Kivii.Finances.Transforms
{
var settlement = new EntitySettlement<T>();
settlement.PopulateInstance(item);
settlement.AddOnlyProperties(o => o.PayKvid);
settlement.AddOnlyProperties(o => o.AmountPayment);
connE.UpdateOnly(settlement);
......@@ -440,171 +383,171 @@ namespace Kivii.Finances.Transforms
}
}
[Api(Description = "作废登记")]
[RequiresAnyRole(SystemRoles.Everyone)]
public class PayOffset : RestfulExecution<Pay>
{
public Guid Kvid { get; set; }
public string Remark { get; set; }
private static MethodInfo _realMethod = null;
public override object OnExecution(IRequest req, IResponse res)
{
Kvid.ThrowIfEmpty("未传入要冲账的付款登记!");
var conn = KiviiContext.GetOpenedDbConnection<Pay>();
var pay = conn.SingleById<Pay>(Kvid);
pay.ThrowIfNull("未找到对应数据!");
if (pay.OffsetKvid != Guid.Empty) throw new Exception("已冲账,请勿重复重复操作!");
if (pay.BizKvid != Guid.Empty) throw new Exception("已关联业务,请先解除关联!");
var settlements = conn.Select<Settlement>(o => o.OffsetKvid == Guid.Empty && o.PayKvid == Kvid);//付款登记的结算
var dynamicPayments = conn.Select<Payment>(o => o.OffsetKvid == Guid.Empty && o.BizKvid == Kvid);//使用的付款信息 要作废
List<Payment> offsetPayments = null;//要作废的关联数据
List<Payment> payPayments = null;//要作废的关联数据
List<AccountDetail> allAccountDetails = null;//退回对应账户生成的明细
var offsetPay = pay.Offset($"付款登记作废,:{Remark}");
Account payerAccount = null;
Account payeeAccount = null;
if (!dynamicPayments.IsNullOrEmpty())
{
dynamicPayments.Exists(o => o.Type != PaymentType.DynamicSplit).ThrowIfTrue("存在不正确的付款数据类型!");
dynamicPayments.Exists(o => o.PayerAccountKvid == Guid.Empty || o.PayeeAccountKvid == Guid.Empty).ThrowIfTrue("存在无收付账户信息的记录!");
payPayments = conn.Select<Payment>(o => o.OffsetKvid == Guid.Empty && Sql.In(o.ParentKvid, dynamicPayments.ConvertAll(p => p.Kvid)));
foreach (var dynamicPayment in dynamicPayments)
{
if (payerAccount == null || payerAccount.Kvid != dynamicPayment.PayerAccountKvid)
{
payerAccount = conn.SingleById<Account>(dynamicPayment.PayerAccountKvid);
payerAccount.ThrowIfNull("未找到当前对应账户");
}
if (payeeAccount == null || payeeAccount.Kvid != dynamicPayment.PayeeAccountKvid)
{
payeeAccount = conn.SingleById<Account>(dynamicPayment.PayeeAccountKvid);
payeeAccount.ThrowIfNull("未找到当前对应账户");
}
var accountDetails = dynamicPayment.Using(payeeAccount, payerAccount, $"付款登记作废,:{Remark}");//原路退回对应账户
if (allAccountDetails.IsNullOrEmpty()) allAccountDetails = new List<AccountDetail>();
allAccountDetails.AddRange(accountDetails);
var offsetPayment = dynamicPayment.Offset($"付款登记作废:{Remark}");
if (offsetPayments.IsNullOrEmpty()) offsetPayments = new List<Payment>();
offsetPayments.Add(offsetPayment);
}
}
if (!payPayments.IsNullOrEmpty())
{
foreach (var item in payPayments)
{
var offsetPayment = item.Offset($"付款登记作废:{Remark}");
if (offsetPayments.IsNullOrEmpty()) offsetPayments = new List<Payment>();
offsetPayments.Add(offsetPayment);
}
}
var rtns = new RestfulExecutionResponse<Pay>();
rtns.Results = new List<Pay>();
var trans = conn.OpenTransaction();
List<IDbTransaction> subTrans = new List<IDbTransaction>();
try
{
if (!payPayments.IsNullOrEmpty()) payPayments.ForEach(o => conn.UpdateOnly(o));
if (!offsetPayments.IsNullOrEmpty()) offsetPayments.ForEach(o => conn.Insert(o));
if (!dynamicPayments.IsNullOrEmpty())
{
dynamicPayments.ForEach(o => conn.UpdateOnly(o));
foreach (var item in dynamicPayments)
{
if (item.RootKvid != item.Kvid) item.RecalculateAmountUsed(conn);
}
}
if (!allAccountDetails.IsNullOrEmpty()) allAccountDetails.ForEach(o => o.Insert(conn));
if (!settlements.IsNullOrEmpty())
{
var updateLamda = conn.From<Settlement>();
updateLamda = updateLamda.Update(o => new { o.PayKvid, o.AmountPayment });
updateLamda = updateLamda.Where(o => Sql.In(o.Kvid, settlements.ConvertAll(p => p.Kvid)));
conn.UpdateOnly<Settlement>(new Settlement { PayKvid = Guid.Empty, AmountPayment = 0 }, updateLamda);
var groupSettlement = settlements.GroupBy(o => o.BizType);
if (_realMethod == null)
{
var function = new Func<IDbConnection, List<Settlement>, object>(onExecution<Entity>);
_realMethod = this.GetType().GetMethod(function.Method.Name, BindingFlags.NonPublic | BindingFlags.Instance);
}
foreach (var group in groupSettlement)
{
var entityType = Text.AssemblyUtils.FindType(group.Key);
if (entityType == null) continue;
if (entityType == typeof(Settlement)) continue;
var result = _realMethod.MakeGenericMethod(entityType).Invoke(this, new object[2] { conn, group.ToList() });
if (result != null) subTrans.Add(result as IDbTransaction);
}
}
conn.UpdateOnly(pay);
rtns.Results.Add(pay);
conn.Insert(offsetPay);
trans.Commit();
subTrans.ForEach(o => o?.Commit());
}
catch (Exception ex)
{
trans.Rollback();
subTrans.ForEach(o => o?.Rollback());
throw ex;
}
return rtns;
}
private IDbTransaction onExecution<T>(IDbConnection conn, List<Settlement> settlements) where T : IEntity
{
var connE = KiviiContext.GetOpenedDbConnection<EntitySettlement<T>>();
#region 合并数据库连接,并启用事务
IDbTransaction tranE = null;
if (connE.ConnectionString == conn.ConnectionString)
{
connE.Close();
connE = conn;
}
else
{
tranE = connE.OpenTransaction();
}
#endregion
var updateLamda = connE.From<EntitySettlement<T>>();
updateLamda = updateLamda.Update(o => new { o.PayKvid, o.AmountPayment });
updateLamda = updateLamda.Where(o => Sql.In(o.Kvid, settlements.ConvertAll(p => p.Kvid)));
connE.UpdateOnly<EntitySettlement<T>>(new EntitySettlement<T> { PayKvid = Guid.Empty, AmountPayment = 0 }, updateLamda);
var instance = Activator.CreateInstance(typeof(T)) as IEntityHasPayment;
foreach (var item in settlements)
{
try
{
if (instance != null)
{
instance.Kvid = item.BizKvid;
instance.AmountPayment = 0;
instance.AddOnlyProperties(o => o.AmountPayment);
connE.UpdateOnly(instance);
}
}
catch
{
continue;
}
}
return tranE;
}
}
//[Api(Description = "作废登记")]
//[RequiresAnyRole(SystemRoles.Everyone)]
//public class PayOffset : RestfulExecution<Pay>
//{
// public Guid Kvid { get; set; }
// public string Remark { get; set; }
// private static MethodInfo _realMethod = null;
// public override object OnExecution(IRequest req, IResponse res)
// {
// Kvid.ThrowIfEmpty("未传入要冲账的付款登记!");
// var conn = KiviiContext.GetOpenedDbConnection<Pay>();
// var pay = conn.SingleById<Pay>(Kvid);
// pay.ThrowIfNull("未找到对应数据!");
// if (pay.OffsetKvid != Guid.Empty) throw new Exception("已冲账,请勿重复重复操作!");
// if (pay.BizKvid != Guid.Empty) throw new Exception("已关联业务,请先解除关联!");
// var settlements = conn.Select<Settlement>(o => o.OffsetKvid == Guid.Empty && o.PayKvid == Kvid);//付款登记的结算
// var dynamicPayments = conn.Select<Payment>(o => o.OffsetKvid == Guid.Empty && o.BizKvid == Kvid);//使用的付款信息 要作废
// List<Payment> offsetPayments = null;//要作废的关联数据
// List<Payment> payPayments = null;//要作废的关联数据
// List<AccountDetail> allAccountDetails = null;//退回对应账户生成的明细
// var offsetPay = pay.Offset($"付款登记作废,:{Remark}");
// Account payerAccount = null;
// Account payeeAccount = null;
// if (!dynamicPayments.IsNullOrEmpty())
// {
// dynamicPayments.Exists(o => o.Type != PaymentType.DynamicSplit).ThrowIfTrue("存在不正确的付款数据类型!");
// dynamicPayments.Exists(o => o.PayerAccountKvid == Guid.Empty || o.PayeeAccountKvid == Guid.Empty).ThrowIfTrue("存在无收付账户信息的记录!");
// payPayments = conn.Select<Payment>(o => o.OffsetKvid == Guid.Empty && Sql.In(o.ParentKvid, dynamicPayments.ConvertAll(p => p.Kvid)));
// foreach (var dynamicPayment in dynamicPayments)
// {
// if (payerAccount == null || payerAccount.Kvid != dynamicPayment.PayerAccountKvid)
// {
// payerAccount = conn.SingleById<Account>(dynamicPayment.PayerAccountKvid);
// payerAccount.ThrowIfNull("未找到当前对应账户");
// }
// if (payeeAccount == null || payeeAccount.Kvid != dynamicPayment.PayeeAccountKvid)
// {
// payeeAccount = conn.SingleById<Account>(dynamicPayment.PayeeAccountKvid);
// payeeAccount.ThrowIfNull("未找到当前对应账户");
// }
// var accountDetails = dynamicPayment.Using(payeeAccount, payerAccount, $"付款登记作废,:{Remark}");//原路退回对应账户
// if (allAccountDetails.IsNullOrEmpty()) allAccountDetails = new List<AccountDetail>();
// allAccountDetails.AddRange(accountDetails);
// var offsetPayment = dynamicPayment.Offset($"付款登记作废:{Remark}");
// if (offsetPayments.IsNullOrEmpty()) offsetPayments = new List<Payment>();
// offsetPayments.Add(offsetPayment);
// }
// }
// if (!payPayments.IsNullOrEmpty())
// {
// foreach (var item in payPayments)
// {
// var offsetPayment = item.Offset($"付款登记作废:{Remark}");
// if (offsetPayments.IsNullOrEmpty()) offsetPayments = new List<Payment>();
// offsetPayments.Add(offsetPayment);
// }
// }
// var rtns = new RestfulExecutionResponse<Pay>();
// rtns.Results = new List<Pay>();
// var trans = conn.OpenTransaction();
// List<IDbTransaction> subTrans = new List<IDbTransaction>();
// try
// {
// if (!payPayments.IsNullOrEmpty()) payPayments.ForEach(o => conn.UpdateOnly(o));
// if (!offsetPayments.IsNullOrEmpty()) offsetPayments.ForEach(o => conn.Insert(o));
// if (!dynamicPayments.IsNullOrEmpty())
// {
// dynamicPayments.ForEach(o => conn.UpdateOnly(o));
// foreach (var item in dynamicPayments)
// {
// if (item.RootKvid != item.Kvid) item.RecalculateAmountUsed(conn);
// }
// }
// if (!allAccountDetails.IsNullOrEmpty()) allAccountDetails.ForEach(o => o.Insert(conn));
// if (!settlements.IsNullOrEmpty())
// {
// var updateLamda = conn.From<Settlement>();
// updateLamda = updateLamda.Update(o => new { o.PayKvid, o.AmountPayment });
// updateLamda = updateLamda.Where(o => Sql.In(o.Kvid, settlements.ConvertAll(p => p.Kvid)));
// conn.UpdateOnly<Settlement>(new Settlement { PayKvid = Guid.Empty, AmountPayment = 0 }, updateLamda);
// var groupSettlement = settlements.GroupBy(o => o.BizType);
// if (_realMethod == null)
// {
// var function = new Func<IDbConnection, List<Settlement>, object>(onExecution<Entity>);
// _realMethod = this.GetType().GetMethod(function.Method.Name, BindingFlags.NonPublic | BindingFlags.Instance);
// }
// foreach (var group in groupSettlement)
// {
// var entityType = Text.AssemblyUtils.FindType(group.Key);
// if (entityType == null) continue;
// if (entityType == typeof(Settlement)) continue;
// var result = _realMethod.MakeGenericMethod(entityType).Invoke(this, new object[2] { conn, group.ToList() });
// if (result != null) subTrans.Add(result as IDbTransaction);
// }
// }
// conn.UpdateOnly(pay);
// rtns.Results.Add(pay);
// conn.Insert(offsetPay);
// trans.Commit();
// subTrans.ForEach(o => o?.Commit());
// }
// catch (Exception ex)
// {
// trans.Rollback();
// subTrans.ForEach(o => o?.Rollback());
// throw ex;
// }
// return rtns;
// }
// private IDbTransaction onExecution<T>(IDbConnection conn, List<Settlement> settlements) where T : IEntity
// {
// var connE = KiviiContext.GetOpenedDbConnection<EntitySettlement<T>>();
// #region 合并数据库连接,并启用事务
// IDbTransaction tranE = null;
// if (connE.ConnectionString == conn.ConnectionString)
// {
// connE.Close();
// connE = conn;
// }
// else
// {
// tranE = connE.OpenTransaction();
// }
// #endregion
// var updateLamda = connE.From<EntitySettlement<T>>();
// updateLamda = updateLamda.Update(o => new { o.PayKvid, o.AmountPayment });
// updateLamda = updateLamda.Where(o => Sql.In(o.Kvid, settlements.ConvertAll(p => p.Kvid)));
// connE.UpdateOnly<EntitySettlement<T>>(new EntitySettlement<T> { PayKvid = Guid.Empty, AmountPayment = 0 }, updateLamda);
// var instance = Activator.CreateInstance(typeof(T)) as IEntityHasPayment;
// foreach (var item in settlements)
// {
// try
// {
// if (instance != null)
// {
// instance.Kvid = item.BizKvid;
// instance.AmountPayment = 0;
// instance.AddOnlyProperties(o => o.AmountPayment);
// connE.UpdateOnly(instance);
// }
// }
// catch
// {
// continue;
// }
// }
// return tranE;
// }
//}
[Api(Description = "更新")]
[RequiresAnyRole(SystemRoles.Everyone)]
......
......@@ -26,28 +26,37 @@ namespace Kivii.Finances.Transforms
if (Items.IsNullOrEmpty()) Items = new List<Payment>();
if (Item != null) Items.Add(Item);
if (Items.Exists(o => o.Currency != CurrencyUnit.CNY)) throw new Exception("暂仅支持生成人民币货币单位流水!");
////这两步验证用于验证针对当前登录组织是收款还是付款
//if (Items.Exists(o => o.PayerAccountKvid == Guid.Empty && o.PayeeAccountKvid == Guid.Empty)) throw new Exception("收付款账户不能同时为空!");
//if (Items.Exists(o => o.PayerAccountKvid != Guid.Empty && o.PayeeAccountKvid != Guid.Empty)) throw new Exception("收付款账户不能同时指定!");
var typeBanks = Items.Where(o => o.Type == PaymentType.Bank).ToList();
var typeCashs = Items.Where(o => o.Type == PaymentType.Cash).ToList();
var typePoss = Items.Where(o => o.Type == PaymentType.Pos).ToList();
var conn = KiviiContext.GetOpenedDbConnection<Payment>();
//var allAccountKvids = new List<Guid>();
//allAccountKvids.AddRange(Items.ConvertAll(o => o.PayeeAccountKvid).ToList());
//allAccountKvids.AddRange(Items.ConvertAll(o => o.PayerAccountKvid).ToList());
//allAccountKvids = allAccountKvids.Distinct().ToList();
//var accounts = conn.Select<Account>(o => Sql.In(o.Kvid, allAccountKvids));
//accounts.ThrowIfNullOrEmpty("未找到相关账号!");
var accountBalance = CurrencyUnit.CNY.GetBalanceAccount();
var allAccountDetails = new List<AccountDetail>();
var allAcceptPayments = new List<Payment>();
var allAcceptPays = new List<Pay>();
//生成银行流水
if (!typeBanks.IsNullOrEmpty())
{
var bankAccounts = conn.Select<Account>(o => o.Type == AccountType.Bank && o.Currency == CurrencyUnit.CNY && o.OwnerKvid == KiviiContext.CurrentMember.OrganizationKvid);
if (bankAccounts.IsNullOrEmpty()) throw new Exception("未找到当前登录人所在组织的银行账户!");
foreach (var item in typeBanks)
{
(item.PayeeAccountSerialNumber.IsNullOrEmpty()).ThrowIfTrue("银行流水收款单位PayeeAccountSerialNumber不能为空");
var bankAccount = bankAccounts.FirstOrDefault(o => o.SerialNumber == item.PayeeAccountSerialNumber);
if (bankAccount == null) throw new Exception($"未找到当前银行流水{item.PayerName}[{item.PayeeAccountSerialNumber}]对应系统银行账户!");
if (item.Amount <= 0) continue;
//Account account = null;
//if (item.PayerAccountKvid != Guid.Empty) account = accounts.FirstOrDefault(o => o.Kvid == item.PayerAccountKvid);
//if (item.PayeeAccountKvid != Guid.Empty) account = accounts.FirstOrDefault(o => o.Kvid == item.PayeeAccountKvid);
//if (account == null) continue;
var itemKvid = Guid.NewGuid();
item.AmountInvoice = 0;
item.AmountSplited = 0;
......@@ -68,16 +77,14 @@ namespace Kivii.Finances.Transforms
item.PayerAccountOwnerName = item.PayerAccountOwnerName.IsNullOrEmpty() ? accountBalance.OwnerName : item.PayerAccountOwnerName;
item.PayerAccountSerialNumber = item.PayerAccountSerialNumber.IsNullOrEmpty() ? accountBalance.SerialNumber : item.PayerAccountSerialNumber;
item.PayeeAccountKvid = bankAccount.Kvid;
item.PayeeAccountName = bankAccount.Name;
item.PayeeAccountOwnerName = bankAccount.OwnerName;
item.PayeeAccountSerialNumber = bankAccount.SerialNumber;
item.PayeeAccountKvid = Guid.Empty;
item.OperateTime = (item.OperateTime == DateTime.MinValue ? DateTime.Now : item.OperateTime);
item.OperatorName = KiviiContext.CurrentMember.FullName;
item.OperatorKvid = KiviiContext.CurrentMember.Kvid;
var accountDetails = item.Accept();
var accountDetail = item.Accept(out Pay pay);
allAcceptPayments.Add(item);
allAccountDetails.AddRange(accountDetails);
allAccountDetails.Add(accountDetail);
allAcceptPays.Add(pay);
}
}
......@@ -133,16 +140,14 @@ namespace Kivii.Finances.Transforms
item.PayerAccountOwnerName = item.PayerAccountOwnerName.IsNullOrEmpty() ? cashAccount.OwnerName : item.PayerAccountOwnerName;
item.PayerAccountSerialNumber = item.PayerAccountSerialNumber.IsNullOrEmpty() ? cashAccount.SerialNumber : item.PayerAccountSerialNumber;
item.PayeeAccountKvid = accountBalance.Kvid;
item.PayeeAccountName = accountBalance.Name;
item.PayeeAccountOwnerName = accountBalance.OwnerName;
item.PayeeAccountSerialNumber = accountBalance.SerialNumber;
item.PayeeAccountKvid = Guid.Empty;
item.OperateTime = (item.OperateTime == DateTime.MinValue ? DateTime.Now : item.OperateTime);
item.OperatorName = KiviiContext.CurrentMember.FullName;
item.OperatorKvid = KiviiContext.CurrentMember.Kvid;
var accountDetails = item.Accept();
var accountDetail = item.Accept(out Pay pay);
allAcceptPayments.Add(item);
allAccountDetails.AddRange(accountDetails);
allAccountDetails.Add(accountDetail);
allAcceptPays.Add(pay);
}
}
//生成Pos流水
......@@ -173,16 +178,14 @@ namespace Kivii.Finances.Transforms
item.PayerAccountOwnerName = item.PayerAccountOwnerName.IsNullOrEmpty() ? posAccount.OwnerName : item.PayerAccountOwnerName;
item.PayerAccountSerialNumber = item.PayerAccountSerialNumber.IsNullOrEmpty() ? posAccount.SerialNumber : item.PayerAccountSerialNumber;
item.PayeeAccountKvid = accountBalance.Kvid;
item.PayeeAccountName = accountBalance.Name;
item.PayeeAccountOwnerName = accountBalance.OwnerName;
item.PayeeAccountSerialNumber = accountBalance.SerialNumber;
item.PayeeAccountKvid = Guid.Empty;
item.OperateTime = (item.OperateTime == DateTime.MinValue ? DateTime.Now : item.OperateTime);
item.OperatorName = KiviiContext.CurrentMember.FullName;
item.OperatorKvid = KiviiContext.CurrentMember.Kvid;
var accountDetails = item.Accept();
var accountDetail = item.Accept(out Pay pay);
allAcceptPayments.Add(item);
allAccountDetails.AddRange(accountDetails);
allAccountDetails.Add(accountDetail);
allAcceptPays.Add(pay);
}
}
......@@ -202,6 +205,13 @@ namespace Kivii.Finances.Transforms
}
}
if (!allAccountDetails.IsNullOrEmpty()) allAccountDetails.ForEach(o => o.Insert(conn));
if (!allAcceptPays.IsNullOrEmpty())
{
foreach (var item in allAcceptPays)
{
conn.Insert(item);
}
}
trans.Commit();
}
catch (Exception ex)
......
......@@ -46,58 +46,51 @@ namespace Kivii.Finances.Transforms
if (accountPayee == null) throw new Exception("不存在此账户");
if (accountPayee.Type != AccountType.Cash && accountPayee.Type != AccountType.Pos && accountPayee.Type != AccountType.Deposit && accountPayee.Type != AccountType.Refund) throw new Exception("不支持的账户类型");
var accountPayer = accountPayee.Currency.GetBalanceAccount();
accountPayer.ThrowIfNull($"未能正确获取系统{accountPayee.Currency}平衡账户!请联系管理员!");
//var accountPayer = accountPayee.Currency.GetBalanceAccount();
//accountPayer.ThrowIfNull($"未能正确获取系统{accountPayee.Currency}平衡账户!请联系管理员!");
//生成转账Payment
Payment transfer = null;
//生成账户明细
List<AccountDetail> accountDetails = new List<AccountDetail>();
//存在的父级Payment要更新AmountUsed
Payment parentPayment = null;
List<Pay> pays = new List<Pay>();
//3.
//3
if (payment.Type == PaymentType.UnBiz)
{
if (accountPayee.Type != AccountType.Cash && accountPayee.Type != AccountType.Pos) throw new Exception("非业务收款,仅支持现金或刷卡个人账户充值!");
transfer = payment.Transfer(accountPayee, accountPayer, Amount, $"非业务入账{(Remark.IsNullOrEmpty() ? string.Empty : ":" + Remark)}");
accountDetails = transfer.Using(accountPayer, accountPayee);
transfer = payment.Transfer(accountPayee, Amount, $"非业务入账{(Remark.IsNullOrEmpty() ? string.Empty : ":" + Remark)}", out Pay pay, out AccountDetail accountDetail);
accountDetails.Add(accountDetail);
pays.Add(pay);
}
//2.
//2
else if (payment.Type == PaymentType.Refund)
{
if (accountPayee.Type != AccountType.Refund) throw new Exception("退款收款,仅支持退款账户充值!");
transfer = payment.Transfer(accountPayee, accountPayer, Amount, $"退款入账{(Remark.IsNullOrEmpty() ? string.Empty : ":" + Remark)}");
accountDetails = transfer.Using(accountPayer, accountPayee);
transfer = payment.Transfer(accountPayee, Amount, $"退款入账{(Remark.IsNullOrEmpty() ? string.Empty : ":" + Remark)}", out Pay pay, out AccountDetail accountDetail);
accountDetails.Add(accountDetail);
pays.Add(pay);
}
//1.
//1
else
{
if(accountPayee.Type!=AccountType.Deposit) throw new Exception("业务收款,仅支持客户存款账户充值!");
transfer = payment.Transfer(accountPayee, accountPayer, Amount, $"到账充值{(Remark.IsNullOrEmpty() ? string.Empty : ":" + Remark)}");
accountDetails = transfer.Using(accountPayer, accountPayee);
if (accountPayee.Type != AccountType.Deposit) throw new Exception("业务收款,仅支持客户存款账户充值!");
transfer = payment.Transfer(accountPayee, Amount, $"到账充值{(Remark.IsNullOrEmpty() ? string.Empty : ":" + Remark)}", out Pay pay, out AccountDetail accountDetail);
accountDetails.Add(accountDetail);
pays.Add(pay);
}
if (payment.ParentKvid != Guid.Empty) parentPayment = conn.SingleById<Payment>(payment.ParentKvid);
var rtns = new RestfulExecutionResponse<Payment>();
rtns.Results = new List<Payment>();
var trans = conn.OpenTransaction();
try
{
if (transfer != null)
{
transfer.SerialNumber = transfer.GetSubSerialNumber(conn);
conn.Insert(transfer);
rtns.Results.Add(transfer);
}
accountDetails.ForEach(o => o.Insert(conn));
conn.UpdateOnly(payment);
if (parentPayment != null)
{
parentPayment.AmountUsed += transfer.Amount;
parentPayment.AddOnlyProperties(o => o.AmountUsed);
conn.UpdateOnly(parentPayment);
}
payment.RecalculateAmountUsed(conn);//重新计算AmountUsed!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//if (parentPayment != null) conn.UpdateOnly(parentPayment);
trans.Commit();
}
catch (Exception ex)
......@@ -133,33 +126,24 @@ namespace Kivii.Finances.Transforms
var parentPayments = conn.SelectByIds<Payment>(payments.ConvertAll(o => o.ParentKvid));
parentPayments.ThrowIfNullOrEmpty("未找到夫级付款,数据错误!");
var rootPayments = conn.SelectByIds<Payment>(parentPayments.ConvertAll(o => o.ParentKvid));
//var rootPayments = conn.SelectByIds<Payment>(parentPayments.ConvertAll(o => o.ParentKvid));
var accountPayees = conn.SelectByIds<Account>(payments.ConvertAll(o => o.PayeeAccountKvid));
accountPayees.ThrowIfNullOrEmpty("未找到收款账户!");
var accountPayers = conn.SelectByIds<Account>(payments.ConvertAll(o => o.PayerAccountKvid));
accountPayers.ThrowIfNullOrEmpty("未找到付款账户!");
//新生成的Offset数据
var offsets = new List<Payment>();
//原Transfer数据更新Offset
var orginOffsets = new List<Payment>();
//生成的账户明细
var totalAccountDetails = new List<AccountDetail>();
//Parent和Root 更新AmountUsed
var roots = new List<Payment>();
var allPays = conn.Select<Pay>(o => o.FromType == PayType.Payment && Sql.In(o.FromKvid, payments.ConvertAll(p => p.Kvid)));
var offsets = new List<Payment>();//新生成的Offset数据
var orginOffsets = new List<Payment>();//原Transfer数据更新Offset
var payOffsets = new List<Pay>();//新生成Offset的Pay
var orginPayOffsets = new List<Pay>();//原Pay作废
var totalAccountDetails = new List<AccountDetail>();//生成的账户明细
foreach (var item in payments)
{
var parent = parentPayments.FirstOrDefault(o => o.Kvid == item.ParentKvid);
parent.ThrowIfNull($"未找到{item.SerialNumber}当前的到账上级节点!");
var root = rootPayments.FirstOrDefault(o => o.Kvid == parent.ParentKvid);
//var parent = parentPayments.FirstOrDefault(o => o.Kvid == item.ParentKvid);
//parent.ThrowIfNull($"未找到{item.SerialNumber}当前的到账上级节点!");
var accountPayee = accountPayees.FirstOrDefault(o => o.Kvid == item.PayeeAccountKvid);
accountPayee.ThrowIfNull($"未找到{item.SerialNumber}对应收款账户!");
var accountPayer = accountPayers.FirstOrDefault(o => o.Kvid == item.PayerAccountKvid);
accountPayer.ThrowIfNull($"未找到{item.SerialNumber}对应付款账户!");
#region 新增流水
#region 新增流水,原收款账户新增扣款明细
var payeeAaccountDetail = new AccountDetail();
payeeAaccountDetail.AccountKvid = accountPayee.Kvid;
payeeAaccountDetail.BizId = item.SerialNumber;
......@@ -174,66 +158,30 @@ namespace Kivii.Finances.Transforms
payeeAaccountDetail.PayeeKvid = item.PayerKvid;
payeeAaccountDetail.PayeeName = item.PayerName;
payeeAaccountDetail.PayeeAccountKvid = accountPayer.Kvid;
payeeAaccountDetail.PayeeAccountName = accountPayer.Name;
payeeAaccountDetail.PayeeAccountSerialNumber = accountPayer.SerialNumber;
//payeeAaccountDetail.PayeeAccountKvid = accountPayer.Kvid;
//payeeAaccountDetail.PayeeAccountName = accountPayer.Name;
//payeeAaccountDetail.PayeeAccountSerialNumber = accountPayer.SerialNumber;
payeeAaccountDetail.AmountPayment = item.Amount;
payeeAaccountDetail.Summary = "撤销转账";
#endregion
totalAccountDetails.Add(payeeAaccountDetail);
#region 新增流水
var payerAaccountDetail = new AccountDetail();
payerAaccountDetail.AccountKvid = accountPayer.Kvid;
payerAaccountDetail.BizId = item.SerialNumber;
payerAaccountDetail.BizKvid = item.Kvid;
payerAaccountDetail.BizType = typeof(Payment).FullName;
payerAaccountDetail.PayerKvid = item.PayeeKvid;
payerAaccountDetail.PayerName = item.PayeeName;
payerAaccountDetail.PayerAccountKvid = accountPayee.Kvid;
payerAaccountDetail.PayerAccountName = accountPayee.Name;
payerAaccountDetail.PayerAccountSerialNumber = accountPayee.SerialNumber;
payerAaccountDetail.PayeeKvid = item.PayerKvid;
payerAaccountDetail.PayeeName = item.PayerName;
payerAaccountDetail.PayeeAccountKvid = accountPayer.Kvid;
payerAaccountDetail.PayeeAccountName = accountPayer.Name;
payerAaccountDetail.PayeeAccountSerialNumber = accountPayer.SerialNumber;
payerAaccountDetail.AmountPayment = item.Amount;
payerAaccountDetail.Summary = "撤销转账";
#endregion
totalAccountDetails.Add(payerAaccountDetail);
var offset = item.Offset($"撤销转账");
var offset = item.Offset($"撤销转账");//tranfer的Payment作废
offsets.Add(offset);
orginOffsets.Add(item);
if (roots.Exists(o => o.Kvid == parent.Kvid))
if (!allPays.IsNullOrEmpty())//Transfer对应的Pay也要作废
{
var exist = roots.FirstOrDefault(o => o.Kvid == parent.Kvid);
exist.AmountUsed -= item.Amount;
}
else
var currentPays = allPays.Where(o => o.FromKvid == item.Kvid).ToList();
if (!currentPays.IsNullOrEmpty())
{
parent.AmountUsed -= item.Amount;
parent.AddOnlyProperties(o => o.AmountUsed);
roots.Add(parent);
}
if (root != null)
{
if (roots.Exists(o => o.Kvid == root.Kvid))
foreach (var pay in currentPays)
{
var exist = roots.FirstOrDefault(o => o.Kvid == root.Kvid);
exist.AmountUsed -= item.Amount;
var offsetPay = pay.Offset($"撤销转账");
payOffsets.Add(offsetPay);
orginPayOffsets.Add(pay);
}
else
{
root.AmountUsed -= item.Amount;
root.AddOnlyProperties(o => o.AmountUsed);
roots.Add(root);
}
}
}
......@@ -245,25 +193,35 @@ namespace Kivii.Finances.Transforms
try
{
foreach (var item in orginOffsets)
{
conn.UpdateOnly(item);
rtns.Results.Add(item);
}
foreach(var offset in offsets)
{
conn.Insert(offset);
}
foreach (var item in orginOffsets)
foreach (var item in orginPayOffsets)
{
conn.UpdateOnly(item);
rtns.Results.Add(item);
}
foreach(var item in totalAccountDetails)
foreach (var offset in payOffsets)
{
conn.Insert(offset);
}
foreach (var item in totalAccountDetails)
{
item.Insert(conn);
}
foreach( var item in roots)
foreach( var item in parentPayments)
{
conn.UpdateOnly(item);
item.RecalculateAmountUsed(conn);
}
trans.Commit();
......
......@@ -35,99 +35,94 @@ namespace Kivii.Finances.Transforms
//查询当前项的拆分子项List
if (conn.Exists<Payment>(o => Sql.In(o.ParentKvid, payments.ConvertAll(p => p.Kvid)) && o.OffsetKvid == Guid.Empty)) throw new Exception("不可冲账,此到账存在未冲账子项!");
if (conn.Exists<InvoiceApply>(o => Sql.In(o.BizKvid, payments.ConvertAll(p => p.Kvid)) && o.OffsetKvid == Guid.Empty)) throw new Exception("申请开票中,不可冲账!");
(payments.Exists(o => o.PayeeAccountKvid==Guid.Empty)).ThrowIfTrue("收款账户(PayeeAccountKvid)为空!");
(payments.Exists(o => o.PayerAccountKvid == Guid.Empty)).ThrowIfTrue("付款账户(PayerAccountKvid)为空!");
var allPays = conn.Select<Pay>(o => o.ToType == PayType.Payment && Sql.In(o.ToKvid, payments.ConvertAll(p => p.Kvid)));
List<Payment> offsets = new List<Payment>();
List<Account> accountPayees = conn.SelectByIds<Account>(payments.ConvertAll(p => p.PayeeAccountKvid));
List<Payment> offsetPayments = new List<Payment>();
var payOffsets = new List<Pay>();//新生成Offset的Pay
var orginPayOffsets = new List<Pay>();//原Pay作废
List<Account> accountPayers = conn.SelectByIds<Account>(payments.ConvertAll(p => p.PayerAccountKvid));
foreach (var payment in payments)
{
var accountPayee = conn.SingleById<Account>(payment.PayeeAccountKvid);
var accountPayer = conn.SingleById<Account>(payment.PayerAccountKvid);
if (accountPayee == null) accountPayee = payment.Currency.GetBalanceAccount();
if (accountPayer == null) accountPayer = payment.Currency.GetBalanceAccount();
var accountPayer = accountPayers.FirstOrDefault(o => o.Kvid == payment.PayerAccountKvid);
if (accountPayer == null) continue;
var offset = payment.Offset($"冲账:{Remark}");
offsets.Add(offset);
offsetPayments.Add(payment);
if (!allPays.IsNullOrEmpty())//Transfer对应的Pay也要作废
{
var currentPays = allPays.Where(o => o.ToKvid == payment.Kvid).ToList();
if (!currentPays.IsNullOrEmpty())
{
foreach (var pay in currentPays)
{
var offsetPay = pay.Offset($"到账冲账");
payOffsets.Add(offsetPay);
orginPayOffsets.Add(pay);
}
}
}
}
var rtns = new RestfulExecutionResponse<Payment>();
rtns.Results = new List<Payment>();
using (var trans = conn.OpenTransaction())
var trans = conn.OpenTransaction();
try
{
foreach (var item in payments)
foreach (var item in offsetPayments)
{
conn.UpdateOnly(item);
rtns.Results.Add(item);
Account accountPayee = null;
Account accountPayer = null;
if (!accountPayees.IsNullOrEmpty()) accountPayee = accountPayees.FirstOrDefault(o => o.Kvid == item.PayeeAccountKvid);
if (!accountPayers.IsNullOrEmpty()) accountPayer = accountPayers.FirstOrDefault(o => o.Kvid == item.PayerAccountKvid);
if (accountPayee == null) accountPayee = item.Currency.GetBalanceAccount();
if (accountPayer == null) accountPayer = item.Currency.GetBalanceAccount();
if (accountPayee != null)
{
#region 新增流水
var newAccountDetail = new AccountDetail();
newAccountDetail.AccountKvid = accountPayee.Kvid;
newAccountDetail.BizId = item.SerialNumber;
newAccountDetail.BizKvid = item.Kvid;
newAccountDetail.BizType = typeof(Payment).FullName;
newAccountDetail.PayerKvid = item.PayeeKvid;
newAccountDetail.PayerName = item.PayeeName;
newAccountDetail.PayerAccountKvid = accountPayee.Kvid;
newAccountDetail.PayerAccountName = accountPayee.Name;
newAccountDetail.PayerAccountSerialNumber = accountPayee.SerialNumber;
newAccountDetail.PayeeKvid = item.PayerKvid;
newAccountDetail.PayeeName = item.PayerName;
newAccountDetail.PayeeAccountKvid = accountPayer.Kvid;
newAccountDetail.PayeeAccountName = accountPayer.Name;
newAccountDetail.PayeeAccountSerialNumber = accountPayer.SerialNumber;
newAccountDetail.AmountPayment = item.Amount;
newAccountDetail.Summary = "冲账:" + Remark;
#endregion
newAccountDetail.Insert(conn);
}
if (accountPayer != null)
{
#region 新增流水
var accountDetailBalance = new AccountDetail();
accountDetailBalance.AccountKvid = accountPayer.Kvid;
accountDetailBalance.BizId = item.SerialNumber;
accountDetailBalance.BizKvid = item.Kvid;
accountDetailBalance.BizType = typeof(Payment).FullName;
accountDetailBalance.PayerKvid = item.PayeeKvid;
accountDetailBalance.PayerName = item.PayeeName;
accountDetailBalance.PayerAccountKvid = accountPayee.Kvid;
accountDetailBalance.PayerAccountName = accountPayee.Name;
accountDetailBalance.PayerAccountSerialNumber = accountPayee.SerialNumber;
accountDetailBalance.PayeeKvid = item.PayerKvid;
accountDetailBalance.PayeeName = item.PayerName;
accountDetailBalance.PayeeAccountKvid = accountPayer.Kvid;
accountDetailBalance.PayeeAccountName = accountPayer.Name;
accountDetailBalance.PayeeAccountSerialNumber = accountPayer.SerialNumber;
accountDetailBalance.AmountPayment = item.Amount;
accountDetailBalance.Summary = "冲账:" + Remark;
var accountDetail = new AccountDetail();
accountDetail.AccountKvid = accountPayer.Kvid;
accountDetail.BizId = item.SerialNumber;
accountDetail.BizKvid = item.Kvid;
accountDetail.BizType = typeof(Payment).FullName;
accountDetail.PayerKvid = item.PayeeKvid;
accountDetail.PayerName = item.PayeeName;
accountDetail.PayerAccountKvid = Guid.Empty;
accountDetail.PayerAccountName = item.PayeeAccountName;
accountDetail.PayerAccountSerialNumber = item.PayeeAccountSerialNumber;
accountDetail.PayeeKvid = item.PayerKvid;
accountDetail.PayeeName = item.PayerName;
accountDetail.PayeeAccountKvid = accountPayer.Kvid;
accountDetail.PayeeAccountName = accountPayer.Name;
accountDetail.PayeeAccountSerialNumber = accountPayer.SerialNumber;
accountDetail.AmountPayment = item.Amount;
accountDetail.Summary = "冲账:" + Remark;
#endregion
accountDetailBalance.Insert(conn);
accountDetail.Insert(conn);
}
}
foreach (var item in offsets)
{
conn.Insert(item);
}
foreach (var item in orginPayOffsets)
{
conn.UpdateOnly(item);
}
foreach (var offset in payOffsets)
{
conn.Insert(offset);
}
trans.Commit();
}
catch (Exception ex)
{
trans.Rollback();
throw ex;
}
return rtns;
}
}
......@@ -153,100 +148,54 @@ namespace Kivii.Finances.Transforms
(payments.Exists(o => o.BizKvid != Guid.Empty)).ThrowIfTrue("收付款已关联业务!请先解除关联!");
(payments.Exists(o => o.Amount <= 0)).ThrowIfTrue("请选择正确的到账流水进行撤销!");
(payments.Exists(o => o.OffsetKvid == Guid.Empty)).ThrowIfTrue("收付款未冲账,无需撤销");
(payments.Exists(o => o.PayeeAccountKvid == Guid.Empty)).ThrowIfTrue("收款账户(PayeeAccountKvid)为空!");
//(payments.Exists(o => o.PayeeAccountKvid == Guid.Empty)).ThrowIfTrue("收款账户(PayeeAccountKvid)为空!");
(payments.Exists(o => o.PayerAccountKvid == Guid.Empty)).ThrowIfTrue("付款账户(PayerAccountKvid)为空!");
var offsets = conn.SelectByIds<Payment>(payments.ConvertAll(o=>o.OffsetKvid));
List<Account> accountPayees = conn.SelectByIds<Account>(payments.ConvertAll(p => p.PayeeAccountKvid));
List<Account> accountPayers = conn.SelectByIds<Account>(payments.ConvertAll(p => p.PayerAccountKvid));
var allAccountDetails = new List<AccountDetail>();
var allAcceptPayments = new List<Payment>();
var allAcceptPays = new List<Pay>();
foreach (var item in payments)
{
//payment 取消OffsetKvid
item.OffsetKvid = Guid.Empty;
item.AddOnlyProperties(o => o.OffsetKvid);
item.Remark = string.Empty;
item.AddOnlyProperties(o => o.Remark);
var accountDetail = item.Accept(out Pay pay);
allAcceptPayments.Add(item);
allAccountDetails.Add(accountDetail);
allAcceptPays.Add(pay);
}
var rtns = new RestfulExecutionResponse<Payment>();
rtns.Results = new List<Payment>();
using (var trans = conn.OpenTransaction())
var trans = conn.OpenTransaction();
try
{
foreach (var item in payments)
if (!allAcceptPayments.IsNullOrEmpty())
{
foreach (var item in allAcceptPayments)
{
conn.UpdateOnly(item);
rtns.Results.Add(item);
Account accountPayee = null;
Account accountPayer = null;
if (!accountPayees.IsNullOrEmpty()) accountPayee = accountPayees.FirstOrDefault(o => o.Kvid == item.PayeeAccountKvid);
if (!accountPayers.IsNullOrEmpty()) accountPayer = accountPayers.FirstOrDefault(o => o.Kvid == item.PayerAccountKvid);
if (accountPayee == null) accountPayee = item.Currency.GetBalanceAccount();
if (accountPayer == null) accountPayer = item.Currency.GetBalanceAccount();
if (accountPayee != null)
{
#region 新增流水
var newAccountDetail = new AccountDetail();
newAccountDetail.AccountKvid = accountPayee.Kvid;
newAccountDetail.BizId = item.SerialNumber;
newAccountDetail.BizKvid = item.Kvid;
newAccountDetail.BizType = typeof(Payment).FullName;
newAccountDetail.PayeeKvid = item.PayeeKvid;
newAccountDetail.PayeeName = item.PayeeName;
newAccountDetail.PayeeAccountKvid = accountPayee.Kvid;
newAccountDetail.PayeeAccountName = accountPayee.Name;
newAccountDetail.PayeeAccountSerialNumber = accountPayee.SerialNumber;
newAccountDetail.PayerKvid = item.PayerKvid;
newAccountDetail.PayerName = item.PayerName;
newAccountDetail.PayerAccountKvid = accountPayer.Kvid;
newAccountDetail.PayerAccountName = accountPayer.Name;
newAccountDetail.PayerAccountSerialNumber = accountPayer.SerialNumber;
newAccountDetail.AmountPayment = item.Amount;
newAccountDetail.Summary = "撤销冲账";
#endregion
newAccountDetail.Insert(conn);
}
if (accountPayer != null)
{
#region 新增流水
var accountDetailBalance = new AccountDetail();
accountDetailBalance.AccountKvid = accountPayer.Kvid;
accountDetailBalance.BizId = item.SerialNumber;
accountDetailBalance.BizKvid = item.Kvid;
accountDetailBalance.BizType = typeof(Payment).FullName;
accountDetailBalance.PayeeKvid = item.PayeeKvid;
accountDetailBalance.PayeeName = item.PayeeName;
accountDetailBalance.PayeeAccountKvid = accountPayee.Kvid;
accountDetailBalance.PayeeAccountName = accountPayee.Name;
accountDetailBalance.PayeeAccountSerialNumber = accountPayee.SerialNumber;
accountDetailBalance.PayerKvid = item.PayerKvid;
accountDetailBalance.PayerName = item.PayerName;
accountDetailBalance.PayerAccountKvid = accountPayer.Kvid;
accountDetailBalance.PayerAccountName = accountPayer.Name;
accountDetailBalance.PayerAccountSerialNumber = accountPayer.SerialNumber;
accountDetailBalance.AmountPayment = item.Amount;
accountDetailBalance.Summary = "撤销冲账";
#endregion
accountDetailBalance.Insert(conn);
}
}
if (!offsets.IsNullOrEmpty())
if (!allAccountDetails.IsNullOrEmpty()) allAccountDetails.ForEach(o => o.Insert(conn));
if (!allAcceptPays.IsNullOrEmpty())
{
foreach (var item in offsets)
foreach (var item in allAcceptPays)
{
item.Status = -1;
item.AddOnlyProperties(o => o.Status);
conn.UpdateOnly(item);
conn.Insert(item);
}
}
trans.Commit();
}
catch (Exception ex)
{
trans.Rollback();
throw ex;
}
return rtns;
}
}
......
......@@ -72,6 +72,8 @@ namespace Kivii.Finances.Transforms
if (Amount <= 0) throw new Exception("金额不能为小于0!");
if (payment.AmountSplited == payment.Amount) throw new Exception("无剩余收款可认领!");
if (payment.AmountSplited + Amount > payment.Amount) throw new Exception("认领金额超出范围!");
var amountSplit = conn.Scalar<Payment, decimal>(o => Sql.Sum(o.Amount), p => p.ParentKvid == payment.Kvid && p.OffsetKvid == Guid.Empty);
if (amountSplit + Amount > payment.Amount) throw new Exception("认领金额超出范围!");
bank = payment;
split = bank.BizSplit(Amount, ownerKvid, ownerName, conn);
......@@ -120,8 +122,7 @@ namespace Kivii.Finances.Transforms
conn.Insert(split);
rtns.Results.Add(split);
}
if (bank != null) conn.UpdateOnly(bank);
payment.RecalculateAmountSplit(conn);
if (log != null) conn.Insert(log);
}
......@@ -257,7 +258,7 @@ namespace Kivii.Finances.Transforms
}
foreach (var item in banks)
{
conn.UpdateOnly(item);
item.RecalculateAmountSplit(conn);
}
foreach (var log in logs)
{
......@@ -292,6 +293,7 @@ namespace Kivii.Finances.Transforms
if (payments == null) throw new Exception("收款不存在!");
if (payments.Exists(o => o.Type != PaymentType.Split)) throw new Exception("非银行到账不可以认领!");
if (payments.Exists(o => o.OffsetKvid != Guid.Empty)) throw new Exception("已冲销收款不可撤销认领!");
(conn.Exists<InvoiceApply>(o => o.OperateType == InvoiceApplyType.Related && o.OffsetKvid == Guid.Empty && o.AmountInvoice != o.Amount && Sql.In(o.BizKvid, payments.ConvertAll(p => p.Kvid)))).ThrowIfTrue("存在申请开票中的到账,暂无法撤销认领!");
var rtns = new RestfulExecutionResponse<Payment>();
rtns.Results = new List<Payment>();
//if (payments.Exists(o => o.AmountUsed > 0)) throw new Exception("存在到账已使用,不可撤销认领!");
......@@ -318,37 +320,27 @@ namespace Kivii.Finances.Transforms
#region 没有使用的撤销
if (!paymentUnuseds.IsNullOrEmpty())
{
var rootKvids = paymentUnuseds.ConvertAll(o => o.RootKvid).Distinct().ToList();
var roots = conn.SelectByIds<Payment>(rootKvids);
var parentKvids = paymentUnuseds.ConvertAll(o => o.ParentKvid).Distinct().ToList();
var parents = conn.SelectByIds<Payment>(parentKvids);
var rootUpdates = new List<Payment>();
var parentUpdates = new List<Payment>();
var splitOffsets = new List<Payment>();
var offsets = new List<Payment>();
foreach (var split in paymentUnuseds)
{
var root = roots.FirstOrDefault(o => o.Kvid == split.ParentKvid);
if (root == null) continue;
var parent = parents.FirstOrDefault(o => o.Kvid == split.ParentKvid);
if (parent == null) continue;
var offset = split.Offset($"认领撤销:{Remark}");
offsets.Add(offset);
splitOffsets.Add(split);
if (root.AmountSplited >= split.Amount) root.AmountSplited -= split.Amount;
else root.AmountSplited = 0;
root.AddOnlyProperties(o => o.AmountSplited);
if (rootUpdates.Exists(o => o.Kvid == root.Kvid)) rootUpdates.RemoveAll(o => o.Kvid == root.Kvid);
rootUpdates.Add(root);
parentUpdates.Add(parent);
}
var trans = conn.OpenTransaction();
try
{
foreach (var item in rootUpdates)
{
conn.UpdateOnly(item);
}
foreach (var item in splitOffsets)
{
conn.UpdateOnly(item);
......@@ -358,6 +350,10 @@ namespace Kivii.Finances.Transforms
{
conn.Insert(item);
}
foreach (var item in parentUpdates)
{
item.RecalculateAmountSplit(conn);
}
trans.Commit();
}
catch (Exception ex)
......
......@@ -30,6 +30,8 @@ namespace Kivii.Finances.Transforms
if (payment.OffsetKvid != Guid.Empty) throw new Exception("已冲销收款不可操作!");
if (payment.AmountSplited == payment.Amount) throw new Exception("无剩余收款可操作!");
if (payment.AmountSplited + Amount > payment.Amount) throw new Exception("操作金额超出范围!");
//if (payment.AmountInvoice > 0) throw new Exception("已开票,无法非业务处理!");
if (payment.AmountUsed > 0) throw new Exception("已使用金额,无法非业务处理!");
var split = payment.UnBizSplit(Amount, PaymentType.UnBiz);
......@@ -49,8 +51,8 @@ namespace Kivii.Finances.Transforms
var trans = conn.OpenTransaction();
try
{
conn.UpdateOnly(payment);
conn.Insert(split);
payment.RecalculateAmountSplit(conn);
conn.Insert(log);
rtns.Results.Add(split);
......@@ -84,6 +86,8 @@ namespace Kivii.Finances.Transforms
if (payments.Exists(o => o.Type != PaymentType.Bank)) throw new Exception("非银行到账不可以操作!");
if (payments.Exists(o => o.OffsetKvid != Guid.Empty)) throw new Exception("已冲销收款不可操作!");
if (payments.Exists(o => o.AmountSplited >= o.Amount)) throw new Exception("无剩余收款可操作!");
//if (payments.Exists(o => o.AmountInvoice > 0)) throw new Exception("已开票,无法非业务处理!");
if (payments.Exists(o => o.AmountUsed > 0)) throw new Exception("已使用,无法非业务处理!");
var banks = new List<Payment>();
var splits = new List<Payment>();
......@@ -123,7 +127,7 @@ namespace Kivii.Finances.Transforms
}
foreach (var item in banks)
{
conn.UpdateOnly(item);
item.RecalculateAmountSplit(conn);
}
foreach (var log in logs)
{
......@@ -159,29 +163,24 @@ namespace Kivii.Finances.Transforms
if (payments.Exists(o => o.Type != PaymentType.UnBiz)) throw new Exception("非银行到账不可以操作!");
if (payments.Exists(o => o.OffsetKvid != Guid.Empty)) throw new Exception("已冲销收款不可撤销操作!");
if (payments.Exists(o => o.AmountUsed > 0)) throw new Exception("存在到账已使用,不可撤销操作!");
(conn.Exists<InvoiceApply>(o => o.OperateType == InvoiceApplyType.Related && o.OffsetKvid == Guid.Empty && o.AmountInvoice != o.Amount && Sql.In(o.BizKvid, payments.ConvertAll(p => p.Kvid)))).ThrowIfTrue("存在申请开票中的到账,暂无法撤销认领!");
var rootKvids = payments.ConvertAll(o => o.RootKvid).Distinct().ToList();
var roots = conn.SelectByIds<Payment>(rootKvids);
var parentKvids = payments.ConvertAll(o => o.ParentKvid).Distinct().ToList();
var parents = conn.SelectByIds<Payment>(parentKvids);
var rootUpdates = new List<Payment>();
var parentUpdates = new List<Payment>();
var splitOffsets = new List<Payment>();
var offsets = new List<Payment>();
foreach (var split in payments)
{
var root = roots.FirstOrDefault(o => o.Kvid == split.ParentKvid);
if (root == null) continue;
var parent = parents.FirstOrDefault(o => o.Kvid == split.ParentKvid);
if (parent == null) continue;
var offset = split.Offset($"非业务撤销:{Remark}");
offsets.Add(offset);
splitOffsets.Add(split);
if (root.AmountSplited >= split.Amount) root.AmountSplited -= split.Amount;
else root.AmountSplited = 0;
root.AddOnlyProperties(o => o.AmountSplited);
if (rootUpdates.Exists(o => o.Kvid == root.Kvid)) rootUpdates.RemoveAll(o => o.Kvid == root.Kvid);
rootUpdates.Add(root);
parentUpdates.Add(parent);
}
var rtns = new RestfulExecutionResponse<Payment>();
......@@ -190,10 +189,6 @@ namespace Kivii.Finances.Transforms
var trans = conn.OpenTransaction();
try
{
foreach (var item in rootUpdates)
{
conn.UpdateOnly(item);
}
foreach (var item in splitOffsets)
{
conn.UpdateOnly(item);
......@@ -203,6 +198,10 @@ namespace Kivii.Finances.Transforms
{
conn.Insert(item);
}
foreach (var item in parentUpdates)
{
item.RecalculateAmountSplit(conn);
}
trans.Commit();
}
catch (Exception ex)
......@@ -236,6 +235,8 @@ namespace Kivii.Finances.Transforms
if (payment.OffsetKvid != Guid.Empty) throw new Exception("已冲销收款不可操作!");
if (payment.AmountSplited == payment.Amount) throw new Exception("无剩余收款可操作!");
if (payment.AmountSplited + Amount > payment.Amount) throw new Exception("操作金额超出范围!");
//if (payment.AmountInvoice > 0) throw new Exception("已开票,无法退款处理!");
if (payment.AmountUsed > 0) throw new Exception("已使用金额,无法退款处理!");
var split = payment.UnBizSplit(Amount, PaymentType.Refund);
......@@ -255,8 +256,8 @@ namespace Kivii.Finances.Transforms
var trans = conn.OpenTransaction();
try
{
conn.UpdateOnly(payment);
conn.Insert(split);
payment.RecalculateAmountSplit(conn);
conn.Insert(log);
rtns.Results.Add(split);
......@@ -290,6 +291,8 @@ namespace Kivii.Finances.Transforms
if (payments.Exists(o => o.Type != PaymentType.Bank)) throw new Exception("非银行到账不可以操作!");
if (payments.Exists(o => o.OffsetKvid != Guid.Empty)) throw new Exception("已冲销收款不可操作!");
if (payments.Exists(o => o.AmountSplited >= o.Amount)) throw new Exception("无剩余收款可操作!");
//if (payments.Exists(o => o.AmountInvoice > 0)) throw new Exception("已开票,无法退款处理!");
if (payments.Exists(o => o.AmountUsed > 0)) throw new Exception("已使用,无法退款处理!");
var banks = new List<Payment>();
var splits = new List<Payment>();
......@@ -329,7 +332,7 @@ namespace Kivii.Finances.Transforms
}
foreach (var item in banks)
{
conn.UpdateOnly(item);
item.RecalculateAmountSplit(conn);
}
foreach (var log in logs)
{
......@@ -365,29 +368,24 @@ namespace Kivii.Finances.Transforms
if (payments.Exists(o => o.Type != PaymentType.Refund)) throw new Exception("非银行到账不可以操作!");
if (payments.Exists(o => o.OffsetKvid != Guid.Empty)) throw new Exception("已冲销收款不可撤销操作!");
if (payments.Exists(o => o.AmountUsed > 0)) throw new Exception("存在到账已使用,不可撤销操作!");
(conn.Exists<InvoiceApply>(o => o.OperateType == InvoiceApplyType.Related && o.OffsetKvid == Guid.Empty && o.AmountInvoice != o.Amount && Sql.In(o.BizKvid, payments.ConvertAll(p => p.Kvid)))).ThrowIfTrue("存在申请开票中的到账,暂无法撤销认领!");
var rootKvids = payments.ConvertAll(o => o.RootKvid).Distinct().ToList();
var roots = conn.SelectByIds<Payment>(rootKvids);
var parentKvids = payments.ConvertAll(o => o.ParentKvid).Distinct().ToList();
var parents = conn.SelectByIds<Payment>(parentKvids);
var rootUpdates = new List<Payment>();
var parentUpdates = new List<Payment>();
var splitOffsets = new List<Payment>();
var offsets = new List<Payment>();
foreach (var split in payments)
{
var root = roots.FirstOrDefault(o => o.Kvid == split.ParentKvid);
if (root == null) continue;
var parent = parents.FirstOrDefault(o => o.Kvid == split.ParentKvid);
if (parent == null) continue;
var offset = split.Offset($"退款撤销:{Remark}");
offsets.Add(offset);
splitOffsets.Add(split);
if (root.AmountSplited >= split.Amount) root.AmountSplited -= split.Amount;
else root.AmountSplited = 0;
root.AddOnlyProperties(o => o.AmountSplited);
if (rootUpdates.Exists(o => o.Kvid == root.Kvid)) rootUpdates.RemoveAll(o => o.Kvid == root.Kvid);
rootUpdates.Add(root);
parentUpdates.Add(parent);
}
var rtns = new RestfulExecutionResponse<Payment>();
......@@ -396,10 +394,6 @@ namespace Kivii.Finances.Transforms
var trans = conn.OpenTransaction();
try
{
foreach (var item in rootUpdates)
{
conn.UpdateOnly(item);
}
foreach (var item in splitOffsets)
{
conn.UpdateOnly(item);
......@@ -409,6 +403,10 @@ namespace Kivii.Finances.Transforms
{
conn.Insert(item);
}
foreach (var item in parentUpdates)
{
item.RecalculateAmountSplit(conn);
}
trans.Commit();
}
catch (Exception ex)
......
......@@ -59,18 +59,15 @@ namespace Kivii.Finances.Transforms
}
if (IsPayee != null)
{
var queryBankAccount = conn.From<Account>();
queryBankAccount.Where(o => o.OrganizationKvid == KiviiContext.CurrentMember.OrganizationKvid && Sql.In(o.Type, AccountType.Bank, AccountType.WeChat, AccountType.AliPay));
queryBankAccount.Select(o => o.Kvid);
var queryAccount = conn.From<Account>();
queryAccount.Where(o => o.OrganizationKvid == KiviiContext.CurrentMember.OrganizationKvid && Sql.In(o.Type, AccountType.Balance, AccountType.Cash, AccountType.Pos));
queryAccount.Select(o => o.Kvid);
var queryCashAccount = conn.From<Account>();
queryCashAccount.Where(o => o.OrganizationKvid == KiviiContext.CurrentMember.OrganizationKvid && Sql.In(o.Type, AccountType.Cash, AccountType.Pos));
queryCashAccount.Select(o => o.Kvid);
if (IsPayee.Value)//收款
{
sqlExpress.And(o => (Sql.In(o.PayeeAccountKvid, queryBankAccount) || Sql.In(o.PayerAccountKvid, queryCashAccount)));
sqlExpress.And(o => (Sql.In(o.PayerAccountKvid, queryAccount)));
}
else sqlExpress.And(o => Sql.In(o.PayerAccountKvid, queryBankAccount));
else sqlExpress.And(o => Sql.In(o.PayeeAccountKvid, queryAccount));
}
var rtns = autoQuery.Execute(Request, conn, request, sqlExpress);
......@@ -78,6 +75,50 @@ namespace Kivii.Finances.Transforms
}
}
[Api(Description = "到账收款登记查询")]
[RequiresAnyRole(SystemRoles.Everyone)]
public class PaymentPayQuery : RestfulExecution<Payment>
{
#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 override object OnExecution(IRequest req, IResponse res)
{
var conn = KiviiContext.GetOpenedDbConnection<Payment>();
var dynamicParams = Request.GetRequestParams();
var autoQuery = Request.TryResolve<IAutoQueryDb>();
autoQuery.IncludeTotal = true;
var request = new RestfulQuery<Payment>();
request = request.PopulateWith(this);
var sqlExpress = autoQuery.CreateQuery(Request, conn, request, dynamicParams);
sqlExpress.Where(o => o.OffsetKvid == Guid.Empty && Sql.In(o.Type, PaymentType.AliPay, PaymentType.WeChat, PaymentType.Split, PaymentType.Cash, PaymentType.Pos));
sqlExpress.And(o => o.AmountUsed == 0 || o.AmountUsed < o.Amount);
var queryAccount = conn.From<Account>();
queryAccount.Where(o => o.OrganizationKvid == KiviiContext.CurrentMember.OrganizationKvid && Sql.In(o.Type, AccountType.Balance, AccountType.Cash, AccountType.Pos));
queryAccount.Select(o => o.Kvid);
sqlExpress.And(o => (Sql.In(o.PayerAccountKvid, queryAccount)));
var rtns = autoQuery.Execute(Request, conn, request, sqlExpress);
return rtns;
}
}
[Api(Description = "到账开票查询")]
[RequiresAnyRole(SystemRoles.Everyone)]
public class PaymentInvoiceApplyQuery : RestfulExecution<Payment>
......@@ -113,7 +154,7 @@ namespace Kivii.Finances.Transforms
request = request.PopulateWith(this);
var sqlExpress = autoQuery.CreateQuery(Request, conn, request, dynamicParams);
sqlExpress.Where(o => o.OffsetKvid == Guid.Empty && Sql.In(o.Type, PaymentType.AliPay, PaymentType.WeChat, PaymentType.Cash, PaymentType.Pos, PaymentType.Split));
sqlExpress.And(o => o.AmountInvoice <= 0 && o.AmountInvoice < o.Amount);
sqlExpress.And(o => o.AmountInvoice <= 0 || o.AmountInvoice < o.Amount);
var queryInvoiceApplyRelations = conn.From<InvoiceApply>();
queryInvoiceApplyRelations.Where(o => o.OperateType == InvoiceApplyType.Related && o.OffsetKvid == Guid.Empty);
......@@ -159,15 +200,11 @@ namespace Kivii.Finances.Transforms
var sqlExpress = autoQuery.CreateQuery(Request, conn, request, dynamicParams);
sqlExpress.Where(o => o.OffsetKvid == Guid.Empty && Sql.In(o.Type, PaymentType.AliPay, PaymentType.WeChat, PaymentType.Bank, PaymentType.Cash, PaymentType.Pos) && o.AmountInvoice < o.Amount);
var queryBankAccount = conn.From<Account>();
queryBankAccount.Where(o => o.OrganizationKvid == KiviiContext.CurrentMember.OrganizationKvid && Sql.In(o.Type, AccountType.Bank, AccountType.WeChat, AccountType.AliPay));
queryBankAccount.Select(o => o.Kvid);
var queryAccount = conn.From<Account>();
queryAccount.Where(o => o.OrganizationKvid == KiviiContext.CurrentMember.OrganizationKvid && Sql.In(o.Type, AccountType.Balance, AccountType.Cash, AccountType.Pos));
queryAccount.Select(o => o.Kvid);
var queryCashAccount = conn.From<Account>();
queryCashAccount.Where(o => o.OrganizationKvid == KiviiContext.CurrentMember.OrganizationKvid && Sql.In(o.Type, AccountType.Cash, AccountType.Pos));
queryCashAccount.Select(o => o.Kvid);
sqlExpress.And(o => (Sql.In(o.PayeeAccountKvid, queryBankAccount) || Sql.In(o.PayerAccountKvid, queryCashAccount)));
sqlExpress.And(o => (Sql.In(o.PayerAccountKvid, queryAccount)));
var rtns = autoQuery.Execute(Request, conn, request, sqlExpress);
return rtns;
......@@ -211,4 +248,83 @@ namespace Kivii.Finances.Transforms
return rtns;
}
}
[Api(Description = "认领查询")]
[RequiresAnyRole(SystemRoles.Everyone)]
public class PaymentSplitQuery : RestfulExecution<Payment>
{
#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 bool? IsBiz { get; set; }//Split,Pos,Cash,WeChat..
public override object OnExecution(IRequest req, IResponse res)
{
var conn = KiviiContext.GetOpenedDbConnection<Payment>();
var dynamicParams = Request.GetRequestParams();
var autoQuery = Request.TryResolve<IAutoQueryDb>();
autoQuery.IncludeTotal = true;
var request = new RestfulQuery<Payment>();
request = request.PopulateWith(this);
var sqlExpress = autoQuery.CreateQuery(Request, conn, request, dynamicParams);
if (IsBiz == null) sqlExpress.Where(o => o.OffsetKvid == Guid.Empty && Sql.In(o.Type, PaymentType.WeChat, PaymentType.Cash, PaymentType.AliPay, PaymentType.Pos, PaymentType.Split, PaymentType.Refund, PaymentType.UnBiz));
else if (IsBiz.Value) sqlExpress.Where(o => o.OffsetKvid == Guid.Empty && Sql.In(o.Type, PaymentType.WeChat, PaymentType.Cash, PaymentType.AliPay, PaymentType.Pos, PaymentType.Split));
else sqlExpress.Where(o => o.OffsetKvid == Guid.Empty && Sql.In(o.Type, PaymentType.Refund, PaymentType.UnBiz));
var rtns = autoQuery.Execute(Request, conn, request, sqlExpress);
return rtns;
}
}
[Api(Description = "充值查询")]
[RequiresAnyRole(SystemRoles.Everyone)]
public class PaymentTransferQuery : RestfulExecution<Payment>
{
#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 override object OnExecution(IRequest req, IResponse res)
{
var conn = KiviiContext.GetOpenedDbConnection<Payment>();
var dynamicParams = Request.GetRequestParams();
var autoQuery = Request.TryResolve<IAutoQueryDb>();
autoQuery.IncludeTotal = true;
var request = new RestfulQuery<Payment>();
request = request.PopulateWith(this);
var sqlExpress = autoQuery.CreateQuery(Request, conn, request, dynamicParams);
sqlExpress.Where(o => o.Type == PaymentType.Transfer);
var rtns = autoQuery.Execute(Request, conn, request, sqlExpress);
return rtns;
}
}
}
using Kivii.Finances.Entities;
using Kivii.Linq;
using Kivii.Web;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Kivii.Finances.Transforms
{
[Api(Description = "结算作废")]//区别于 删除 当此结算已经收款登记时无法删除 只能作废,相反同理
[RequiresAnyRole(SystemRoles.Everyone)]
public class SettlementOffset: RestfulExecutionGeneric<Settlement>
{
public List<Guid> Kvids { get; set; }
public override object OnExecutionGeneric<G>(IRequest req, IResponse res)
{
Kvids.ThrowIfNullOrEmpty("参数错误:未传入要作废的结算Kvids");
var connF = KiviiContext.GetOpenedDbConnection<Settlement>();
//var connE = KiviiContext.GetOpenedDbConnection<EntitySettlement<G>>();
var settlements = connF.Select<Settlement>(o => Sql.In(o.Kvid, Kvids));
(settlements.Count != Kvids.Count).ThrowIfTrue("所选结算和查询结果不一致!");
settlements.Exists(o => o.OffsetKvid != Guid.Empty).ThrowIfTrue("存在已作废结算,无法重复作废");
settlements.Exists(o => o.AmountPayment != o.Amount).ThrowIfTrue("作废错误:作废的结算中包含未收款的结算!");
//connF.Exists<Settlement>(o => o.AmountPayment != o.Amount && Sql.In(o.Kvid, Kvids)).ThrowIfTrue("作废错误:作废的结算中包含未收款的结算!");
////如果泛型类型不是Settlement本身就需要判断
//if (typeof(G) != typeof(Settlement)) connE.Exists<EntitySettlement<G>>(o => o.AmountPayment != o.Amount && Sql.In(o.Kvid, Kvids)).ThrowIfTrue("作废错误:作废的结算中包含未收款的结算!");
List<Payment> allPayments = new List<Payment>();
List<Account> allFromAccounts = new List<Account>();
List<Account> allToAccounts = new List<Account>();
List<Payment> paymentsPreUpdate = new List<Payment>();
List<Payment> parentsPreUpdate = new List<Payment>();
List<AccountDetail> accountDetailsPreInsert = new List<AccountDetail>();
List<Pay> paysOffsetPreUpdate = new List<Pay>();
List<Pay> paysOffsetPreInsert = new List<Pay>();
List<Settlement> settlementsOffsetPreUpdate = new List<Settlement>();
List<Settlement> settlementsOffsetPreInsert = new List<Settlement>();
var queryPays =connF.From<Pay>();
queryPays.Where(o => o.BizType == typeof(Settlement).FullName && Sql.In(o.BizKvid, Kvids));
var allPays = connF.Select(queryPays);
if (!allPays.IsNullOrEmpty())
{
#region 先查出相关数据
allToAccounts = connF.Select<Account>(o => Sql.In(o.Kvid, allPays.ConvertAll(p => p.ToKvid).Distinct()));
var payFromPayments = allPays.Where(o => o.FromType == PayType.Payment).ToList();
if (!payFromPayments.IsNullOrEmpty()) allPayments = connF.Select<Payment>(o => Sql.In(o.Kvid, payFromPayments.ConvertAll(p => p.FromKvid).Distinct()));
var payFromAccounts = allPays.Where(o => Sql.In(o.FromType, PayType.Account, PayType.Discount)).ToList();
if (!payFromAccounts.IsNullOrEmpty()) allFromAccounts = connF.Select<Account>(o => Sql.In(o.Kvid, payFromAccounts.ConvertAll(p => p.FromKvid).Distinct()));
#endregion
}
foreach (var settlement in settlements)
{
if (!allPays.IsNullOrEmpty())
{
var pays = allPays.Where(o => o.BizKvid == settlement.Kvid).ToList();
if (!pays.IsNullOrEmpty())
{
foreach (var pay in pays)
{
var toAccount = allToAccounts.FirstOrDefault(o => o.Kvid == pay.ToKvid);
if (toAccount == null) throw new Exception("未找到原收款账户!");
if (pay.FromType == PayType.Payment)
{
var payment = allPayments.FirstOrDefault(o => o.Kvid == pay.FromKvid);
if (payment != null)
{
payment.Amount -= pay.Amount;
payment.AddOnlyProperties(o => o.Amount);
payment.AmountUsed -= pay.Amount;
payment.AddOnlyProperties(o => o.AmountUsed);
paymentsPreUpdate.Add(payment);
var toDetail = new AccountDetail();
toDetail.AccountKvid = toAccount.Kvid;
toDetail.BizId = payment.SerialNumber;
toDetail.BizKvid = payment.Kvid;
toDetail.BizType = typeof(Payment).FullName;
toDetail.PayerKvid = toAccount.Kvid;
toDetail.PayerName = toAccount.Name;
toDetail.PayerAccountKvid = toAccount.Kvid;
toDetail.PayerAccountName = toAccount.Name;
toDetail.PayerAccountSerialNumber = toAccount.SerialNumber;
toDetail.PayeeKvid = payment.PayerKvid;
toDetail.PayeeName = payment.PayerName;
toDetail.AmountPayment = pay.Amount;
toDetail.Summary = "结算项作废,分摊费用退回";
accountDetailsPreInsert.Add(toDetail);
}
}
else
{
var fromAccount = allFromAccounts.FirstOrDefault(o => o.Kvid == pay.FromKvid);
if (fromAccount != null)
{
var fromDetail = new AccountDetail();
fromDetail.AccountKvid = fromAccount.Kvid;
fromDetail.BizId = toAccount.SerialNumber;
fromDetail.BizKvid = toAccount.Kvid;
fromDetail.BizType = typeof(Account).FullName;
fromDetail.PayerKvid = toAccount.Kvid;
fromDetail.PayerName = toAccount.Name;
fromDetail.PayerAccountKvid = toAccount.Kvid;
fromDetail.PayerAccountName = toAccount.Name;
fromDetail.PayerAccountSerialNumber = toAccount.SerialNumber;
fromDetail.PayeeKvid = fromAccount.Kvid;
fromDetail.PayeeName = fromAccount.Name;
fromDetail.PayeeAccountKvid = fromAccount.Kvid;
fromDetail.PayeeAccountName = fromAccount.Name;
fromDetail.PayeeAccountSerialNumber = fromAccount.SerialNumber;
fromDetail.AmountPayment = pay.Amount;
fromDetail.Summary = "结算项作废,分摊费用退回";
accountDetailsPreInsert.Add(fromDetail);
var toDetail = new AccountDetail();
toDetail.AccountKvid = toAccount.Kvid;
toDetail.BizId = fromAccount.SerialNumber;
toDetail.BizKvid = fromAccount.Kvid;
toDetail.BizType = typeof(Account).FullName;
toDetail.PayerKvid = toAccount.Kvid;
toDetail.PayerName = toAccount.Name;
toDetail.PayerAccountKvid = toAccount.Kvid;
toDetail.PayerAccountName = toAccount.Name;
toDetail.PayerAccountSerialNumber = toAccount.SerialNumber;
toDetail.PayeeKvid = fromAccount.Kvid;
toDetail.PayeeName = fromAccount.Name;
toDetail.PayeeAccountKvid = fromAccount.Kvid;
toDetail.PayeeAccountName = fromAccount.Name;
toDetail.PayeeAccountSerialNumber = fromAccount.SerialNumber;
toDetail.AmountPayment = pay.Amount;
toDetail.Summary = "结算项作废,分摊费用退回";
accountDetailsPreInsert.Add(toDetail);
}
}
var payOffset = pay.Offset("结算项作废");
paysOffsetPreUpdate.Add(pay);
paysOffsetPreInsert.Add(payOffset);
}
}
}
var settlementOffset = settlement.Offset("结算项作废");
settlementsOffsetPreUpdate.Add(settlement);
settlementsOffsetPreInsert.Add(settlementOffset);
}
if (!paymentsPreUpdate.IsNullOrEmpty())
{
parentsPreUpdate = connF.Select<Payment>(o => Sql.In(o.Kvid, paymentsPreUpdate.ConvertAll(p => p.ParentKvid).Distinct()));
}
var rtns = new RestfulExecutionResponse<Settlement>();
rtns.Results = new List<Settlement>();
var connE = KiviiContext.GetOpenedDbConnection<G>();
#region 合并数据库连接,并启用事务
IDbTransaction tranE = null, tranF = null;
if (connE.ConnectionString == connF.ConnectionString)
{
connF.Close();
connF = connE;
tranE = connE.OpenTransaction();
}
else
{
tranE = connE.OpenTransaction();
tranF = connF.OpenTransaction();
}
#endregion
try
{
foreach (var payment in paymentsPreUpdate)
{
connF.UpdateOnly(payment);
}
foreach (var item in parentsPreUpdate)
{
item.RecalculateAmountUsed(connF);
}
foreach (var accountDetail in accountDetailsPreInsert)
{
accountDetail.Insert(connF);
}
foreach (var pay in paysOffsetPreUpdate)
{
connF.UpdateOnly(pay);
}
foreach (var pay in paysOffsetPreInsert)
{
connF.Insert(pay);
}
foreach (var settlement in settlementsOffsetPreUpdate)
{
connF.UpdateOnly(settlement);
rtns.Results.Add(settlement);
if (typeof(G) != typeof(Settlement))
{
var entitySettlement = new EntitySettlement<G>();
entitySettlement.PopulateInstance(settlement);
connE.UpdateOnly(entitySettlement);
#region 回写更新G数据
var instance = Activator.CreateInstance(typeof(G)) as IEntityHasSettlement;
if (instance != null)
{
instance.Kvid = settlement.BizKvid;
instance.AmountSettlement = settlement.Amount;
instance.AddOnlyProperties(o => o.AmountSettlement);
connE.UpdateOnly(instance);
}
#endregion
}
}
foreach (var item in settlementsOffsetPreInsert)
{
connF.Insert(item);
if (typeof(G) != typeof(Settlement))
{
var entitySettlement = new EntitySettlement<G>();
entitySettlement.PopulateInstance(item);
connE.Insert(entitySettlement);
}
}
tranE?.Commit();
tranF?.Commit();
}
catch (Exception ex)
{
tranE?.Rollback();
tranF?.Rollback();
throw ex;
}
return rtns;
}
}
}
......@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
......@@ -25,14 +26,22 @@ namespace Kivii.Finances.Transforms
Items.Exists(o => o.PayerName.IsNullOrEmpty()).ThrowIfTrue("付款单位不能为空!");
Items.Exists(o => o.Currency == CurrencyUnit.Unsupported).ThrowIfTrue("不支持的货币单位!");
Items.Exists(o => o.Details.IsNullOrEmpty()).ThrowIfTrue("结算明细不能为空!");
var bizKvids = Items.ConvertAll(p => p.BizKvid);
bizKvids.RemoveAll(o => o == Guid.Empty);
var bizids = Items.ConvertAll(p => p.BizId);
bizids.RemoveAll(o => o.IsNullOrEmpty());
var connF = KiviiContext.GetOpenedDbConnection<Settlement>();
if (connF.Exists<Settlement>(o => o.OffsetKvid == Guid.Empty && Sql.In(o.BizKvid, Items.ConvertAll(p => p.BizKvid)))) throw new Exception("存在重复结算的对象!");
if (connF.Exists<Settlement>(o => o.OffsetKvid == Guid.Empty && (Sql.In(o.BizKvid, bizKvids) || Sql.In(o.BizId, bizids)))) throw new Exception("存在重复结算的对象!");
var connE = KiviiContext.GetOpenedDbConnection<G>();
//如果泛型类型不是Settlement本身就需要判断
if (typeof(G) != typeof(Settlement)) connE.Exists<EntitySettlement<G>>(o => o.OffsetKvid == Guid.Empty && Sql.In(o.BizKvid, Items.ConvertAll(p => p.BizKvid))).ThrowIfTrue("存在重复结算的对象!");
if (typeof(G) != typeof(Settlement)) connE.Exists<EntitySettlement<G>>(o => o.OffsetKvid == Guid.Empty && (Sql.In(o.BizKvid, bizKvids) || Sql.In(o.BizId, bizids))).ThrowIfTrue("存在重复结算的对象!");
var allDetails = new List<SettlementDetail>();
Items.ForEach(o => allDetails.AddRange(o.Details));
if (connE.Exists<EntitySettlementDetail<G>>(o => o.OffsetKvid != Guid.Empty && Sql.In(o.BizKvid, allDetails.ConvertAll(p => p.BizKvid)))) throw new Exception("存在重复结算的明细项目!");
var detailBizKvids = allDetails.ConvertAll(p => p.BizKvid);
detailBizKvids.RemoveAll(o => o == Guid.Empty);
var detailBizids = allDetails.ConvertAll(p => p.BizId);
detailBizids.RemoveAll(o => o.IsNullOrEmpty());
if (connE.Exists<EntitySettlementDetail<G>>(o => o.OffsetKvid != Guid.Empty && (Sql.In(o.BizKvid, detailBizKvids) || Sql.In(o.BizId, detailBizids)))) throw new Exception("存在重复结算的明细项目!");
var rtns = new RestfulCreateResponse<Settlement>();
rtns.Results = new List<Settlement>();
......@@ -163,7 +172,19 @@ namespace Kivii.Finances.Transforms
[RequiresAnyRole(SystemRoles.Everyone)]
public class SettlementQuery : RestfulQuery<Settlement>
{
public Guid BillKvid { get; set; }
public override bool OnPreRestfulQuery(IRequest req, IResponse res, IDbConnection dbConnection, IRestfulQueryResponse<Settlement> rtns, ref Expression<Func<Settlement, bool>> where)
{
if (BillKvid != Guid.Empty)
{
var queryDetails = dbConnection.From<BillDetail>();
queryDetails.Where(o => o.BillKvid == BillKvid);
queryDetails.Select(o => o.BizKvid);
where = o => Sql.In(o.Kvid, queryDetails);
}
return base.OnPreRestfulQuery(req, res, dbConnection, rtns, ref where);
}
}
[Api(Description = "结算查询Ex")]
......@@ -204,8 +225,8 @@ namespace Kivii.Finances.Transforms
var sqlExpress = autoQuery.CreateQuery(Request, conn, request, dynamicParams);
if (IsPayed != null)
{
if (IsPayed.Value) sqlExpress.And(o => o.PayKvid != Guid.Empty);
else sqlExpress.And(o => o.PayKvid == Guid.Empty);
if (IsPayed.Value) sqlExpress.And(o => o.AmountPayment == o.Amount);
else sqlExpress.And(o => o.AmountPayment < o.Amount || o.AmountPayment == 0);
}
if (IsBilled != null)
{
......@@ -235,9 +256,9 @@ namespace Kivii.Finances.Transforms
var connF = KiviiContext.GetOpenedDbConnection<Settlement>();
var connE = KiviiContext.GetOpenedDbConnection<EntitySettlement<G>>();
connF.Exists<Settlement>(o => o.PayKvid != Guid.Empty && Sql.In(o.Kvid, Kvids)).ThrowIfTrue("删除错误:删除的结算中包含已收款的结算!");
connF.Exists<Settlement>(o => o.AmountPayment != 0 && Sql.In(o.Kvid, Kvids)).ThrowIfTrue("删除错误:删除的结算中包含已收款的结算!");
//如果泛型类型不是Settlement本身就需要判断
if (typeof(G) != typeof(Settlement)) connE.Exists<EntitySettlement<G>>(o => o.PayKvid != Guid.Empty && Sql.In(o.Kvid, Kvids)).ThrowIfTrue("删除错误:删除的结算中包含已收款的结算!");
if (typeof(G) != typeof(Settlement)) connE.Exists<EntitySettlement<G>>(o => o.AmountPayment != 0 && Sql.In(o.Kvid, Kvids)).ThrowIfTrue("删除错误:删除的结算中包含已收款的结算!");
var settlements = connF.Select<Settlement>(o => Sql.In(o.Kvid, Kvids));
//var entitySettlements = connE.Select<EntitySettlement<G>>(o => Sql.In(o.Kvid, Kvids));
......@@ -397,10 +418,10 @@ namespace Kivii.Finances.Transforms
Kvids.ThrowIfNullOrEmpty("参数错误:未传入要调价的结算Kvids");
(Amount < 0).ThrowIfTrue("调整总价格不能为负值!");
var connFins = KiviiContext.GetOpenedDbConnection<Settlement>();
connFins.Exists<Settlement>(o => (o.PayKvid != Guid.Empty || o.OffsetKvid != Guid.Empty) && Sql.In(o.Kvid, Kvids)).ThrowIfTrue("调价错误:存在已支付或待支付或已冲销的结算!");
connFins.Exists<Settlement>(o => (o.AmountPayment != 0 || o.OffsetKvid != Guid.Empty) && Sql.In(o.Kvid, Kvids)).ThrowIfTrue("调价错误:存在已支付或待支付或已冲销的结算!");
var connG = KiviiContext.GetOpenedDbConnection<EntitySettlement<G>>();
//如果泛型类型不是Settlement本身就需要判断
if (typeof(G) != typeof(Settlement)) connG.Exists<EntitySettlement<G>>(o => (o.PayKvid != Guid.Empty || o.OffsetKvid != Guid.Empty) && Sql.In(o.Kvid, Kvids)).ThrowIfTrue("调价错误:存在已支付或待支付或已冲销的结算!");
if (typeof(G) != typeof(Settlement)) connG.Exists<EntitySettlement<G>>(o => (o.AmountPayment != 0 || o.OffsetKvid != Guid.Empty) && Sql.In(o.Kvid, Kvids)).ThrowIfTrue("调价错误:存在已支付或待支付或已冲销的结算!");
var querySettlements = connFins.From<Settlement>();
querySettlements.Where(o => Sql.In(o.Kvid, Kvids));
......@@ -408,7 +429,7 @@ namespace Kivii.Finances.Transforms
var settlements = connFins.Select(querySettlements);
settlements.ThrowIfNullOrEmpty("未找到要调价的结算单!");
(settlements.Count != Kvids.Count).ThrowIfTrue("所选结算单信息不完整!");
settlements.Exists(o => o.PayKvid != Guid.Empty || o.OffsetKvid != Guid.Empty).ThrowIfTrue("调价错误:存在已支付或待支付或已冲销的结算!");
settlements.Exists(o => o.AmountPayment != 0 || o.OffsetKvid != Guid.Empty).ThrowIfTrue("调价错误:存在已支付或待支付或已冲销的结算!");
var amountSum = settlements.Sum(o => o.Amount);
var rates = new Dictionary<Guid, decimal>();
foreach (var item in settlements)
......
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