From 28897c96ea2e22c901f86ba708213f896e609a51 Mon Sep 17 00:00:00 2001
From: Tsanie <tsorgy@gmail.com>
Date: Fri, 11 Mar 2022 17:16:49 +0800
Subject: [PATCH] issue fix

---
 Billing.Shared/Helper.cs                     |  7 +-
 Billing.Shared/Models/IIdItem.cs             |  2 +-
 Billing.Shared/Store/StoreHelper.cs          | 67 ++++++++++----------
 Billing.Shared/Views/AccountPage.xaml.cs     | 13 +---
 Billing.Shared/Views/AddAccountPage.xaml.cs  |  1 -
 Billing.Shared/Views/AddBillPage.xaml.cs     |  1 -
 Billing.Shared/Views/AddCategoryPage.xaml.cs |  1 -
 Billing.Shared/Views/BillPage.xaml           |  1 +
 Billing.Shared/Views/BillPage.xaml.cs        | 34 ++++++----
 Billing.Shared/Views/CategoryPage.xaml.cs    | 12 +---
 Billing.Shared/Views/RankPage.xaml           |  1 +
 11 files changed, 66 insertions(+), 74 deletions(-)

diff --git a/Billing.Shared/Helper.cs b/Billing.Shared/Helper.cs
index f0a5100..b4fd510 100644
--- a/Billing.Shared/Helper.cs
+++ b/Billing.Shared/Helper.cs
@@ -1,4 +1,5 @@
 using Billing.Models;
+using Billing.Themes;
 using Billing.UI;
 using Billing.Views;
 using System;
