diff --git a/AyaNovaQBI/Map.cs b/AyaNovaQBI/Map.cs index 53d3282..78df197 100644 --- a/AyaNovaQBI/Map.cs +++ b/AyaNovaQBI/Map.cs @@ -953,7 +953,7 @@ namespace AyaNovaQBI - private void updateSelectedItemsToolStripMenuItem_Click(object sender, EventArgs e) + private async void updateSelectedItemsToolStripMenuItem_Click(object sender, EventArgs e) { //Parts in v7 default update would do price / cost both ways in addition to the part description and other fields // however the user could go to map and select to *only* update the prices in AyaNova from QB but not the other fields @@ -997,7 +997,118 @@ namespace AyaNovaQBI if (s.ShowDialog() == DialogResult.Cancel) return; - MessageBox.Show("STUB: UPDATE SELECTED ITEMS"); + bool PricesOnly = s.PriceOnly; + s.Dispose(); + + + + + + bool SaveIntegration = false; + + if (IsAyaGrid) + { + #region AyaGrid so UPDATE AYANOVA FROM QB + switch (_Type) + { + + case AyaType.Customer: + await util.PopulateQBClientCacheAsync(); + break; + case AyaType.Vendor: + await util.PopulateQBVendorCacheAsync(); + break; + case AyaType.Part: + await util.PopulateQBItemCacheAsync(); + break; + } + + foreach (DataGridViewRow r in gridAya.SelectedRows) + { + string AyaName = r.Cells[0].Value.ToString(); + long AyaId = (long)r.Cells[1].Value; + + //only linked items can be updated + IntegrationItem m = util.QBIntegration.Items.FirstOrDefault(z => z.ObjectId == AyaId && z.AType == _Type); + if (m != null) + { + switch (_Type) + { + + case AyaType.Customer: + sType = "Customers"; + break; + case AyaType.Vendor: + sType = "Vendors"; + break; + case AyaType.Part: + await util.RefreshAyaNovaPartFromQB(AyaId, PricesOnly); + break; + } + SaveIntegration = true; + + + } + + } + + + + #endregion AyaGrid + } + else + { + #region QB GRID + //################ + //QB GRID + // + + if (gridQB.SelectedRows.Count > 1) + { + MessageBox.Show("You can not link more than one QuickBooks\r\n" + + "object to a single AyaNova object", "Not supported", MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + } + + var QBItemName = gridQB.SelectedRows[0].Cells[0].Value.ToString(); + var QBItemId = gridQB.SelectedRows[0].Cells[1].Value.ToString(); + + MapSelectAyaNovaItem s = new MapSelectAyaNovaItem(); + s.Items = _aya; + if (s.ShowDialog() == DialogResult.Cancel) + return; + + var AyaId = s.SelectedItemId; + s.Dispose(); + + //This way is a one to one mapping so only one iteration and two potential things to do, add or change link + //Is it already present? + IntegrationItem m = util.QBIntegration.Items.FirstOrDefault(z => z.ObjectId == AyaId && z.AType == _Type); + if (m != null) + { + m.IntegrationItemId = QBItemId; + m.IntegrationItemName = QBItemName; + m.LastSync = System.DateTime.Now; + SaveIntegration = true; + } + else + { + //not already present, so add it + m = new IntegrationItem { AType = _Type, IntegrationItemName = QBItemName, IntegrationItemId = QBItemId, LastSync = System.DateTime.Now, ObjectId = AyaId }; + util.QBIntegration.Items.Add(m); + SaveIntegration = true; + } + + #endregion qb grid + } + + if (SaveIntegration) + { + await util.SaveIntegrationObject(); + Initialize(); + } + + }//eof }//eoc diff --git a/AyaNovaQBI/util.cs b/AyaNovaQBI/util.cs index a54478e..7c24c6f 100644 --- a/AyaNovaQBI/util.cs +++ b/AyaNovaQBI/util.cs @@ -714,7 +714,7 @@ namespace AyaNovaQBI if (!present) BadIntegrationItemIds.Add(new NameIdItem { Name = m.IntegrationItemName, Id = m.Id }); - //dtTemp.Rows.Add(new object[] { m.Id, m.AType.ToString() + ": " + m.IntegrationItemName }); + //dtTemp.Rows.Add(new object[] { m.Id, m.AType.ToString() + ": " + m.IntegrationItemName }); } @@ -758,7 +758,7 @@ namespace AyaNovaQBI await IntegrationLog("PFC: Some integration maps do not match qb database objects"); //foreach (DataRow row in dtTemp.Rows) - foreach(var bi in BadIntegrationItemIds) + foreach (var bi in BadIntegrationItemIds) { DialogResult dr = MessageBox.Show("Linked object: " + bi.Name + "\r\n" + @@ -769,7 +769,7 @@ namespace AyaNovaQBI { //var mapId = (long)row["MAPID"]; var removeItem = QBIntegration.Items.Where(z => z.Id == bi.Id).First(); - //TODO: this needs to be a reverse for next loop + //TODO: this needs to be a reverse for next loop bool bResult = QBIntegration.Items.Remove(removeItem); if (!bResult) MessageBox.Show("Error attempting to remove unmapped item; it could not be found in the map list"); @@ -1677,7 +1677,7 @@ namespace AyaNovaQBI await PopulateQBClientCacheAsync(); w.Step = "Items"; - await PopulateQBItemCache(); + await PopulateQBItemCacheAsync(); if (!(QVersion < 3))//qbXML 3.0 or higher (QB 2004 any country or newer) { @@ -1750,7 +1750,7 @@ namespace AyaNovaQBI /// Populate the cached qb data /// billable /// - private async static Task PopulateQBItemCache() + internal async static Task PopulateQBItemCacheAsync() { if (_dtQBItems == null) { @@ -2531,7 +2531,7 @@ namespace AyaNovaQBI /// Populate the cached qb data /// of customers / clients /// - private static async Task PopulateQBClientCacheAsync() + internal static async Task PopulateQBClientCacheAsync() { if (_dtQBClients == null) { @@ -2761,7 +2761,7 @@ namespace AyaNovaQBI /// Populate the cached qb data /// of Vendors /// - private static async Task PopulateQBVendorCacheAsync() + internal static async Task PopulateQBVendorCacheAsync() { if (_dtQBVendors == null) { @@ -4058,26 +4058,29 @@ namespace AyaNovaQBI - public static async Task RefreshAyaNovaPartFromQB(List objectIDList) - { - await PopulateQBItemCache(); - foreach (long id in objectIDList) - { - try - { - var r = await GetAsync($"part/{id}"); - var c = r.ObjectResponse["data"].ToObject(); - await RefreshAyaNovaPartFromQB(c); - r = await PutAsync($"part", Newtonsoft.Json.JsonConvert.SerializeObject(c)); - } - catch { }; - } + //public static async Task RefreshAyaNovaPartFromQB(List objectIDList) + //{ + // await PopulateQBItemCache(); + // foreach (long id in objectIDList) + // { + // try + // { + // var r = await GetAsync($"part/{id}"); + // var c = r.ObjectResponse["data"].ToObject(); + // await RefreshAyaNovaPartFromQB(c); + // r = await PutAsync($"part", Newtonsoft.Json.JsonConvert.SerializeObject(c)); + // } + // catch { }; + // } - } + //} - public static async Task RefreshAyaNovaPartFromQB(Part c) + public static async Task RefreshAyaNovaPartFromQB(long PartId, bool pricesOnly = false) { - await PopulateQBItemCache(); + var r = await GetAsync($"part/{PartId}"); + var c = r.ObjectResponse["data"].ToObject(); + if (c == null) return; + IntegrationItem im = util.QBIntegration.Items.FirstOrDefault(z => z.ObjectId == c.Id && z.AType == AyaType.Part); if (im == null) return;//this part is not linked @@ -4925,7 +4928,7 @@ namespace AyaNovaQBI //Link var m = new IntegrationItem { AType = AyaType.Vendor, IntegrationItemName = sName, IntegrationItemId = sNewCustID, LastSync = DateTime.Now, ObjectId = c.Id }; QBIntegration.Items.Add(m); - + } catch (Exception ex) { @@ -4972,8 +4975,10 @@ namespace AyaNovaQBI /// Refresh the indicated AyaNova part /// to it's linked QuickBooks item record /// - public static async Task RefreshQBPartFromAyaNova(Part c) + public static async Task RefreshQBPartFromAyaNova(long PartId, bool pricesOnly = false) { + var r = await GetAsync($"part/{PartId}"); + var c = r.ObjectResponse["data"].ToObject(); IntegrationItem im = QBIntegration.Items.FirstOrDefault(z => z.ObjectId == c.Id && z.AType == AyaType.Part); if (im == null) return;//this part is not linked @@ -5018,48 +5023,29 @@ namespace AyaNovaQBI //Get and set edit sequence string sEditSequence = await GetInventoryItemEditSequenceAsync(im.IntegrationItemId); + if (!pricesOnly) + { + dr["FullName"] = sName; + dr["Type"] = qbitemtype.Inventory; + dr["VendorID"] = c.WholeSalerId.ToString(); + dr["SalesDesc"] = sDescription; - //create a new row to add to the client cache datatable - - dr["FullName"] = sName; - dr["Type"] = qbitemtype.Inventory; + //Set the qb item values + ca.Name.SetValue(sName); + ca.SalesDesc.SetValue(sDescription); + ca.PurchaseDesc.SetValue(sDescription); + } dr["Price"] = c.Retail; dr["Cost"] = c.Cost; - dr["SalesDesc"] = sDescription; - //dr["ReorderPoint"] = 0; dr["Modified"] = DateTime.Now; - dr["VendorID"] = c.WholeSalerId.ToString(); - - //Set the QB item identification and edit sequence - ca.ListID.SetValue(im.IntegrationItemId); - ca.EditSequence.SetValue(sEditSequence); - - - //------------------------ - //Set the qb item values - ca.Name.SetValue(sName); - //ca.IncomeAccountRef.ListID.SetValue(QDat.QBInventoryIncomeAccountReference); - // ca.COGSAccountRef.ListID.SetValue(QDat.QBInventoryCOGSAccountRef); - // ca.AssetAccountRef.ListID.SetValue(QDat.QBInventoryAssetAccountRef); - ca.SalesDesc.SetValue(sDescription); - ca.PurchaseDesc.SetValue(sDescription); ca.SalesPrice.SetValue((double)c.Retail); ca.PurchaseCost.SetValue((double)c.Cost); - //Inventory values cannot be updated this way - //they require generating a PO or making an invoice so - //the refresh command won't support inventory values - - //if (AyaBizUtils.GlobalSettings.UseInventory) - //{ - // PartInventoryValuesFetcher pbw = PartInventoryValuesFetcher.GetItem(c.ID); - // ca.QuantityOnHand.SetValue((double)pbw.QuantityOnHand); - // ca.ReorderPoint.SetValue((double)pbw.MinStockLevel); - //} - //------------------------ - + //Set the QB item identification and edit sequence + ca.ListID.SetValue(im.IntegrationItemId); + ca.EditSequence.SetValue(sEditSequence); //This is intended to be called after already sucessfully connected //to get version info so no special safety checks here @@ -5088,8 +5074,6 @@ namespace AyaNovaQBI } - // IItemInventoryRet cr = response.Detail as IItemInventoryRet; - // string sNewID = cr.ListID.GetValue(); requestSet.ClearRequests(); //---------------- @@ -5098,23 +5082,8 @@ namespace AyaNovaQBI sessionManager.EndSession(); booSessionBegun = false; sessionManager.CloseConnection(); - - //catch the new ID for the QB Item - // dr["ID"] = sNewID; - //add the new row for the newly imported object - // _dtQBItems.Rows.Add(dr); - - //Link - //// IntegrationMap m = QBI.Maps.Add(QBI); - ////m.Name = sName; - //// m.RootObjectID = c.ID; - //// m.RootObjectType = RootObjectTypes.Part; - //im.LastSync = DateTime.Now; - ////m.ForeignID = sNewID; - //QBI = (Integration)QBI.Save(); - //v8NOTE: name was not set here as you can see above, maybe on purpose? leaving as is, not sure why but safest option to copy what was done before im.LastSync = DateTime.Now; - await SaveIntegrationObject(); + } catch (Exception ex) { @@ -5128,7 +5097,7 @@ namespace AyaNovaQBI //and it is if it's got an inner exception of any kind if (ex.InnerException != null) ex = ex.InnerException; CopyableMessageBox cp = new CopyableMessageBox( - "RefreshQBPartFromAyaNova: QuickBooks won't allow import of " + sName + "\r\n" + + "RefreshQBPartFromAyaNova: QuickBooks won't allow update of " + sName + "\r\n" + "Due to the following error:\r\n" + ex.Message); cp.ShowDialog(); @@ -5318,7 +5287,7 @@ namespace AyaNovaQBI //Link var m = new IntegrationItem { AType = AyaType.Part, IntegrationItemName = sName, IntegrationItemId = sNewID, LastSync = DateTime.Now, ObjectId = c.Id }; QBIntegration.Items.Add(m); - + } catch (Exception ex) { @@ -5470,7 +5439,7 @@ namespace AyaNovaQBI //Link var m = new IntegrationItem { AType = AyaType.ServiceRate, IntegrationItemName = sName, IntegrationItemId = sNewID, LastSync = DateTime.Now, ObjectId = c.Id }; QBIntegration.Items.Add(m); - + } catch (Exception ex) { @@ -5620,7 +5589,7 @@ namespace AyaNovaQBI //Link var m = new IntegrationItem { AType = AyaType.TravelRate, IntegrationItemName = sName, IntegrationItemId = sNewID, LastSync = DateTime.Now, ObjectId = c.Id }; QBIntegration.Items.Add(m); - + } catch (Exception ex) {