我正在做一个项目来管理会员资格和其他类型的付款,但主要是会员资格,所以我创建了一个多态模式。任何想法,改进,由于某种原因,我不完全相信模式。
正如您将看到的那样,拥有月,年NULL-ABLE的想法允许保存任何其他付款的记录
CREATE TABLE IF NOT EXISTS `orders` (
`id` int(11) NOT NULL auto_increment,
`partner_id` int(11) NOT NULL,
`status` enum('pending','accepted','cancelled','other') NOT NULL,
`created_on` datetime NOT NULL,
`concept` varchar(250) NOT NULL,
`type` enum('membership','other') NOT NULL default 'membership',
`source` enum('dineromail','casati','deposit','other') NOT NULL default 'dineromail',
`notes` text NULL,
`last_check_on` datetime default NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM ;
CREATE TABLE IF NOT EXISTS `payments` (
`id` int(11) NOT NULL auto_increment,
`order_id` int(11) NOT NULL,
`month` int(11) default NULL,
`year` int(11) default NULL,
`amount` float NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `idx-order_id-month-year` (`order_id`,`month`,`year`)
) ENGINE=MyISAM ;
CREATE TABLE IF NOT EXISTS `partners` (
`id` int(10) unsigned NOT NULL auto_increment,
`name` varchar(255) default NULL,
`last_name` varchar(255) default NULL,
) ENGINE=MyISAM;
答案 0 :(得分:5)
我还会在收到付款时附上日期时间戳,如果付款完成或金额不完整,可能会标记。
答案 1 :(得分:4)
一些共同点:
在这种情况下,我会考虑将月份作为枚举。它当然可以消除所有歧义,除非你需要在该领域进行数学运算(之前是这样)。
钱应该存储为十进制,而不是浮点数。如果没有奇怪的四舍五入的东西。
没有订单价格的概念。如果他们支付不足,你怎么知道多少?
(与3相关的类型)您通常会将此视为发票和付款类型表示(即使您不开具发票),这意味着一次付款可能代表多个订单,反之亦然,这意味着多对多的关系。
你关心他们的付款方式吗? (支票,信用卡,现金等?)
如果只能在一个月内收到一个订单,为什么要订购多笔付款?如果在同一个月内收到付款,您会怎么做?这里真的应该只有一对一的关系吗?
答案 2 :(得分:2)
我同意jtyost2和Yishai之前的答案。
另外请注意,我们的约定是以单数形式命名实体表,与类名匹配。也就是说,我们命名一行(我们命名该类的一个实例)而不是命名该集合。我们问的问题是,这个表中的一行代表一个什么?我们在课堂和桌子上使用这个单数名称。 (预测反对意见,是的,我确实认识到其他开发人员和其他框架遵循'复数表名'约定.Rails在复数化方面甚至足够聪明,可以从Person类生成“people”表。)
但是当表名开始变得多元化时,我注意到通常只有一些表名被复数化,并且它最终是混合的单数和复数名称。
`partner_id`
`order_id`
您的外键列的命名方式与我们命名它们的方式完全相同。我们遵循的外键列约定是使用父表的名称,然后使用_id。对于同一个表的多个关系,除了表名之外或代替表名,我们使用角色的名称。
我还建议在数据库中添加外键约束定义,即使MyISAM引擎没有强制执行它们。
在每个表的ID列上添加主键约束(partner
表中似乎缺少。
使用unqiue索引识别自然键。
在我看来,付款有两种模式:
这是亚马逊似乎使用的模型。可能会向订单申请奖励优惠券和积分,但在付款时,我只为该订单支付一笔款项。
另一种模式是使用帐户,并将费用,信用和付款应用于帐户。这是电话公司等公用事业常用的模型。这允许诸如当前余额和到期金额之类的概念。
在这方面,你的设计似乎是非常规的。没有客户帐户的概念。然而,似乎一个订单会有多笔付款。
答案 3 :(得分:2)
payment_date
添加到payments
会让您摆脱orders.last_check_on
以支持视图payments.month
和payments.year
似乎很奇怪。如果这是一个会员制,我会假设你只是按现收现付。因此,从订单日期开始,6笔付款将为您提供6个月的会员资格。没有必要跟踪付款的月份(否则,当我支付第6个月和第7个月而不是1-5个月时,它意味着什么?)如果这里有更多的复杂性,可能需要另外一两个表那个概念。......管理会员资格和其他类型付款的项目
type
枚举('membership','其他')有月,年NULL-ABLE的想法允许保存任何其他付款的记录
我可能不在这里,但听起来你正在试图猜测未来的要求。如果是这样的话......不要。没有一个通用的数据库模式 - 所以不要破坏您为将来可能构建或不构建的应用程序构建的应用程序。
如果您有成员之外的具体用例,请分享。但是,我觉得它最适合2种不同的型号。 Type
和可以为空的列通常会尖叫,你试图将这些内容与不同的东西挂在同一张桌子上。
答案 4 :(得分:1)
CREATE TABLE [dbo].PaymentLog(
TransactionNumber int IDENTITY(1,1) NOT NULL,
ReferenceID int NOT NULL,
ReferenceType varchar(20) NULL,
TransactionID int NULL,
CustomerID int NULL,
PaymentMethod char(4) NULL,
LogType varchar(20) NULL,
UserHostAddress varchar(20) NULL,
Content nvarchar(4000) NULL,
ReasonCode varchar(20) NULL ,
Flag nvarchar(20) NULL ,
Note nvarchar(200) NULL,
[InDate] [datetime] NOT NULL CONSTRAINT DF_PaymentLog_InDate DEFAULT (GETDATE()),
[InUser] [nvarchar](100) NULL,
CONSTRAINT PK_PaymentLog PRIMARY KEY CLUSTERED (
TransactionNumber
)
)
GO
CREATE NONCLUSTERED INDEX [IX_PaymentLog_ReferenceID] ON [dbo].PaymentLog (
ReferenceID ASC
) WITH FILLFACTOR = 90
GO
答案 5 :(得分:0)
此外,我将源代码放在另一个表中,因为您可能需要在应用程序增长时添加一些源。