我正在用jqTouch设计一个基于网络的智能手机应用程序。其理念是能够:
追踪谁欠谁午餐
跟踪债务随时间变化
把债务从一个人转移到另一个人身上
这听起来很复杂,但这将为我的午餐伙伴们解决一个现实世界的问题,他们经常互相付钱,最后通过Paypal偿还。对于那些不这样做的人来说,他们经常进行债务交易。。。例如:

Jason buys lunch for David
David buys lunch for Roslyn
Phillip buys lunch for Roslyn

所以-大卫欠杰森,罗斯林欠大卫和菲利普。作为债务结算,大卫把他的债务转给杰森,罗斯林给他买午餐作为大卫的偿还,现在他们扯平了。只剩下我一个人站着了,这在球场上是相当正常的:)
真正的问题是。。。
如何用关系数据库来表达这一点?我可以跟踪行项目支出和用户:
purchases
=========
purch_id
user_id
amount
location

users
=======
user_id
name

我是否将其余部分作为业务逻辑处理?如何追踪债务通勤?如果我想从中得到有意义的报告,比如一段时间内的支出,以及一个人偿还的平均时间——我需要一个更复杂的模式!
欢迎任何意见/批评!这是一个有趣的心理锻炼,绝不是一个严肃的项目。
更新
考虑到大家对这个问题不感兴趣,我要发一份赏金!奖励奖金需要解决的问题如下:
如何跟踪运行总数而不必对可能很长的事务表求和
如何在不过度规范化的情况下跟踪交易的元数据(例如,上面描述的“通勤”债务功能

最佳答案

你建议的大纲听起来不错。。。从以下关系开始
要跟踪人员和交易:

 Person(*PID*, Name)

其中PID是唯一标识每个人的代理项密钥。
 Transaction(*TID*, Description, Date)

其中TID是唯一标识要跟踪的每个事务的代理项密钥(如午餐)。
追踪谁欠谁:
 Owes(*PIDOwes*, *PIDOwed*, *TID*, Amount)

其中PIDOwes和PIDOwes是来自人际关系的ID。TID标识事务
负责创建借方及其金额。
每次一个组去吃午饭时,都会创建一个新的事务,并且Owes关系
更新以反映谁因此欠谁。这就是你的数据库
杰森给大卫买了一顿15点的午餐后;
大卫10点买罗斯林午餐,菲利普12点买罗斯林午餐。假设
午餐费用按50:50分摊(你可以随意分摊)。重要的是
借方分配给每个人):
Person(J, Jason)
Person(D, David)
Person(R, Roslyn)
Person(P, Phillip)

Transaction(1, Lunch, 2011-03-04)
Transaction(2, Lunch, 2011-03-05)
Transaction(3, Lunch, 2011-03-06)

Owes(D, J, 1, 7.50)
Owes(R, D, 2, 5.00)
Owes(R, P, 3, 6.00)

转帐:
当大卫把罗斯林的欠款转给杰森时,你会记录下
交易:
Transaction(4, CommuteDebit, 2011-03-07)

Owes(R, J, 4,  5.00)
Owes(R, D, 4, -5.00)

谨慎的做法是核实罗斯林事实上至少欠大卫5.00英镑
接受此交易!
上面的第二排可能是大卫欠罗斯林5.00英镑,但我喜欢+/-
方法,因为它捕获了这是零和事务的想法。另一个好处是
您可以确定谁发起了通勤借记,因为他们将始终是pidown in
欠的那一行有一个负数。
当Roslyn为Jason的那部分午餐付账时,创建以下事务
成本13.00分50:50:
Transaction(5, Lunch, 2011-03-08)

Owes(J, R, 5, 6.50)

突然事情变得复杂起来。。。相互借项累积。大卫欠罗斯林和
罗斯林欠大卫的。这些借项应相互抵消,以便大卫欠罗斯林1.50英镑。那个东西
关于债务关系,除了借记通勤,金额只会累积。获取
通过将“a”所欠的“B”与“B”所欠的“a”进行净额结算来实现平衡。这个
负债关系是一种交易明细记录,不提供往来余额。
计算“Jason owes Roslyn”余额的查询非常简单,如下所示:
select sum(case when PIDOwes = 'J' then
                     +amount
                else
                     -amount
                end)
from Owes
where PIDOwes in ('R', 'J')
  and PIDOwed in ('J', 'R')

此查询将返回1.50-Jason现在欠Roslyn的金额。
通过迭代上面的查询,可以找到Roslyn下一次请谁吃午饭
在每个迭代中替换“J”的Person表上(Roslyn保持不变)。
当总数为正时,罗斯林就欠了。当总和为负数时,
那个人欠罗斯林的。
这样的查询将导致:
Phillip  6.00
Jason   -1.50

所以,罗斯林应该治疗菲利普,杰森应该治疗罗斯林。
例如,计算一个人的总体平衡,大卫就可以了
把所有欠大卫的行加起来,把它们从
大卫是小人的总称。
这个方案的基本问题是你必须对整个欠债关系求和
为了获得平衡。优化可能会降低士气
平衡关系,如:
 OwesBal(*PIDOwes*, *PIDOwed*, Balance)

每次将一行添加到欠费关系记录中,记录a欠B一定的金额,
OwesBal关系更新如下:
set TranAmt to whatever A owes B according to the new Owes row.

select Balance as AowesB
from OwesBal
where PIDOwes = 'A'
  and PIDOwed = 'B'

select Balance as BowesA
from OwesBal
where PIDOwes = 'B'
  and PIDOwed = 'A'

if BowesA < TranAmt then
   TranAmt = TranAmt - BowesA
   BowesA = 0.00
else
   BowesA = BowesA - TranAmt
   TranAmt = 0.00

update OwesBal
set Balance = BowesA
where PIDOwes = 'B'
  and PIDOwed = 'A'

update OwesBal
set Balance = Balance + TranAmt
where PIDOwes = 'A'
  and PIDOwed = 'B'

当然,您需要捕获“not found”条件并创建初始OwesBal行
当新的午餐伴侣组合出现时。
上述会计模式不容易跟踪午餐总开支。只是
让你知道谁欠谁。跟踪总支出可以通过添加
与模型的关系如下:
 Share(*PID*, *TID*, Amount)

共享关系将在填充事务和Owes关系时填充。每个人都会
输入他们的份额。例如:
Share(D, 1, 7.50)
Share(J, 1, 7.50)
Share(R, 2, 5.00)
Share(D, 2, 5.00)
Share(R, 3, 6.00)
Share(P, 3, 6.00)
Share(J, 5, 6.50)
Share(R, 5, 6.50)

借记通勤等交易将不会重新记录。您可以按日期获得成本
通过加入交易关系。

关于php - 午餐时间报销应用程序的建议数据库模式,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5241725/

10-10 06:46