Thursday, 28 December 2017

ebay delivery aspcore


.asp core project ebay_track
search by shipping date

additional filters for search

dropdown list is sorted

sort by item

sort by date

every action is logged by history controller


dropdown list item is selected based on record

do a final validation before search form submission, 
found error start date entered is later than end date


input type: text, date, number, select list




----------------------------------------------------------------------------------------
delivery controller

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using ebay_track.Models;
using Microsoft.AspNetCore.Http;

namespace ebay_track.Controllers
{
    public class DeliveriesController : Controller
    {
        private readonly ebayContext _context;

        public DeliveriesController(ebayContext context)
        {
            _context = context;
        }

        public async Task<IActionResult> Index()
        {
            ViewBag.c_end = DateTime.Now;
            ViewBag.c_begin = "";

            var ebayContext = _context.Delivery.Include(d => d.Item).
                Where(x => x.Arrived == "N" &&x.CaseClosed!="Y");

            ViewBag.ItemId = await _context.Item.ToListAsync();

            return View(await ebayContext.ToListAsync());
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Index(IFormCollection collection)
        {         

            var search_result = new List<Delivery>();

            var C_begin = DateTime.Now.AddYears(-10);
            var C_end = DateTime.Now;

            if (collection["begin"] != "") { C_begin = Convert.ToDateTime(collection["begin"]); }
            if (collection["end"] != "") { C_end = Convert.ToDateTime(collection["end"]); }

            ViewBag.c_end = C_end;
            ViewBag.c_begin = C_begin;
            ViewBag.ItemId = await _context.Item.ToListAsync();

            //filter by calendar
            search_result = await _context.Delivery.Include(d => d.Item).
                Where(x => DateTime.Compare(C_begin, x.ShippingDate) < 0 && DateTime.Compare(C_end, x.ShippingDate) > 0).ToListAsync();

            //filter by delivery status
         
            var delivery_status = collection["delivery"].ToString();

            if (delivery_status=="Y"||delivery_status=="N")
            {             
                search_result = search_result.Where(x => x.Arrived == delivery_status).ToList();
            }

            //filter by case_closed
            var case_closed_status = collection["case_closed"].ToString();

            if (case_closed_status=="Y")
            {
                search_result = search_result.Where(x => x.CaseClosed == "Y").ToList();
            }
            else if(case_closed_status=="N")
            {
                search_result = search_result.Where(x => x.CaseClosed != "Y").ToList();
            }
            else
            { }

            //filter by item
            if (collection["item_select"] != "")
            {
                var item_number = Convert.ToInt32(collection["item_select"]);

                search_result = search_result.Where(x => x.ItemId == item_number).ToList();
            }

            return View(search_result);
        }

        // GET: Deliveries/Details/5
        public async Task<IActionResult> Details(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var delivery = await _context.Delivery
                .Include(d => d.Item)
                .SingleOrDefaultAsync(m => m.Id == id);
            if (delivery == null)
            {
                return NotFound();
            }

            return View(delivery);
        }

        // GET: Deliveries/Create
        public async Task<IActionResult> Create()
        {

            ViewBag.ItemId = await _context.Item.ToListAsync();
            return View();
        }

        // POST: Deliveries/Create
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create([Bind("Id,ItemId,ShippingDate,DeliveryDate,Qty,Tracking,Arrived,CaseClosed")] Delivery delivery)
        {
            if (ModelState.IsValid)
            {
                _context.Add(delivery);
                await _context.SaveChangesAsync();

                //------------------------------------------------------
                var item = await _context.Item.SingleOrDefaultAsync(m => m.Id == delivery.ItemId);

                var history = new History
                {
                    ActionDate = DateTime.Now,
                    ActionType = "Create",
                    Item = item.Name,
                    Qty = delivery.Qty,
                    Tracking = delivery.Tracking,
                    DeliveryDate=delivery.DeliveryDate,
                    ShippingDate=delivery.ShippingDate
                };

                HttpContext.Session.SetObjectAsJson("action", history);
                //redirect to history controller to save a record of the action
                return RedirectToAction("receiver", "Histories");
                //------------------------------------------------------
            }
            ViewData["ItemId"] = new SelectList(_context.Item, "Id", "Name", delivery.ItemId);
            return View(delivery);
        }

        // GET: Deliveries/Edit/5
        public async Task<IActionResult> Edit(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var delivery = await _context.Delivery.SingleOrDefaultAsync(m => m.Id == id);
            if (delivery == null)
            {
                return NotFound();
            }
            ViewData["ItemId"] = new SelectList(_context.Item, "Id", "Name", delivery.ItemId);
            return View(delivery);
        }

        // POST: Deliveries/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Edit(int id, [Bind("Id,ItemId,Qty,ShippingDate,DeliveryDate,Tracking,Arrived,CaseClosed")] Delivery delivery)
        {
            if (id != delivery.Id)
            {
                return NotFound();
            }

            if (ModelState.IsValid)
            {
                try
                {
                    _context.Update(delivery);
                    await _context.SaveChangesAsync();
                }
                catch (DbUpdateConcurrencyException)
                {
                    if (!DeliveryExists(delivery.Id))
                    {
                        return NotFound();
                    }
                    else
                    {
                        throw;
                    }
                }
                //------------------------------------------------------
                var item = await _context.Item.SingleOrDefaultAsync(m => m.Id == delivery.ItemId);

                var history = new History
                {
                    ActionDate = DateTime.Now,
                    ActionType = "Edit",
                    Item = item.Name,
                    Qty = delivery.Qty,
                    Tracking = delivery.Tracking,
                    DeliveryDate = delivery.DeliveryDate,
                    ShippingDate = delivery.ShippingDate
                };

                HttpContext.Session.SetObjectAsJson("action", history);
                //redirect to history controller to save a record of the action
                return RedirectToAction("receiver", "Histories");
                //-----------------------------------------------------------
            }
            ViewData["ItemId"] = new SelectList(_context.Item, "Id", "Name", delivery.ItemId);
            return View(delivery);
        }

        // GET: Deliveries/Delete/5
        public async Task<IActionResult> Delete(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var delivery = await _context.Delivery
                .Include(d => d.Item)
                .SingleOrDefaultAsync(m => m.Id == id);
            if (delivery == null)
            {
                return NotFound();
            }

            return View(delivery);
        }

        // POST: Deliveries/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> DeleteConfirmed(int id)
        {
            var delivery = await _context.Delivery.SingleOrDefaultAsync(m => m.Id == id);
            _context.Delivery.Remove(delivery);
            await _context.SaveChangesAsync();

            //------------------------------------------------------
            var item = await _context.Item.SingleOrDefaultAsync(m => m.Id == delivery.ItemId);

            var history = new History
            {
                ActionDate = DateTime.Now,
                ActionType = "Delete",
                Item = item.Name,
                Qty = delivery.Qty,
                Tracking = delivery.Tracking,
                DeliveryDate = delivery.DeliveryDate,
                ShippingDate = delivery.ShippingDate
            };

            HttpContext.Session.SetObjectAsJson("action", history);
            //redirect to history controller to save a record of the action
            return RedirectToAction("receiver", "Histories");
            //------------------------------------------------------
        }

        private bool DeliveryExists(int id)
        {
            return _context.Delivery.Any(e => e.Id == id);
        }
    }
}

---------------------------------------------------------------------
history controller function

public async Task<IActionResult> receiver()
        {
            var lastAction = HttpContext.Session.GetObjectFromJson<History>("action");
            _context.Add(lastAction);
            await _context.SaveChangesAsync();
            return RedirectToAction("Index", "Deliveries");
        }

-----------------------------------------------------------------------
SessionExtensions.cs

using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ebay_track.Models
{
    public static class SessionExtensions
    {
        public static void SetObjectAsJson(this ISession session, string key, object value)
        {
            session.SetString(key, JsonConvert.SerializeObject(value));
        }

        public static T GetObjectFromJson<T>(this ISession session, string key)
        {
            var value = session.GetString(key);

            return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value);
        }
    }
}


