65.9K
CodeProject 正在变化。 阅读更多。
Home

数据中心:产品信息和促销管理系统

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.84/5 (9投票s)

2012 年 1 月 23 日

CPOL

11分钟阅读

viewsIcon

31945

一个用于轻松有效地存储产品信息和管理促销的系统

Home screen

引言

您的应用程序/扩展程序做什么?它解决了什么业务问题?

Office Products Depot 数据中心旨在成为我们业务中所有产品和促销信息的中心枢纽。它旨在成为唯一的信息来源,以清晰、简洁和一致的方式提供这些信息。

我们业务中存在两个主要问题,数据中心旨在为此提供解决方案

  1. 我们是一个由 37 家独立拥有的文具店(经销商)组成的合作团体,位于新西兰各地。由于每家店都是一个独立的业务,它们各自的 ERP 系统中都有自己的产品信息数据库。历史上,每家店都维护自己的数据库。最近,我们已转向在全国支持办公室 (NSO) 维护产品信息,然后将这些信息分发到商店的数据库。我们一直在使用我们 ERP 系统的副本执行此操作,这产生了它自己的一系列挑战,因为它并非为此目的而设计。使用我们的 ERP 系统存储产品信息所产生的主要问题是
    1. 无法让所有相关信息对产品管理员可见
    2. 一些信息使用非常规方法存储,这使得提取困难且缓慢
    3. 任何自定义数据提取都需要自定义报告,这会耗费大量时间来创建和运行
    4. 可用的历史信息很少,且大部分毫无意义
    5. 在未来的特定日期更新成本价格是一个尴尬的过程,通过我们 ERP 的肮脏“黑客”才得以实现

    数据中心通过替换我们的 ERP 作为主要数据源来解决这些问题,从而以更清晰、更一致的方式显示数据,使用直观且易于使用的表单,允许用户使用熟悉的方法创建自己的报告,记录和显示相关且有意义的历史信息,并提供一种简单的方法将未来发生的成本价格变化添加到数据库中。

  2. 每年我们制作 12 份传单,每份长达 18 页,一份长约 500 页的主要目录,许多发送给我们客户的电子邮件促销活动,以及其他几份专注于特定类别或客户群的目录。到目前为止,我们一直通过多个 Excel 电子表格处理创建这些促销材料的过程,这些电子表格在我们办公室和供应商之间通过电子邮件发送以确认数据,然后进行整理和检查,最后用于填充促销活动的布局。随着我们的促销活动变得越来越复杂,这种 Excel 电子表格系统需要越来越多的时间来维护和分发。每次只能一个人编辑每个电子表格,这意味着这个问题无法通过投入更多资源来解决。

    数据中心通过为所有促销信息提供一个中央存储库,并允许我们的供应商在我们将这些信息用于任何出版物之前通过 LightSwitch 网络门户访问并确认这些信息来解决了这个问题。多个用户可以同时访问相同的信息。许多繁琐的数据输入任务已实现自动化或简化。得益于 LightSwitch 和数据中心,我们希望大幅缩短促销信息整理和确认的周转时间,从而使我们能够以相同的资源水平制作更高质量的促销材料。

    数据中心需要与我们的 ERP 系统完全集成,以使数据中心中维护的信息能够轻松流入我们的 ERP,然后下发到我们商店的数据库。这已轻松实现,这得益于 LightSwitch 由 SQL Server 支持,从而允许简单的数据提取。

    这并非系统要求,但我们强烈希望将数据中心托管在云端。得益于 LightSwitch 与 Windows Azure 的紧密关系,这一愿望得以实现。数据中心是一个桌面应用程序,但应用程序服务托管在 Azure 上,并且应用程序的所有数据都存储在 SQL Azure 中。我之所以将数据中心制作成桌面应用程序,是因为它需要访问用户系统上的 Excel 和 Outlook。连接到同一 SQL Azure 数据库的供应商确认中心门户是一个完全托管在 Windows Azure 上的 Web 应用程序。这需要是一个 Web 应用程序,因为我们不愿意要求我们的供应商在其网络上安装我们创建的应用程序。

    数据中心将大幅提高我们业务的准确性和效率,使我们能够更专注于战略性举措,而不是数据输入和维护。

