public async Task<LogSim> Add(LogSim item)
        {
            var gps = await GpsExist(item.GpsId);
            if (gps.SimId != item.SimAtFirst)
                throw new ArgumentException("Invalid SimAtFirst", "SimAtFirst");

            var oldSim = await SimExist(item.SimAtFirst);
            var newSim = await SimExist(item.SimNew);
            var createBy = await EmpExist(item.CreateBy);

            oldSim.Status = 1;

            if (newSim.Status != 2) newSim.Status = 2;
            else throw new ArgumentException("SimNew.Status is currently Active", "SimNew");

            gps.SimId = newSim.Id;

            var newLogSim = new LogSim
            {
                CreateBy = createBy,
                CreateDate = DateTime.UtcNow,
                GpsId = gps.Id,
                SimAtFirst = oldSim.Id,
                SimNew = newSim.Id
            };

            _db.Entry(oldSim).State = EntityState.Modified;
            _db.Entry(newSim).State = EntityState.Modified;
            _db.Entry(gps).State = EntityState.Modified;
            newLogSim = _db.LogSims.Add(newLogSim);
            try
            {
                await _db.SaveChangesAsync();
                return newLogSim;
            }
            catch (DbUpdateConcurrencyException exception)
            {
                throw new DbUpdateConcurrencyException(exception.Message);
            }
        }
        public async Task<bool> Update(Gps item)
        {
            var product = await IdExist(item.Id);

            switch (item.State)
            {
                case 2: //stock (Manu)
                    if (item.StockBy == null)
                        throw new ArgumentNullException("StockBy", "StockBy is Required for this state");
                    product.StockBy = await EmpExist(item.StockBy.Value);
                    product.StockDate = DateTime.UtcNow;
                    product.State = 2;
                    break;
                case 3: //QC (Qc)
                    if (item.QcBy == null)
                        throw new ArgumentNullException("QcBy", "QcBy is Required for this state");

                    if (item.SimId == null)
                        throw new ArgumentNullException("SimId", "SimId is Required for this state");

                    if (item.OrderId == null)
                        throw new ArgumentNullException("OrderId", "OrderId is Required for this state");

                    var by = await EmpExist(item.QcBy.Value);
                    var d = DateTime.UtcNow;
                    var newSim = await SimExist(item.SimId.Value);

                    if (product.SimId != null) //changeSim
                    {
                        var log = new LogSim
                        {
                            CreateBy = by,
                            CreateDate = d,
                            GpsId = product.Id,
                            SimAtFirst = product.SimId.Value,
                            SimNew = newSim
                        };
                        _db.LogSims.Add(log);
                        try
                        {
                            await _db.SaveChangesAsync();
                        }
                        catch (DbUpdateConcurrencyException exception)
                        {
                            throw new DbUpdateConcurrencyException(exception.Message);
                        }
                    }

                    product.SimId = newSim;
                    product.QcBy = by;
                    product.QcDate = d;
                    product.State = 3;
                    product.OrderId = item.OrderId.Value;

                    //todo: check all product.state = 3 in this order
        //          //todo: update order status = 4 (QCcomplete)

                    break;
                /*case 4: //Install (installation) ... update in order process
                    if (item.InstallBy == null)
                        throw new ArgumentNullException("InstallBy", "InstallBy is Required for this state");
                    product.InstallBy = await EmpExist(item.InstallBy.Value);
                    product.State = 4;
                    break;*/
                case 5: //Bad (Qc)
                    if (item.BadBy == null)
                        throw new ArgumentNullException("BadBy", "BadBy is Required for this state");
                    product.BadBy = await EmpExist(item.BadBy.Value);
                    product.BadDate = DateTime.UtcNow;
                    product.BadComment = item.BadComment;
                    product.State = 5;
                    break;
                case 6: //Unuseable (Manu)
                    if (item.UnuseableBy == null)
                        throw new ArgumentNullException("UnuseableBy", "UnuseableBy is Required for this state");
                    product.UnuseableBy = await EmpExist(item.UnuseableBy.Value);
                    product.UnuseableDate = DateTime.UtcNow;
                    product.UnuseableComment = item.UnuseableComment;
                    product.State = 6;
                    break;
                case 8: //Complete (installation)
                    if (item.OrderId == null)
                        throw new ArgumentNullException("OrderId", "OrderId is Required for this state");

                    //update universe.Display = 3
                    var uni = await _db.Universes.FirstOrDefaultAsync(u => u.GpsProductId == item.Id);
                    if (uni == null) throw new ArgumentNullException("Universes", "ProductId is NotFound in Universe");
                    uni.DisplayStatus = 3;
                    _db.Entry(uni).State = EntityState.Modified;

                    //check this product == SolvedProduct in FixOrder
                    var fix =
                        await _db.FixOrders.Where(f => f.SolvedProduct == item.Id)
                            .OrderByDescending(f => f.CreateDate).FirstOrDefaultAsync();
                    //if found -> update FixOrder status = 6 (Complete) and check fixorder of fixorder of ... of order and update all order status
                    if (fix != null)
                    {
                        fix.State = 6;
                        var loop = fix.FromFixOrderId.HasValue;
                        if (loop)
                        {
                            var fromFix = fix.FromFixOrder;
                            while (loop)
                            {
                                fromFix.State = 6;
                                _db.Entry(fromFix).State = EntityState.Modified;

                                if (fromFix.FromFixOrderId.HasValue)
                                    fromFix = fromFix.FromFixOrder;
                                else
                                {
                                    //call fn() check all product in order
                                    await updateOrder(item.OrderId.Value, item.Id);
                                    loop = false;
                                }
                            }
                        }
                        else
                        {
                            //call fn() check all product in order
                            await updateOrder(item.OrderId.Value, item.Id);
                        }
                    }
                    else
                    {
                        //update logFee startDate&expireDate
                        var fee =
                            await _db.LogFees.OrderByDescending(f => f.CreateDate)
                                .FirstOrDefaultAsync(f => f.GpsId == item.Id);
                        fee.StartDate = DateTime.UtcNow;
                        fee.ExpireDate = DateTime.UtcNow.AddYears(1);
                        _db.Entry(fee).State = EntityState.Modified;

                        //call fn() check all product in order
                        await updateOrder(item.OrderId.Value, item.Id);
                    }

                    product.InstallDate = DateTime.UtcNow;
                    product.State = 8;
                    break;
                case 10: //Fixed (Manu,Qc)
                    if (item.StockBy == null)
                        throw new ArgumentNullException("StockBy", "StockBy is Required for this state");
                    product.StockBy = await EmpExist(item.StockBy.Value);
                    product.StockDate = DateTime.UtcNow;
                    product.State = 2;
                    break;
                    /*case 11://Problem state ... create when FixOrder created
                    if (item.ProblemBy == null)
                        throw new ArgumentNullException("ProblemBy", "ProblemBy is Required for this state");
                    product.ProblemBy = await EmpExist(item.ProblemBy.Value);
                    product.ProblemDate = DateTime.UtcNow;
                    product.ProblemComment = item.ProblemComment;
                    product.State = 11;
                    break;*/
                default:
                    throw new ArgumentException("Incorrect State", "State");
            }

            _db.Entry(product).State = EntityState.Modified;
            try
            {
                await _db.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException exception)
            {
                throw new DbUpdateConcurrencyException(exception.Message);
            }

            return true;
        }