-----------------------------------------------------------------------
deliveries view index.cshtml

@model IEnumerable<ebay_track.Models.Delivery>

@{
    ViewData["Title"] = "Index";
}

<script src="~/lib/jquery/dist/jquery.js"></script>
<script type="text/javascript">

    var item_list = [];
    var delivery_list = [];

    $(document).ready(function () {

    $("#item_select").append(new Option("All",""));

    @foreach(var item in ViewBag.ItemId)
{
    <text>
        item_list.push(new item_class('@item.Id', '@item.Name'));
        </text>
}

          @foreach(var delivery in Model)
{
    <text>
        delivery_list.push(new delivery_class('@delivery.Id','@delivery.ShippingDate', '@delivery.DeliveryDate', '@delivery.Item.Name', '@delivery.Qty', '@delivery.Tracking', '@delivery.Arrived','@delivery.CaseClosed'));
        </text>
}

item_list.sort(function (a, b) {

    var aName = a.name.toLowerCase();
    var bName = b.name.toLowerCase();
    return ((aName < bName) ? -1 : ((aName > bName) ? 1 : 0));
        });

$.each(item_list, function () {

    $("#item_select").append(new Option(this.name, this.id));
    });

    sort_by_date();
     });

function item_class(id, name) {
    this.id = id;
    this.name = name;
    }

    function delivery_class(id, shippingDate, deliveryDate, item, qty, tracking, arrived, caseClosed) {
        this.id = id;
        this.shippingDate = shippingDate.replace("12:00:00 AM", "");
        this.deliveryDate = deliveryDate.replace("12:00:00 AM", "");
        this.item = item;
        this.qty = qty;
        this.tracking = tracking;
        this.arrived = arrived;
        this.caseClosed = caseClosed;
    }

    function check() {

        $("#error").text("");

        var begin = $("#calendar_begin").val();
        var end = $("#calendar_end").val();

        if (begin == null || end == null) { return true; }

        var begin_value = parseInt(begin.replace(/-/g, ''));
        var end_value = parseInt( end.replace(/-/g, ''));

        if (begin_value > end_value) {

            $("#error").text("begin date " + begin + " " + begin_value + " is later than end date " + end_value);
            return false;
        }

        return true;
    }

    function sort_by_item() {

        $("#display_table tbody > tr").remove();

        delivery_list.sort(function (a, b) {

            var aName = a.item.toLowerCase();
            var bName = b.item.toLowerCase();
            return ((aName < bName) ? -1 : ((aName > bName) ? 1 : 0));
        });

        populate_table();

    }

    function sort_by_date() {

        $("#display_table tbody > tr").remove();

        delivery_list.sort(function (a, b) {

            var aName = new Date( a.shippingDate);
            var bName = new Date( b.shippingDate);
            return ((aName.getTime() < bName.getTime()) ? -1 : ((aName.getTime() > bName.getTime()) ? 1 : 0));
        });

        populate_table();
    }

    function sort_by_date2() {

        $("#display_table tbody > tr").remove();

       delivery_list.sort(function (a, b) {

            var aName = new Date(a.deliveryDate);
            var bName = new Date(b.deliveryDate);
            return ((aName.getTime() < bName.getTime()) ? -1 : ((aName.getTime() > bName.getTime()) ? 1 : 0));
        });

        populate_table();
    }

    function populate_table() {

        $.each(delivery_list, function () {

            $("#display_table tbody ").append(
                "<tr><td>" + this.shippingDate +
                "</td><td>" + this.deliveryDate +
                "</td><td>" + this.item +
                "</td><td>" + this.qty +
                "</td><td>" + this.tracking +
                "</td><td>" + this.arrived +
                "</td><td>" + this.caseClosed +
                "</td><td>" + "<a href= '" + window.location.href +"/Deliveries/Edit?id=" + this.id + "'>edit</a>" +
                "</td><td>" + "<a href= '" + window.location.href +"/Deliveries/Details?id=" + this.id + "'>detail</a>" +
                "</td><td>" + "<a href= '" + window.location.href +"/Deliveries/Delete?id=" + this.id + "'>delete</a>" +
                "</td></tr>");
        });
    }
