nopcommerce中文网

nopcommerce是国外asp.net领域一个高质量的b2c开源项目,基于EntityFramework和MVC开发,QQ群1:75272942(2000人超级群,已满) QQ群2:640322459

导航 - 搜索

为nopcommerce自定义用户积分功能(2)

积分功能第二部,不了解情况的可以先看看第一部

nopcommerce的总体架构我们就不多说了,从WEB到逻辑再到数据库访问都有地方要修改,本文主要演示逻辑和数据库访问的修改,Web界面上的后边会提到如何调用。

首 先我们有一个新的reward point provider,那么在web.config的sectionGroup里要加上:<section name=”RewardProvider” type=”NopSolutions.NopCommerce.DataAccess.DBProviderSection, Nop.DataAccess” requirePermission=”false”/>

在nopDataProviders的最后也要加上:

<RewardProvider defaultProvider=”SQLRewardProvider”>
<providers>
<add name=”SQLRewardProvider” type=”NopSolutions.NopCommerce.DataAccess.Promo.SQLRewardProvider, Nop.DataAccess.SqlServer” connectionStringName=”NopSqlConnection”/>
</providers>
</RewardProvider>

NopContext里也要加个字段用来保存当前session下的积分值:

public decimal RewardPoint
{
get {
if (HttpContext.Current.Session["RewardPoint"] == null)
return decimal.Zero;

decimal ret = decimal.Zero;
if (decimal.TryParse(HttpContext.Current.Session["RewardPoint"].ToString(), out ret))
return ret;
else
return decimal.Zero;
}
set
{
HttpContext.Current.Session["RewardPoint"] = value;
}
}

现在再来看数据库抽象接口的代码,各个方法什么意思想必大家一看就懂:

namespace NopSolutions.NopCommerce.DataAccess.Promo
{
[DBProviderSectionName("nopDataProviders/RewardProvider")]
public abstract partial class DBRewardProvider : BaseDBProvider
{
public abstract bool RewardCalculation(decimal point, int customerID, int orderid, string details);
public abstract DBCustomerCollection CustomerRewardList();
public abstract DBRewardAuditCollection GetAllAuditList(DateTime from, DateTime to);
public abstract DBRewardAuditCollection GetAuditByOrderID(DateTime from, DateTime to, int OrderID);
public abstract bool RewardPointSetTo(decimal point, int customerID, string details);
}
}

DBRewardAudit的定义:

namespace NopSolutions.NopCommerce.DataAccess.Promo
{
public partial class DBRewardAudit : BaseDBEntity
{
public int RewardID { get; set; }
public int OrderID { get; set; }
public DateTime RewardTime { get; set; }
public string Status { get; set; }
public decimal Amount { get; set; }
public string RewardDetails { get; set; }
}
}

按照标配来说还得要个DBRewardAuditCollection,我形式上加了这个文件,但没实质内容,如果管理员要求在登录网店后看到历史记录,可以用这个。

数据层的DBCustomer还要加上个RewardPoint属性:

namespace NopSolutions.NopCommerce.DataAccess.CustomerManagement
{
public partial class DBCustomer : BaseDBEntity
{
public decimal RewardPoint { get; set; }
}
}

数 据库层的UpdateCustomer方法的参数要修改,把reward point属性传进去,SQL里update的时候也能更新积分,在这儿就省略了。DBOrder也要加同样的public decimal RewardPoint { get; set; }属性。InsertOrder方法也要把RewardPoint包含进来。

具体的数据访问层,我这儿有个SQLRewardProvider.cs供参考。SQLRewardProvider

然后再看看业务逻辑层的RewardManager.cs,RewardManager,简单的代码,就不用再描述了。

OK到这儿大部分接口已经实现了,只等客户端代码调用了,所有的逻辑层,web层的代码都可以称为客户端代码,那么我们来试试下订单后消耗积分的情况。OrderManager.cs 中的PlaceOrder,

….