这个应用程序有多少屏幕和实体?

数据中心包含 2 个项目中的 28 个屏幕和 25 个实体。

LightSwitch 为您的业务节省了资金吗?如何节省?

LightSwitch 为我们节省了资金,因为我们能够在内部开发数据中心。这节省了承包商和/或第三方开发人员的费用。LightSwitch 还使我们能够在未来轻松扩展数据中心,这将节省更多资金。LightSwitch 让我们能够将功能集成到数据中心中,这将使我们能够制作更多促销材料,从而为我们的业务创造更多收益。我们还将节省资金并减轻业务压力,因为产品信息更加及时且更易于维护。将应用程序托管在 Windows Azure 上也为我们节省了资金,因为我们无需设置任何新服务器,并且可以根据需求扩展 Web 应用程序或完全关闭它。如果当初我们没有使用 LightSwitch,那么利用 Windows Azure 的这些优势将非常困难。

我估计 LightSwitch 至少为我们节省了 20,000 美元的开发成本。LightSwitch 在数据中心提供的功能将继续每年为我们的业务节省数万美元,并使我们能够制作更多促销活动,从而创造收入而不是节省开支。

如果您没有 LightSwitch,这个应用程序还会被构建出来吗?如果会,用什么构建?

是的。我们当时正在调查由第三方承包商使用 ASP.NET Web Forms 构建一个 Web 应用程序版数据中心。我之前使用 ASP.NET 动态数据构建了一个原始版数据中心,但该应用程序的开发时间是 LightSwitch 数据中心的两倍,功能仅为其 10%。LightSwitch 在成本、速度和质量方面都让这两个选项望尘莫及。

这个应用程序支持多少用户?

全国支持办公室的 10 个用户,以及可能通过网络门户连接的 300 多家供应商,尽管并非所有人都需要使用它。但如果确实需要向 300 家供应商提供访问权限,这也可以轻松实现,这得益于 Windows Azure 的可扩展性。再加上可以在不需要时完全关闭网络服务器且不收取使用费的功能,这是我们决定使用 Azure 平台的主要原因。

使用 LightSwitch 构建此应用程序实际花了多长时间?

数据中心从开始到完成大约花了 4 周时间,尽管那段时间进行了大量的学习和阅读。如果我现在从头开始创建它,所需时间会更少。

此应用程序是否使用任何 LightSwitch 扩展?如果使用,是哪些?您自己编写过这些扩展吗?如果编写过,是否公开发布?在哪里?

数据中心使用以下扩展

  1. Microsoft 的 Microsoft LightSwitch 扩展
  2. GridLogic 的 Office 集成包
  3. Microsoft 的 Excel 导入器
  4. ComponentOne 的 ComponentOne OLAP for LightSwitch

我没有编写这些扩展中的任何一个。除了 ComponentOne OLAP 之外,它们都可以通过扩展管理器获取,ComponentOne OLAP 可以在 ComponentOne 网站上找到。我强烈推荐他们的扩展,我认为每个 LightSwitch 应用程序都应该使用它!

LightSwitch 如何让您的开发人员生活更好?与您考虑过的其他选项相比,构建速度是否更快?

在使用 LightSwitch 之前,我创建了一个 ASP.NET 动态数据 Web 应用程序来管理数据。有了 LightSwitch,我能够在一半的时间内构建一个功能多 90% 的应用程序,而动态数据解决方案的设计和构建时间却更长。我们的用户对最终产品更加满意,这让我的开发人员生涯变得 1,000,000% 更好!