@@ -83,9 +84,13 @@ namespace Billing
 
         public static UIBill WrapBill(Bill b)
         {
+            var category = App.Categories.FirstOrDefault(c => c.Id == b.CategoryId);
             return new UIBill(b)
             {
-                Icon = App.Categories.FirstOrDefault(c => c.Id == b.CategoryId)?.Icon ?? Definition.DefaultIcon,
+                Icon = category?.Icon ?? Definition.DefaultIcon,
+                TintColor = category?.TintColor.IsTransparent() == false ?
+                    category.TintColor.ToColor() :
+                    BaseTheme.CurrentPrimaryColor,
                 Name = b.Name,
                 DateCreation = b.CreateTime,
                 Amount = b.Amount,
diff --git a/Billing.Shared/Models/IIdItem.cs b/Billing.Shared/Models/IIdItem.cs
index 1b1b124..c6f2f1d 100644
--- a/Billing.Shared/Models/IIdItem.cs
+++ b/Billing.Shared/Models/IIdItem.cs
@@ -2,6 +2,6 @@
 {
     public interface IIdItem
     {
-        public int Id { get; }
+        public int Id { get; set; }
     }
 }
diff --git a/Billing.Shared/Store/StoreHelper.cs b/Billing.Shared/Store/StoreHelper.cs
index 86454ed..e799346 100644
--- a/Billing.Shared/Store/StoreHelper.cs
+++ b/Billing.Shared/Store/StoreHelper.cs
@@ -1,7 +1,6 @@
 using System;
 using System.Collections.Generic;
 using System.IO;
-using System.Linq;
 using System.Threading.Tasks;
 using Billing.Models;
 using SQLite;
@@ -31,35 +30,35 @@ namespace Billing.Store
                 await database.InsertAllAsync(new List<Category>
                 {
                     // sample categories
-                    new() { Id = 1, Name = Resource.Clothing, Icon = "clothes" },
-                    new() { Id = 2, Name = Resource.Food, Icon = "food" },
-                    new() { Id = 4, Name = Resource.Daily, Icon = "daily" },
-                    new() { Id = 5, Name = Resource.Trans, Icon = "trans" },
-                    new() { Id = 6, Name = Resource.Entertainment, Icon = "face" },
-                    new() { Id = 7, Name = Resource.Learn, Icon = "learn" },
-                    new() { Id = 8, Name = Resource.Medical, Icon = "medical" },
-                    new() { Id = 9, Name = Resource.OtherSpending, Icon = "plus" },
+                    new() { Name = Resource.Clothing, Icon = "clothes" },
+                    new() { Name = Resource.Food, Icon = "food" },
+                    new() { Name = Resource.Daily, Icon = "daily" },
+                    new() { Name = Resource.Trans, Icon = "trans" },
+                    new() { Name = Resource.Entertainment, Icon = "face" },
+                    new() { Name = Resource.Learn, Icon = "learn" },
+                    new() { Name = Resource.Medical, Icon = "medical" },
+                    new() { Name = Resource.OtherSpending, Icon = "plus" },
 
-                    new() { Id = 10, Type = CategoryType.Income, Name = Resource.Earnings, Icon = "#brand#btc" },
-                    new() { Id = 20, Type = CategoryType.Income, Name = Resource.OtherIncome, Icon = "plus" },
+                    new() { Type = CategoryType.Income, Name = Resource.Earnings, Icon = "#brand#btc" },
+                    new() { Type = CategoryType.Income, Name = Resource.OtherIncome, Icon = "plus" },
 
                     // sub-categories
-                    new() { Id = 100, ParentId = 1, Name = Resource.Jewellery, Icon = "gem" },
-                    new() { Id = 101, ParentId = 1, Name = Resource.Cosmetics, Icon = "makeup" },
-                    new() { Id = 102, ParentId = 2, Name = Resource.Brunch, Icon = "brunch" },
-                    new() { Id = 103, ParentId = 2, Name = Resource.Dinner, Icon = "dinner" },
-                    new() { Id = 104, ParentId = 2, Name = Resource.Drinks, Icon = "drink" },
-                    new() { Id = 105, ParentId = 2, Name = Resource.Fruit, Icon = "fruit" },
-                    new() { Id = 106, ParentId = 4, Name = Resource.UtilityBill, Icon = "bill" },
-                    new() { Id = 107, ParentId = 4, Name = Resource.PropertyFee, Icon = "fee" },
-                    new() { Id = 108, ParentId = 4, Name = Resource.Rent, Icon = "rent" },
-                    new() { Id = 109, ParentId = 4, Name = Resource.Maintenance, Icon = "maintenance" },
-                    new() { Id = 110, ParentId = 5, Name = Resource.LightRail, Icon = "rail" },
-                    new() { Id = 111, ParentId = 5, Name = Resource.Taxi, Icon = "taxi" },
-                    new() { Id = 112, ParentId = 6, Name = Resource.Fitness, Icon = "fitness" },
-                    new() { Id = 113, ParentId = 6, Name = Resource.Party, Icon = "party" },
-                    new() { Id = 200, ParentId = 10, Type = CategoryType.Income, Name = Resource.Salary, Icon = "#brand#buffer" },
-                    new() { Id = 201, ParentId = 10, Type = CategoryType.Income, Name = Resource.Bonus, Icon = "dollar" },
+                    new() { ParentId = 1, Name = Resource.Jewellery, Icon = "gem" },
+                    new() { ParentId = 1, Name = Resource.Cosmetics, Icon = "makeup" },
+                    new() { ParentId = 2, Name = Resource.Brunch, Icon = "brunch" },
+                    new() { ParentId = 2, Name = Resource.Dinner, Icon = "dinner" },
+                    new() { ParentId = 2, Name = Resource.Drinks, Icon = "drink" },
+                    new() { ParentId = 2, Name = Resource.Fruit, Icon = "fruit" },
+                    new() { ParentId = 3, Name = Resource.UtilityBill, Icon = "bill" },
+                    new() { ParentId = 3, Name = Resource.PropertyFee, Icon = "fee" },
+                    new() { ParentId = 3, Name = Resource.Rent, Icon = "rent" },
+                    new() { ParentId = 3, Name = Resource.Maintenance, Icon = "maintenance" },
+                    new() { ParentId = 4, Name = Resource.LightRail, Icon = "rail" },
+                    new() { ParentId = 4, Name = Resource.Taxi, Icon = "taxi" },
+                    new() { ParentId = 5, Name = Resource.Fitness, Icon = "fitness" },
+                    new() { ParentId = 5, Name = Resource.Party, Icon = "party" },
+                    new() { ParentId = 9, Type = CategoryType.Income, Name = Resource.Salary, Icon = "#brand#buffer" },
+                    new() { ParentId = 9, Type = CategoryType.Income, Name = Resource.Bonus, Icon = "dollar" },
                 });
             }
             return instance;
@@ -141,8 +140,8 @@ namespace Billing.Store
                 var source = new TaskCompletionSource<T>();
                 Task.Run(async () =>
                 {
-                    var list = await database.QueryAsync<T>($"SELECT * FROM [{typeof(T).Name}] WHERE [Id] = ?", id);
-                    source.SetResult(list.FirstOrDefault());
+                    var item = await database.FindWithQueryAsync<T>($"SELECT * FROM [{typeof(T).Name}] WHERE [Id] = ? LIMIT 1", id);
+                    source.SetResult(item);
                 });
                 return source.Task;
             }