</script>

<h2>Index</h2>

<p style="color:red" id="error"></p>


<form method="post" onsubmit="return check()">
    <div class="row">
        <div class="col-md-6">
            <label>shipping date begin: @ViewBag.c_begin</label><br />
            <input type="date" class="form-control" name="begin" id="calendar_begin" />
        </div>
        <div class="col-md-6">
            <label>shipping date end: @ViewBag.c_end</label><br />
            <input type="date" class="form-control" name="end" id="calendar_end" />
        </div>
    </div>
    <hr />
    <div class="row">
        <div class="col-md-4">
            <label>delivery status</label>
            <select name="delivery" class="form-control">
                <option value="N" selected>undelivered</option>
                <option value="Y">arrived</option>
                <option value="B">both</option>
            </select>
        </div>
        <div class="col-md-4">
            <label>case closed</label>
            <select name="case_closed" class="form-control">
                <option value="N" selected>no case or case is open</option>
                <option value="Y">closed by ebay</option>
                <option value="B">both</option>
            </select>
        </div>
        <div class="col-md-4">
            <label class="control-label">Item</label>
            <select name="item_select" id="item_select" class="form-control"></select>
        </div>
    </div>
    <hr />
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <input type="submit" value="search" class="form-control btn btn-primary" />
        </div>
    </div>