LightSwitch 让我成为了有史以来最高效的开发人员。它不仅鼓励正确的,而且使其快速而简单地执行。LightSwitch 让我可以专注于添加对用户大有裨益的功能,而不是花费时间让基本功能正常工作。如果没有 LightSwitch,我无法在可用时间内提供这些功能。我不相信第三方或承包商也能做到。我们原本会妥协我们的最初愿景,最终得到一个可能比我们之前的系统效率略高但无法进一步定制的系统。多亏了 LightSwitch,我们打下了坚实的基础,可以在此基础上随着时间的推移,通过仔细、周密、增量的开发,解决我们业务中更多的问题。

通常,我使用 C# 编程,但在看到 Visual Studio LightSwitch 的惊人能力之后,我再也不喜欢回到用 C# 创建东西了。这真是一种顿悟,我现在不用它的时候,感觉就像在逆风而行。感谢微软开发出如此强大、易用的工具!还要感谢支持该产品的 LightSwitch 社区以及本次比赛所得到的支持。看到世界各地的人们都在使用 LightSwitch,真是令人振奋和受益匪浅。谢谢 CodeProject!

链接、截图、视频

如果有人有兴趣阅读完整的文档(不包括大型附录),可以在此处下载 7 MB 的 Word 文档。它描述了许多流程如何工作,并已作为培训文档提供给我们的用户。

屏幕截图

主屏幕

Home screen

产品详细信息屏幕,带价格历史图表,这得益于 ComponentOne 的 Silverlight 图表,包含在其 OLAP 扩展中

Product Details

ComponentOne Olap 屏幕运行中

Analyze Products

Analyze Products Chart

批量编辑屏幕

Bulk Edit screen

促销编辑屏幕

Promotion screen

供应商确认门户

Supplier Confirmation Portal

向我们展示您作为此解决方案的一部分开发的酷炫或独特的代码或技术。

此代码用于一个屏幕,我允许用户上传包含来自供应商的新定价信息的电子表格。信息上传到屏幕后,用户点击一个按钮,运行以下代码

