模拟收支记录的实现

一、问题的提出

目标:做出一张表,样式为:<应付款总额><已付款><当次应付款余额>

二、解决思路及实现步骤

 1. 构造表1:订单Orders<int id, decimal total>(订单ID,订单总金额)

 2. 构造表2:支付记录Payments<int id, decimal payment, datetime date>(订单ID,付款金额,付款发生日期)

 3. 构造表3:对应每张订单每次支付记录的表PaymentList<int id, decimal total, decimal payment, datetime paydate>(订单ID,订单总金额,付款金额,付款发生日期)表3以Order的id为主键,通过外连接Orders与Payments表生成。

 4. 构造表4:在表3基础上增加一个列:<decimal ramain>(当次余额)表4以表3为数据源,以每张订单的id为分类项,以当次付款发生日期为筛选条件,进行付款额的汇总,得到当次余额。

三、实现代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections;
namespace PaymentRecord
{
    class Program
    {
        static void Main(string[] args)
        {
            // 构造演示所需的数据源,对应前述表1 Orders与表2 Payments  
            ArrayList orders = new ArrayList();
            orders.Add(new Order { _id = 1, _total = 80M });
            orders.Add(new Order { _id = 2, _total = 100M });
            orders.Add(new Order { _id = 3, _total = 20.5M });
            ArrayList payments = new ArrayList();
            payments.Add(new Payment { _id = 1, _payment = 20M, _date = DateTime.Parse("2011/06/02") });
            payments.Add(new Payment { _id = 1, _payment = 40M, _date = DateTime.Parse("2011/06/04") });
            payments.Add(new Payment { _id = 1, _payment = 10M, _date = DateTime.Parse("2011/06/12") });
            payments.Add(new Payment { _id = 2, _payment = 30M, _date = DateTime.Parse("2011/06/08") });
            // 利用表1与表2,构造表3  
            var payrecords_1 = orders.OfType<Order>()
                .GroupJoin(payments.OfType<Payment>(),
                o => o._id,
                p => p._id,
                (o, ps) => ps.DefaultIfEmpty().Select(p => new
                {
                    id = o._id,
                    total = o._total,
                    payment = (p != null) ? p._payment : 0,
                    paydate = (p != null) ? p._date : (new DateTime(0))
                }))
                    .SelectMany(r => r);
            // 在表3基础上进行分类汇总,增加列remain,构造出表4  
            var payrecords_2 = payrecords_1.Select(s => new
            {
                id = s.id,
                total = s.total,
                payment = s.payment,
                remain = s.total - payrecords_1.Where(p => (p.id == s.id) && (p.paydate <= s.paydate))
                .Sum(sum => sum.payment),
                paydate = s.paydate
            });
            foreach (var item in payrecords_2)
                Console.WriteLine(item);
        }
        class Order { public int _id; public decimal _total; }
        class Payment { public int _id; public decimal _payment; public DateTime _date; }
    }
}

四、运行结果:

{ id = 1, total = 80, payment = 20, remain = 60, paydate = 2011/6/2 0:00:00 }  
{ id = 1, total = 80, payment = 40, remain = 20, paydate = 2011/6/4 0:00:00 }  
{ id = 1, total = 80, payment = 10, remain = 10, paydate = 2011/6/12 0:00:00 }  
{ id = 2, total = 100, payment = 30, remain = 70, paydate = 2011/6/8 0:00:00 }  
{ id = 3, total = 20.5, payment = 0, remain = 20.5, paydate = 0001/1/1 0:00:00 }  
原文地址:https://www.cnblogs.com/Abbey/p/2103516.html