</form>

<hr/>

<p>
    <a asp-action="Create">Create New</a>
</p>
<table class="table table-hover" id="display_table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.ShippingDate)
                <button type="button" class="btn btn-primary" onclick="sort_by_date()">
                    <span class="glyphicon glyphicon-sort-by-attributes"></span>
                </button>
            </th>
            <th>
                @Html.DisplayNameFor(model => model.DeliveryDate)
                <button type="button" class="btn btn-primary" onclick="sort_by_date2()">
                    <span class="glyphicon glyphicon-sort-by-attributes"></span>
                </button>
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Item)
                <button type="button" class="btn btn-primary" onclick="sort_by_item()">
                    <span class="glyphicon glyphicon-sort-by-attributes"></span>
                </button>
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Qty)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Tracking)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Arrived)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.CaseClosed)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
     
    </tbody>
</table>


---------------------------------------------------------------
delivery view create.cshtml

@model ebay_track.Models.Delivery

@{
    ViewData["Title"] = "Create";
}

<script src="~/lib/jquery/dist/jquery.js"></script>
<script type="text/javascript">

    var item_list = [];

$(document).ready(function () {
    @foreach(var item in ViewBag.ItemId)
{
    <text>
        item_list.push(new item_class('@item.Id', '@item.Name'));
        </text>
}

item_list.sort(function (a, b) {

    var aName = a.name.toLowerCase();
    var bName = b.name.toLowerCase();
    return ((aName < bName) ? -1 : ((aName > bName) ? 1 : 0));
});

$.each(item_list, function () {

    $("#item_select").append(new Option(this.name, this.id));
});
     });

function item_class(id, name) {
    this.id = id;
    this.name = name;
}

</script>

<h2>Create</h2>

<h4>Delivery</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">

                <label asp-for="ItemId" class="control-label">Item</label>
                <select asp-for="ItemId" id="item_select" class="form-control"></select>
            </div>
            <div class="form-group">
                <label asp-for="ShippingDate" class="control-label"></label>
                <input asp-for="ShippingDate" type="date" class="form-control" />
                <span asp-validation-for="ShippingDate" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="DeliveryDate" class="control-label"></label>
                <input asp-for="DeliveryDate" type="date" class="form-control" required="required"/>
                <span asp-validation-for="DeliveryDate" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Qty" class="control-label"></label>
                <input asp-for="Qty" type="number" class="form-control" required="required" />
                <span asp-validation-for="Qty" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Tracking" class="control-label"></label>
                <input asp-for="Tracking" class="form-control" />
                <span asp-validation-for="Tracking" class="text-danger"></span>
            </div>
            <div class="form-group">

                <label asp-for="Arrived" class="control-label"></label>
                <select name="Arrived" class="form-control">
                    <option value="N" selected>undelivered</option>
                    <option value="Y">arrived</option>
                </select>
            </div>
            <div class="form-group">
                <label asp-for="CaseClosed" class="control-label"></label>
                <select name="CaseClosed" class="form-control">
                    <option value="" selected>no case or case is open</option>
                    <option value="Y">closed by ebay</option>
                </select>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

---------------------------------------------------------------------
delivery view Edit.cshtml

@model ebay_track.Models.Delivery