void AddThisPricingToProducts()
{
    /* this function adds the pricing to the product prices table 
     * I've done it this way so that I can change the end date on the price that currently
     * has a blank end date so that only one price ever has a blank end date
    */
    //Get all the price changes uploaded
    var TheseProductPriceChanges = 
        this.DataWorkspace.ApplicationData.ProductPriceChanges.OrderBy(x => x.Id);

    foreach( ProductPriceChange ThisProductPriceChange in TheseProductPriceChanges)
    {
        //if there is a price record which matches the candidate key on the product
        //prices table then check the information on that record
        var MatchingProductPrices = this.DataWorkspace.ApplicationData.ProductPrices.
            Where(x => x.ProductPriceProductCode.Id == ThisProductPriceChange.Product.Id && 
                x.ProductPriceSupplier.Id == ThisProductPriceChange.Supplier.Id && 
                x.ProductPriceUnit.Id == ThisProductPriceChange.Unit.Id && 
                x.ProductPriceEndDate == null);
        ProductPrice CurrentProductPrice = null;
        if (MatchingProductPrices != null)
        {
            CurrentProductPrice = MatchingProductPrices.FirstOrDefault();
        }

        if (CurrentProductPrice != null)
        {
            //Change the end date on the current price so that the system knows 
            //when to use the new price
            CurrentProductPrice.ProductPriceEndDate = 
                          ThisProductPriceChange.ProductPriceChangeStartDate;

            //if the Cost price and the RRP on the product price in question 
            //are the same as what we
            //are loading then don't bother loading anything.
            if (CurrentProductPrice.ProductPriceCostExGST == 
                    ThisProductPriceChange.ProductPriceChangeCostExGST && 
                CurrentProductPrice.ProductPriceRRPExGST == 
                    ThisProductPriceChange.ProductPriceChangeRRPExGST)
            {
                this.ShowMessageBox("The current pricing for product: " + 
                    CurrentProductPrice.ProductPriceProductCode.ToString() + 
                    "\nmatches the pricing currently in the system.
                     \n\nBecause of this no changes were made.");
                ThisProductPriceChange.Delete();
                continue;
            }

            //if the price that we are loading is more than 50% different 
            //to the price that is in
            //the database then the user will need to confirm that the price change is valid
            //and the price will not be loaded
            if ((((CurrentProductPrice.ProductPriceCostExGST - 
                   ThisProductPriceChange.ProductPriceChangeCostExGST) 
                / CurrentProductPrice.ProductPriceCostExGST) * 100) > (decimal)50.00)
            {
                this.ShowMessageBox("The current pricing for product: " + 
                    CurrentProductPrice.ProductPriceProductCode.ToString() + 
                    "\nis significantly different to the current price 
                    in the system:\n\nCurrent Price: " + 
                    CurrentProductPrice.ProductPriceCostExGST.ToString() + "\n\nNew Price: " + 
                    ThisProductPriceChange.ProductPriceChangeCostExGST.ToString() + 
                    ".\n\nBecause of this no changes were made." + 
                    "\nIf this price change is valid you will need to process it manually.");
                ThisProductPriceChange.Delete();
                continue;
            }
        }

        //Load the new product price into the database
        ProductPrice NewProductPrice = new ProductPrice();

        NewProductPrice.ProductPriceProductCode = ThisProductPriceChange.Product;
        NewProductPrice.ProductPriceSupplier = ThisProductPriceChange.Supplier;
        NewProductPrice.ProductPriceUnit = ThisProductPriceChange.Unit;
        NewProductPrice.ProductPriceStartDate = 
                        ThisProductPriceChange.ProductPriceChangeStartDate;
        NewProductPrice.ProductPriceEndDate = 
                        ThisProductPriceChange.ProductPriceChangeEndDate;
        NewProductPrice.ProductPriceCostExGST = 
                        ThisProductPriceChange.ProductPriceChangeCostExGST;
        NewProductPrice.ProductPriceRRPExGST = 
                        ThisProductPriceChange.ProductPriceChangeRRPExGST;
        NewProductPrice.ProductPriceComment = 
                        ThisProductPriceChange.ProductPriceChangeComment;
        ThisProductPriceChange.Delete();
    }

    return;
}

此代码将阻止价格变动超过 50%,因为这通常表示数据问题。如果信息与数据库中已有的信息相同,它将不会对数据库进行任何更改。当价格发生变化时,它会将当前价格的结束日期设置为与新价格的开始日期相同,这样用户就不必手动执行这项繁琐的任务。这为我们公司节省了时间和金钱,并使我们的用户在执行繁琐的数据输入任务时免于睡着。

关注点

在编写应用程序时,你学到了什么有趣/好玩/烦人的东西吗?

如果你在新西兰,并且你的数据托管在 Azure 上,那么使用美国区域而不是亚洲区域的连接似乎更快,这与我预期的相反。在我测试之前有人告诉我这一点,我没有相信他们——我应该相信他们!

你做了什么特别聪明、疯狂或古怪的事情吗?

我认为数据中心的促销确认系统非常巧妙,它将为我们的产品管理员和供应商节省大量时间(从而为我们的公司和供应商节省资金),用于追查信息和一遍又一遍地重新检查相同的数据。

每次供应商在网络门户中更改信息时,都会在另一个表中创建一个条目,其中包含旧值、新值以及进行更改的人。我们这边的用户随后有机会审查所做的更改,如果他们愿意,可以在勾选框并单击按钮将更改导入数据中心之前进行更改。这样,我们就能更有效地处理外部来源对我们信息所做的更改,同时仍然对数据的完整性保持一定程度的控制。完整的流程在本文章顶部链接和下载部分可下载的培训文档中进行了解释。

感谢阅读!

历史

  • 2012 年 1 月 23 日:初始版本
© . All rights reserved.