Order order = InsertOrder(OrderGuid, //这儿注意,用刚才修改过的方法,把积分传进去。

….

等有了OrderID = order.OrderID;这句,订单也生成了,那么就要扣掉相应的积分了,直接在这句后边加上:

//reward function
if (NopContext.Current.RewardPoint > customer.RewardPoint)//reward point cannot greater than customer’s point.
NopContext.Current.RewardPoint = customer.RewardPoint;

if (OrderID >= 0 && NopContext.Current.RewardPoint > decimal.Zero)//success, deduct reward points
RewardManager.RewardCalculation(decimal.Zero – NopContext.Current.RewardPoint, customer.CustomerID, OrderID,”Order placed with ” + RewardManager.RewardName + NopContext.Current.RewardPoint.ToString());

然后再接着往下走找到SendOrderPlacedStoreOwnerNotification和SendOrderPlacedCustomerNotification,里边的方法改改,让email可以支持reward point的消息:

首先要定义这些消息的token是什么,在GetListOfAllowedTokens里添加:

//added comments and reward points – by dingsea:
allowedTokens.Add(“%Order.RewardPointApplied%”);
allowedTokens.Add(“%Customer.CurrentRewardPoint%”);
allowedTokens.Add(“%Customer.WinRewardPoint%”);
allowedTokens.Add(“%Settings.RewardName%”);
//ends here.

ReplaceMessageTemplateTokens里加上如下字段以方便在正则替换的时候找到对应的文字:

//added: dingsea
tokens.Add(“Order.RewardPointApplied”, HttpUtility.HtmlEncode(order.RewardPoint.ToString(“N2″)));
tokens.Add(“Customer.WinRewardPoint”,HttpUtility.HtmlEncode((order.OrderTotal * RewardManager.RewardPercentage).ToString(“N2″)));
tokens.Add(“Customer.CurrentRewardPoint”,HttpUtility.HtmlEncode(NopContext.Current.User.RewardPoint.ToString(“N2″)));
tokens.Add(“Settings.RewardName”,HttpUtility.HtmlEncode(RewardManager.RewardName));

既然都到这里了,那也把nopcommerce的一个小BUG也补上:

ProductListToHtmlTable方法中没有打折信息(在order details页面也有同样问题,同学们自行加上吧),所以我把打折和积分信息一起加上了:

//fixed by dingsea – discount is missing
string CusDiscount = string.Empty;
string CusRewardPoint = string.Empty;

……

//fixed by dingsea – discount and reward point
CusDiscount = order.OrderDiscount == decimal.Zero ? string.Empty : PriceHelper.FormatPrice(order.OrderDiscount, true, order.CustomerCurrencyCode, language, false);
CusRewardPoint = order.RewardPoint.ToString(“N2″);

…….

//fixed by dingsea – discount and reward point
if(CusDiscount!=string.Empty)
sb.AppendLine(“<tr><td style=\”text-align:right;\” colspan=\”3\”><strong>” + LocalizationManager.GetLocaleResourceString(“ShoppingCart.Sub-TotalDiscount”, LanguageID) + “</strong></td> <td style=\”text-align:right;\”><strong>” + CusDiscount + “</strong></td></tr>”);
sb.AppendLine(“<tr><td style=\”text-align:right;\” colspan=\”3\”><strong>” + LocalizationManager.GetLocaleResourceString(“Promotion.RewardPointName”, LanguageID) + “</strong></td> <td style=\”text-align:right;\”><strong>” + CusRewardPoint + “</strong></td></tr>”);
//fix ends

于是呼,在你的template->message template里订单生成时向用户和店主发的email里就可以支持积分的token了。

至于在web如何调用,那就比较容易了,在你想要的页面加上一个textbox,确保用户输入的是decimal,那就够了,这个数字会存到session里直到用户下单。而且在管理界面,利用rewardmanager的方法可以直接操作积分,方便快捷。

为nopcommerce自定义用户积分功能(1)

nopcommerce本身不带用户积分功能,至少1.4还没有。基本目前的用户需求,等不到官方发布这个功能了。我们来自己实现一个简单的用户积分,积分历史记录暂时通过SQL查询

先 来看看基本需求和大概流程。首先这个积分不像凡客那种买个东西就几千上万分,我们所定义的积分就是一种虚拟货币,而且和网店主要货币的汇率为1,我们的 目的很简单,用户在每次购物以后可以给用户的帐户里添加X元的货币,这个货币的名字用户可以自定义,比如这个网店我想取名叫A$,那个网店我想叫 Z$,或者直接叫RMB也行。为了简单起见我们规定在每次购物以后用户可以得到1%的货币(为了更好的区分,以下用“积分”代替),而且积分是扣掉打折以 后再开始计算的。例如用户购买了200元的东西,打折10%即20元,这样用户需要支付180元,所得积分为180*1%=1.8元。当然这个百分比是可 以随时更改的。

要注意的是用户下单后不是马上得到积分而是在网店收到钱以后,由管理员在更新状态时同时给用户添加积分。管理员也可以选 择不给此人增加积分,或者给此人增 加另一个数额的积分,而且在用户管理页面管理员也可以直接对用户的积分进行修改。为了把积分概念深入人心,用户下单以后也要加到邮件通知里。

综上所述我们要的流程如下:

1.用户下单,结帐,email通知用户下单成功并能获得X元的积分,此积分下一次可以在购物时使用。
2.用户付款以后管理员给用户添加积分
3.用户获得积分,下次可以使用。

我们先来进行必要的设置,包括本地化、全局设置以及修改数据库。

configuration->all settings->add new,添加两项设置“RewardPercent”和“RewardPoint”,分别为获得积分的百分比和积分的货币符号。

content management->localization->add new,添加两项“Promotion.RewardMessageForGuest”和“Promotion.RewardPointName”分别为 guest user在结帐时的提示信息和本地化以后的货币符号,其实这个可以用上边的积分符号代替。

然后,我们在数据库里添加一个新的表
CREATE TABLE [dbo].[Nop_RewardAudit](
[RewardID] [int] IDENTITY(1,1) NOT NULL,
[OrderID] [int] NOT NULL,
[RewardTime] [datetime] NOT NULL,
[Status] [nchar](10) NOT NULL,
[Amount] [money] NOT NULL,
[RewardDetails] [nvarchar](2000) NULL,
CONSTRAINT [PK_Nop_RewardAudit] PRIMARY KEY CLUSTERED
(
[RewardID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY]
) ON [PRIMARY]
这个表用来做audit,目前还没有把audit的界面做出来,不过功能倒是设计出来了,有空加上。然后分别再向customer表和order表加一个money字段:

ALTER TABLE dbo.Nop_Customer SET (LOCK_ESCALATION = TABLE)

order表的类似,我把代码搞没了,大家自己加上应该没问题。接下来老丁我还得改几个存储过程,不过强烈建议放到后边改,是更新用户和插入订单的。

CREATE PROCEDURE dbo.Nop_CustomerRewardPointCalculation
@cID int,
@orderID int,
@points money,
@details nvarchar(2000)
AS
update nop_customer
set rewardPoint = rewardPoint + @points
where CustomerID = @cID

insert into Nop_RewardAudit
(OrderID,RewardTime,Status,Amount,RewardDetails)
values
(@orderID,getdate(),””,@points,@details)

还有:
CREATE PROCEDURE dbo.Nop_CustomerSetRewardPoint
@cID int,
@orderID int,
@points money,
@details nvarchar(2000)
AS
update nop_customer
set rewardPoint = @points
where CustomerID = @cID

insert into Nop_RewardAudit
(OrderID,RewardTime,Status,Amount,RewardDetails)
values
(0,getdate(),””,@points,@details)
RETURN

更新用户信息:

CREATE PROCEDURE [dbo].[Nop_CustomerUpdate]
(
@CustomerId int,
@CustomerGUID uniqueidentifier,
@Email nvarchar(255),
@PasswordHash nvarchar(255),
@SaltKey nvarchar(255),
@AffiliateID int,
@BillingAddressID int,
@ShippingAddressID int,
@LastPaymentMethodID int,
@LastAppliedCouponCode nvarchar(100),
@LanguageID int,
@CurrencyID int,
@TaxDisplayTypeID int,
@IsTaxExempt bit,
@IsAdmin bit,
@IsGuest bit,
@IsForumModerator bit,
@TotalForumPosts int,
@Signature nvarchar(300),
@AdminComment nvarchar(4000),
@Active bit,
@Deleted bit,
@RegistrationDate datetime,
@TimeZoneID nvarchar(200),
@Username nvarchar(100),
@AvatarID int,
@RewardPoint money
)
AS
BEGIN

UPDATE [Nop_Customer]
SET
CustomerGUID=@CustomerGUID,
Email=@Email,
PasswordHash=@PasswordHash,
SaltKey=@SaltKey,
AffiliateID=@AffiliateID,
BillingAddressID=@BillingAddressID,
ShippingAddressID=@ShippingAddressID,
LastPaymentMethodID=@LastPaymentMethodID,
LastAppliedCouponCode=@LastAppliedCouponCode,
LanguageID=@LanguageID,
CurrencyID=@CurrencyID,
TaxDisplayTypeID=@TaxDisplayTypeID,
IsTaxExempt=@IsTaxExempt,
IsAdmin=@IsAdmin,
IsGuest=@IsGuest,
IsForumModerator=@IsForumModerator,
TotalForumPosts=@TotalForumPosts,
[Signature]=@Signature,
AdminComment=@AdminComment,
Active=@Active,
Deleted=@Deleted,
RegistrationDate=@RegistrationDate,
TimeZoneID=@TimeZoneID,
Username=@Username,
AvatarID=@AvatarID,
RewardPoint = @RewardPoint
WHERE
[CustomerId] = @CustomerId

END

Nop_OrderInsert的就不用我再放上来了吧,按上边这个SP来改问题不大。

今天先发到这儿。明天继续发CS代码部分。