@{
    ViewData["Title"] = "Edit";
}

<script src="~/lib/jquery/dist/jquery.js"></script>
<script type="text/javascript">

    $(document).ready(function () {

        $('#arrived_tag').append(
            $('<option>', { value: 'N', text: 'undelivered' }),
            $('<option>', { value: 'Y', text: 'arrived' })
        );

        if ('@Model.Arrived' == 'Y') {
            $('#arrived_tag option[value=Y]').prop('selected', true);
        }
        else {
            $('#arrived_tag option[value=N]').prop('selected', true);
        }

        $('#case_closed_tag').append(
            $('<option>', { value: '', text: 'no case or case is open' }),
            $('<option>', { value: 'Y', text: 'closed by ebay' })
        );

        if ('@Model.CaseClosed' == 'Y') {
            $('#case_closed_tag option[value=Y]').prop('selected', true);
        }
        
    });
</script>

<h2>Edit</h2>

<h4>Delivery</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Edit">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <input type="hidden" asp-for="Id" />
            <div class="form-group">
                <label asp-for="ItemId" class="control-label"></label>
                <select asp-for="ItemId" class="form-control" asp-items="ViewBag.ItemId"></select>
                <span asp-validation-for="ItemId" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="ShippingDate" class="control-label"></label>
                <input asp-for="ShippingDate" type="date" class="form-control" />
                <span asp-validation-for="ShippingDate" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="DeliveryDate" class="control-label"></label>
                <input asp-for="DeliveryDate" type="date" class="form-control" required="required"/>
                <span asp-validation-for="DeliveryDate" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Qty" class="control-label"></label>
                <input asp-for="Qty" type="number" class="form-control" required="required" />
                <span asp-validation-for="Qty" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Tracking" class="control-label"></label>
                <input asp-for="Tracking" class="form-control" />
                <span asp-validation-for="Tracking" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Arrived" class="control-label"></label>
                <select name="Arrived" id="arrived_tag" class="form-control"></select>
            </div>
            <div class="form-group">
                <label asp-for="CaseClosed" class="control-label"></label>
                <select name="CaseClosed" id="case_closed_tag" class="form-control"></select>
            </div>
            <div class="form-group">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

----------------------------------------------------------------------------------
start up.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ebay_track.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace ebay_track
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            services.AddDistributedMemoryCache(); // Adds a default in-memory implementation of IDistributedCache
            services.AddSession();

            var cs = Configuration.GetConnectionString("ebayConnection");
            services.AddDbContext<ebayContext>(options => options.UseSqlServer(cs));
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {


            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseBrowserLink();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            // IMPORTANT: This session call MUST go before UseMvc()
            app.UseSession();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Deliveries}/{action=Index}/{id?}");
            });
        }
    }
}

----------------------------------------------------------------------------------
sql querry






create table item
(
id int IDENTITY(1,1) PRIMARY KEY,
name char(50) not null
)

create table delivery
(
id int IDENTITY(1,1) PRIMARY KEY,
item_id int foreign key references item(id) not null,
date datetime not null,
tracking char(50),
arrived char(1) check (arrived in ('Y','N')) not null
)

select * from item;

select d.date, i.name, d.tracking, d.arrived from delivery as d
inner join item as i on d.item_id = i.id
where d.arrived = 'Y'
order by d.date;


reference:
https://www.codeproject.com/Tips/1158082/Date-Time-Picker-in-ASP-NET-Core-using-Jquery-Plug
https://msdn.microsoft.com/fr-fr/library/system.datetime.compare(v=vs.110).aspx
https://www.codeproject.com/Articles/758458/Passing-Data-View-to-Controller-Controller-to-View
https://www.w3schools.com/jsref/jsref_replace.asp
https://stackoverflow.com/questions/20510023/mvc-redirect-to-view-from-jquery-with-parameters
https://stackoverflow.com/questions/740195/adding-options-to-a-select-using-jquery
https://stackoverflow.com/questions/13343566/set-select-option-selected-by-value
https://stackoverflow.com/questions/2656576/select-top-5-in-entity-framework

sessions:
https://chuanshuoge2.blogspot.ca/2018/01/sessions-asp-core.html

No comments:

Post a Comment