Commit c56bed1e by 陶然

init

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