@@ -172,20 +171,20 @@ namespace Billing.Store
         {
             try
             {
-                if (item.Id < 0)
+                if (item.Id > 0)
                 {
-                    return database.InsertAsync(item);
+                    return database.UpdateAsync(item);
                 }
                 else
                 {
-                    return database.UpdateAsync(item);
+                    return database.InsertAsync(item);
                 }
             }
             catch (Exception ex)
             {
                 Helper.Error("db.write", $"failed to insert/update item, table: {typeof(T)}, id: {item.Id}, item: {item}, error: {ex.Message}");
             }
-            return Task.FromResult(-1);
+            return Task.FromResult(0);
         }
 
         private Task<int> DeleteItemAsync<T>(T item) where T : IIdItem
@@ -198,7 +197,7 @@ namespace Billing.Store
             {
                 Helper.Error("db.delete", $"failed to delete item, table: {typeof(T)}, id: {item.Id}, item: {item}, error: {ex.Message}");
             }
-            return Task.FromResult(-1);
+            return Task.FromResult(0);
         }
 
         #endregion
diff --git a/Billing.Shared/Views/AccountPage.xaml.cs b/Billing.Shared/Views/AccountPage.xaml.cs
index 77a136d..db6df89 100644
--- a/Billing.Shared/Views/AccountPage.xaml.cs
+++ b/Billing.Shared/Views/AccountPage.xaml.cs
@@ -64,17 +64,6 @@ namespace Billing.Views
 
         private void AddToAccountGroup(Account account)
         {
-            int maxId;
-            if (accounts.Count > 0)
-            {
-                maxId = accounts.Max(g => g.Max(a => a.Id));
-            }
-            else
-            {
-                maxId = -1;
-            }
-            account.Id = maxId + 1;
-
             var group = accounts.FirstOrDefault(g => g.Key == account.Category);
             if (group == null)
             {
@@ -142,7 +131,7 @@ namespace Billing.Views
 
         private async void AccountChecked(object sender, AccountEventArgs e)
         {
-            var add = e.Account.Id < 0;
+            var add = e.Account.Id <= 0;
             if (add)
             {
                 App.Accounts.Add(e.Account);
diff --git a/Billing.Shared/Views/AddAccountPage.xaml.cs b/Billing.Shared/Views/AddAccountPage.xaml.cs
index 8b04253..4c6e7fb 100644
--- a/Billing.Shared/Views/AddAccountPage.xaml.cs
+++ b/Billing.Shared/Views/AddAccountPage.xaml.cs
@@ -105,7 +105,6 @@ namespace Billing.Views
                 {
                     Account = account ?? new Account
                     {
-                        Id = -1,
                         Name = AccountName,
                         Icon = AccountIcon,
                         Category = Category,
diff --git a/Billing.Shared/Views/AddBillPage.xaml.cs b/Billing.Shared/Views/AddBillPage.xaml.cs
index 5d47c21..f744115 100644
--- a/Billing.Shared/Views/AddBillPage.xaml.cs
+++ b/Billing.Shared/Views/AddBillPage.xaml.cs
@@ -162,7 +162,6 @@ namespace Billing.Views
                 }
                 BillChecked?.Invoke(this, bill ?? new Bill
                 {
-                    Id = -1,
                     Amount = amount,
                     Name = name,
                     CategoryId = categoryId,
diff --git a/Billing.Shared/Views/AddCategoryPage.xaml.cs b/Billing.Shared/Views/AddCategoryPage.xaml.cs
index a9cb66f..c4d7751 100644
--- a/Billing.Shared/Views/AddCategoryPage.xaml.cs
+++ b/Billing.Shared/Views/AddCategoryPage.xaml.cs
@@ -108,7 +108,6 @@ namespace Billing.Views
                 {
                     CategoryChecked?.Invoke(this, new Category
                     {
-                        Id = -1,
                         Name = CategoryName,
                         Icon = CategoryIcon,
                         TintColor = color,
diff --git a/Billing.Shared/Views/BillPage.xaml b/Billing.Shared/Views/BillPage.xaml
index c30a8ec..a33e2c1 100644
--- a/Billing.Shared/Views/BillPage.xaml
+++ b/Billing.Shared/Views/BillPage.xaml
@@ -101,6 +101,7 @@
                                                       CommandParameter="{Binding .}"/>
                             </Grid.GestureRecognizers>
                             <ui:TintImage Source="{Binding Icon, Converter={StaticResource iconConverter}}"
+                                          ui:TintHelper.TintColor="{Binding TintColor}"
                                           WidthRequest="26" HeightRequest="20" VerticalOptions="Center"/>
                             <Label Grid.Column="1" Text="{Binding Name}" TextColor="{DynamicResource TextColor}"
                                    VerticalOptions="Center"
diff --git a/Billing.Shared/Views/BillPage.xaml.cs b/Billing.Shared/Views/BillPage.xaml.cs
index a6ef24f..f3dbdba 100644
--- a/Billing.Shared/Views/BillPage.xaml.cs
+++ b/Billing.Shared/Views/BillPage.xaml.cs
@@ -167,18 +167,8 @@ namespace Billing.Views
 
         private async void OnBillChecked(object sender, Bill e)
         {
-            if (e.Id < 0)
+            if (e.Id <= 0)
             {
-                int maxId;
-                if (App.Bills.Count > 0)
-                {
-                    maxId = App.Bills.Max(b => b.Id);
-                }
-                else
-                {
-                    maxId = -1;
-                }
-                e.Id = maxId + 1;
                 App.Bills.Add(e);
                 var bills = Bills;
                 bills.Add(Helper.WrapBill(e));
@@ -189,7 +179,21 @@ namespace Billing.Views
                 var bill = Bills.FirstOrDefault(b => b.Bill == e);
                 if (bill != null)
                 {
-                    UpdateBill(bill);
+                    if (bill.DateCreation != e.CreateTime)
+                    {
+                        var bills = App.Bills.Where(b => Helper.IsSameDay(b.CreateTime, SelectedDate));
+                        Bills = new List<UIBill>(bills.OrderBy(b => b.CreateTime).Select(b => Helper.WrapBill(b)));
+                        RefreshBalance(Bills);
+
+                        RankPage.Instance?.SetNeedRefresh();
+
+                        await StoreHelper.SaveBillItemAsync(e);
+                        return;
+                    }
+                    else
+                    {
+                        UpdateBill(bill);
+                    }
                 }
             }
             RefreshBalance(Bills);
@@ -203,6 +207,7 @@ namespace Billing.Views
     public class UIBill : BindableObject
     {
         public static readonly BindableProperty IconProperty = Helper.Create<string, UIBill>(nameof(Icon));
+        public static readonly BindableProperty TintColorProperty = Helper.Create<Color, UIBill>(nameof(TintColor));
         public static readonly BindableProperty NameProperty = Helper.Create<string, UIBill>(nameof(Name));
         public static readonly BindableProperty DateCreationProperty = Helper.Create<DateTime, UIBill>(nameof(DateCreation));
         public static readonly BindableProperty AmountProperty = Helper.Create<decimal, UIBill>(nameof(Amount));
@@ -213,6 +218,11 @@ namespace Billing.Views
             get => (string)GetValue(IconProperty);
             set => SetValue(IconProperty, value);
         }
+        public Color TintColor
+        {
+            get => (Color)GetValue(TintColorProperty);
+            set => SetValue(TintColorProperty, value);
+        }
         public string Name
         {
             get => (string)GetValue(NameProperty);
diff --git a/Billing.Shared/Views/CategoryPage.xaml.cs b/Billing.Shared/Views/CategoryPage.xaml.cs
index d5f15bb..74203f1 100644
--- a/Billing.Shared/Views/CategoryPage.xaml.cs
+++ b/Billing.Shared/Views/CategoryPage.xaml.cs
@@ -146,19 +146,9 @@ namespace Billing.Views
 
         private async void OnCategoryChecked(object sender, Category category)
         {
-            if (category.Id < 0)
+            if (category.Id <= 0)
             {
                 // add
-                int maxId;
-                if (App.Categories.Count > 0)
-                {
-                    maxId = App.Categories.Max(b => b.Id);
-                }
-                else
-                {
-                    maxId = -1;
-                }
-                category.Id = maxId + 1;
                 App.Categories.Add(category);
                 Categories.Add(WrapCategory(category));
             }
diff --git a/Billing.Shared/Views/RankPage.xaml b/Billing.Shared/Views/RankPage.xaml
index aa21262..d71b60c 100644
--- a/Billing.Shared/Views/RankPage.xaml
+++ b/Billing.Shared/Views/RankPage.xaml
@@ -116,6 +116,7 @@
                                                           CommandParameter="{Binding .}"/>
                                 </Grid.GestureRecognizers>
                                 <ui:TintImage Source="{Binding Icon, Converter={StaticResource iconConverter}}"
+                                              ui:TintHelper.TintColor="{Binding TintColor}"
                                               WidthRequest="26" HeightRequest="20" VerticalOptions="Center"/>
                                 <Label Grid.Column="1" Text="{Binding Name}" TextColor="{DynamicResource TextColor}"
                                        VerticalOptions="Center"