initial commit

This commit is contained in:
Gitea
2020-11-13 14:13:12 -05:00
commit 05df49ff60
368 changed files with 128754 additions and 0 deletions

View File

@@ -0,0 +1,266 @@
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
local _, TSM = ...
local Auctions = TSM.MainUI.Ledger.Common:NewPackage("Auctions")
local L = TSM.Include("Locale").GetTable()
local Table = TSM.Include("Util.Table")
local String = TSM.Include("Util.String")
local Theme = TSM.Include("Util.Theme")
local ItemInfo = TSM.Include("Service.ItemInfo")
local Settings = TSM.Include("Service.Settings")
local UIElements = TSM.Include("UI.UIElements")
local SECONDS_PER_DAY = 24 * 60 * 60
local private = {
settings = nil,
query = nil,
characters = {},
characterFilter = {},
searchFilter = "",
groupFilter = {},
rarityList = {},
rarityFilter = {},
timeFrameFilter = 30 * SECONDS_PER_DAY,
type = nil
}
do
for i = 1, 4 do
tinsert(private.rarityList, _G[format("ITEM_QUALITY%d_DESC", i)])
private.rarityFilter[i] = true
end
end
local TIME_LIST = { L["All Time"], L["Last 3 Days"], L["Last 7 Days"], L["Last 14 Days"], L["Last 30 Days"], L["Last 60 Days"] }
local TIME_KEYS = { 0, 3 * SECONDS_PER_DAY, 7 * SECONDS_PER_DAY, 14 * SECONDS_PER_DAY, 30 * SECONDS_PER_DAY, 60 * SECONDS_PER_DAY }
-- ============================================================================
-- Module Functions
-- ============================================================================
function Auctions.OnInitialize()
private.settings = Settings.NewView()
:AddKey("global", "mainUIContext", "ledgerAuctionsScrollingTable")
TSM.MainUI.Ledger.FailedAuctions.RegisterPage(L["Expired"], private.DrawExpiredPage)
TSM.MainUI.Ledger.FailedAuctions.RegisterPage(L["Cancelled"], private.DrawCancelledPage)
end
-- ============================================================================
-- Auctions UIs
-- ============================================================================
function private.DrawExpiredPage()
TSM.UI.AnalyticsRecordPathChange("main", "ledger", "failed_auctions", "expired")
private.type = "expire"
return private.DrawAuctionsPage()
end
function private.DrawCancelledPage()
TSM.UI.AnalyticsRecordPathChange("main", "ledger", "failed_auctions", "cancelled")
private.type = "cancel"
return private.DrawAuctionsPage()
end
function private.DrawAuctionsPage()
private.query = private.query or TSM.Accounting.Auctions.CreateQuery()
private.query:Reset()
:Equal("type", "cancel")
:Distinct("player")
:Select("player")
wipe(private.characters)
for _, character in private.query:Iterator() do
tinsert(private.characters, character)
private.characterFilter[character] = true
end
private.query:Reset()
:InnerJoin(ItemInfo.GetDBForJoin(), "itemString")
:LeftJoin(TSM.Groups.GetItemDBForJoin(), "itemString")
:OrderBy("time", false)
private.UpdateQuery()
return UIElements.New("Frame", "content")
:SetLayout("VERTICAL")
:AddChild(UIElements.New("Frame", "row1")
:SetLayout("HORIZONTAL")
:SetHeight(24)
:SetMargin(8)
:AddChild(UIElements.New("Input", "filter")
:SetMargin(0, 8, 0, 0)
:SetIconTexture("iconPack.18x18/Search")
:SetClearButtonEnabled(true)
:AllowItemInsert()
:SetHintText(L["Filter by keyword"])
:SetValue(private.searchFilter)
:SetScript("OnValueChanged", private.SearchFilterChanged)
)
:AddChild(UIElements.New("GroupSelector", "group")
:SetWidth(240)
:SetHintText(L["Filter by groups"])
:SetScript("OnSelectionChanged", private.GroupFilterChanged)
)
)
:AddChild(UIElements.New("Frame", "row2")
:SetLayout("HORIZONTAL")
:SetHeight(24)
:SetMargin(8, 8, 0, 8)
:AddChild(UIElements.New("MultiselectionDropdown", "rarity")
:SetMargin(0, 8, 0, 0)
:SetItems(private.rarityList)
:SetSettingInfo(private, "rarityFilter")
:SetSelectionText(L["No Rarities"], L["%d Rarities"], L["All Rarites"])
:SetScript("OnSelectionChanged", private.DropdownCommonOnSelectionChanged)
)
:AddChild(UIElements.New("MultiselectionDropdown", "character")
:SetMargin(0, 8, 0, 0)
:SetItems(private.characters, private.characters)
:SetSettingInfo(private, "characterFilter")
:SetSelectionText(L["No Characters"], L["%d Characters"], L["All Characters"])
:SetScript("OnSelectionChanged", private.DropdownCommonOnSelectionChanged)
)
:AddChild(UIElements.New("SelectionDropdown", "time")
:SetItems(TIME_LIST, TIME_KEYS)
:SetSelectedItemByKey(private.timeFrameFilter)
:SetSettingInfo(private, "timeFrameFilter")
:SetScript("OnSelectionChanged", private.DropdownCommonOnSelectionChanged)
)
)
:AddChild(UIElements.New("QueryScrollingTable", "scrollingTable")
:SetSettingsContext(private.settings, "ledgerAuctionsScrollingTable")
:GetScrollingTableInfo()
:NewColumn("item")
:SetTitle(L["Item"])
:SetFont("ITEM_BODY3")
:SetJustifyH("LEFT")
:SetTextInfo("itemString", TSM.UI.GetColoredItemName)
:SetTooltipInfo("itemString")
:SetSortInfo("name")
:DisableHiding()
:Commit()
:NewColumn("player")
:SetTitle(PLAYER)
:SetFont("ITEM_BODY3")
:SetJustifyH("LEFT")
:SetTextInfo("player")
:SetSortInfo("player")
:Commit()
:NewColumn("stackSize")
:SetTitle(L["Stack"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo("stackSize")
:SetSortInfo("stackSize")
:Commit()
:NewColumn("quantity")
:SetTitle(L["Auctions"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo(nil, private.FormatAuctions)
:SetSortInfo("quantity")
:Commit()
:NewColumn("time")
:SetTitle(L["Time Frame"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo("time", private.TableGetTimeframeText)
:SetSortInfo("time")
:Commit()
:Commit()
:SetQuery(private.query)
:SetScript("OnRowClick", private.TableSelectionChanged)
)
:AddChild(UIElements.New("Texture", "line")
:SetHeight(2)
:SetTexture("ACTIVE_BG")
)
:AddChild(UIElements.New("Frame", "footer")
:SetLayout("HORIZONTAL")
:SetHeight(40)
:SetPadding(8)
:SetBackgroundColor("PRIMARY_BG")
:AddChild(UIElements.New("Text", "num")
:SetWidth("AUTO")
:SetFont("BODY_BODY2_MEDIUM")
:SetText(format(private.type == "expire" and L["%s Items Expired"] or L["%s Items Cancelled"], Theme.GetColor("INDICATOR"):ColorText(FormatLargeNumber(private.query:Sum("quantity") or 0))))
)
:AddChild(UIElements.New("Spacer", "spacer"))
)
end
-- ============================================================================
-- Scrolling Table Helper Functions
-- ============================================================================
function private.TableGetTimeframeText(record)
return SecondsToTime(time() - record)
end
function private.FormatAuctions(row)
return row:GetField("quantity") / row:GetField("stackSize")
end
-- ============================================================================
-- Local Script Handlers
-- ============================================================================
function private.DropdownCommonOnSelectionChanged(dropdown)
private.UpdateQuery()
dropdown:GetElement("__parent.__parent.scrollingTable")
:UpdateData(true)
local footer = dropdown:GetElement("__parent.__parent.footer")
footer:GetElement("num"):SetText(format(private.type == "expire" and L["%s Items Expired"] or L["%s Items Cancelled"], Theme.GetColor("INDICATOR"):ColorText(FormatLargeNumber(private.query:Sum("quantity") or 0))))
footer:Draw()
end
function private.SearchFilterChanged(input)
private.searchFilter = input:GetValue()
private.DropdownCommonOnSelectionChanged(input)
end
function private.GroupFilterChanged(groupSelector)
wipe(private.groupFilter)
for groupPath in groupSelector:SelectedGroupIterator() do
private.groupFilter[groupPath] = true
end
private.DropdownCommonOnSelectionChanged(groupSelector)
end
-- ============================================================================
-- Private Helper Functions
-- ============================================================================
function private.UpdateQuery()
private.query:ResetFilters()
:Equal("type", private.type)
if private.searchFilter ~= "" then
private.query:Matches("name", String.Escape(private.searchFilter))
end
if Table.Count(private.rarityFilter) ~= #private.rarityList then
private.query:InTable("quality", private.rarityFilter)
end
if Table.Count(private.characterFilter) ~= #private.characters then
private.query:InTable("player", private.characterFilter)
end
if private.timeFrameFilter ~= 0 then
private.query:GreaterThanOrEqual("time", time() - private.timeFrameFilter)
end
if next(private.groupFilter) then
private.query:InTable("groupPath", private.groupFilter)
end
end
function private.TableSelectionChanged(scrollingTable, row)
TSM.MainUI.Ledger.ShowItemDetail(scrollingTable:GetParentElement():GetParentElement(), row:GetField("itemString"), "sale")
end

View File

@@ -0,0 +1,8 @@
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
local _, TSM = ...
TSM.MainUI.Ledger:NewPackage("Common")

View File

@@ -0,0 +1,208 @@
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
local _, TSM = ...
local Other = TSM.MainUI.Ledger.Common:NewPackage("Other")
local L = TSM.Include("Locale").GetTable()
local Table = TSM.Include("Util.Table")
local Money = TSM.Include("Util.Money")
local Settings = TSM.Include("Service.Settings")
local UIElements = TSM.Include("UI.UIElements")
local SECONDS_PER_DAY = 24 * 60 * 60
local private = {
settings = nil,
query = nil,
characters = {},
characterFilter = {},
typeFilter = {},
recordType = nil,
timeFrameFilter = 30 * SECONDS_PER_DAY,
}
local TIME_LIST = { L["All Time"], L["Last 3 Days"], L["Last 7 Days"], L["Last 14 Days"], L["Last 30 Days"], L["Last 60 Days"] }
local TIME_KEYS = { 0, 3 * SECONDS_PER_DAY, 7 * SECONDS_PER_DAY, 14 * SECONDS_PER_DAY, 30 * SECONDS_PER_DAY, 60 * SECONDS_PER_DAY }
local TYPE_LIST = {
expense = { L["Money Transfer"], L["Postage"], L["Repair Bill"] },
income = { L["Money Transfer"], L["Garrison"] },
}
local TYPE_KEYS = {
expense = { "Money Transfer", "Postage", "Repair Bill" },
income = { "Money Transfer", "Garrison" },
}
local TYPE_STR_LOOKUP = {}
do
-- populate lookup table
assert(#TYPE_LIST.expense == #TYPE_KEYS.expense)
for i = 1, #TYPE_LIST.expense do
TYPE_STR_LOOKUP[TYPE_KEYS.expense[i]] = TYPE_LIST.expense[i]
end
assert(#TYPE_LIST.income == #TYPE_KEYS.income)
for i = 1, #TYPE_LIST.income do
TYPE_STR_LOOKUP[TYPE_KEYS.income[i]] = TYPE_LIST.income[i]
end
end
-- ============================================================================
-- Module Functions
-- ============================================================================
function Other.OnInitialize()
private.settings = Settings.NewView()
:AddKey("global", "mainUIContext", "ledgerOtherScrollingTable")
TSM.MainUI.Ledger.Expenses.RegisterPage(OTHER, private.DrawOtherExpensesPage)
TSM.MainUI.Ledger.Revenue.RegisterPage(OTHER, private.DrawOtherRevenuePage)
end
-- ============================================================================
-- Other UIs
-- ============================================================================
function private.DrawOtherExpensesPage()
TSM.UI.AnalyticsRecordPathChange("main", "ledger", "expenses", "other")
return private.DrawOtherPage("expense")
end
function private.DrawOtherRevenuePage()
TSM.UI.AnalyticsRecordPathChange("main", "ledger", "revenue", "other")
return private.DrawOtherPage("income")
end
function private.DrawOtherPage(recordType)
wipe(private.characters)
for _, character in TSM.Accounting.Money.CharacterIterator(recordType) do
tinsert(private.characters, character)
private.characterFilter[character] = true
end
wipe(private.typeFilter)
for _, key in ipairs(TYPE_KEYS[recordType]) do
private.typeFilter[key] = true
end
if not private.query then
private.query = TSM.Accounting.Money.CreateQuery()
:OrderBy("time", false)
end
private.recordType = recordType
private.UpdateQuery()
return UIElements.New("Frame", "content")
:SetLayout("VERTICAL")
:AddChild(UIElements.New("Frame", "row2")
:SetLayout("HORIZONTAL")
:SetHeight(24)
:SetMargin(8)
:AddChild(UIElements.New("MultiselectionDropdown", "type")
:SetMargin(0, 8, 0, 0)
:SetItems(TYPE_LIST[recordType], TYPE_KEYS[recordType])
:SetSettingInfo(private, "typeFilter")
:SetSelectionText(L["No Types"], L["%d Types"], L["All Types"])
:SetScript("OnSelectionChanged", private.DropdownChangedCommon)
)
:AddChild(UIElements.New("MultiselectionDropdown", "character")
:SetMargin(0, 8, 0, 0)
:SetItems(private.characters, private.characters)
:SetSettingInfo(private, "characterFilter")
:SetSelectionText(L["No Characters"], L["%d Characters"], L["All Characters"])
:SetScript("OnSelectionChanged", private.DropdownChangedCommon)
)
:AddChild(UIElements.New("SelectionDropdown", "time")
:SetItems(TIME_LIST, TIME_KEYS)
:SetSelectedItemByKey(private.timeFrameFilter)
:SetSettingInfo(private, "timeFrameFilter")
:SetScript("OnSelectionChanged", private.DropdownChangedCommon)
)
)
:AddChild(UIElements.New("QueryScrollingTable", "table")
:SetSettingsContext(private.settings, "ledgerOtherScrollingTable")
:GetScrollingTableInfo()
:NewColumn("type")
:SetTitle(L["Type"])
:SetFont("ITEM_BODY3")
:SetJustifyH("LEFT")
:SetTextInfo("type", private.TableGetTypeText)
:SetSortInfo("type")
:Commit()
:NewColumn("character")
:SetTitle(L["Character"])
:SetFont("ITEM_BODY3")
:SetJustifyH("LEFT")
:SetTextInfo("player")
:SetSortInfo("player")
:Commit()
:NewColumn("otherCharacter")
:SetTitle(L["Other Character"])
:SetFont("ITEM_BODY3")
:SetJustifyH("LEFT")
:SetTextInfo("otherPlayer")
:SetSortInfo("otherPlayer")
:Commit()
:NewColumn("amount")
:SetTitle(L["Amount"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo("amount", Money.ToString)
:SetSortInfo("amount")
:Commit()
:NewColumn("time")
:SetTitle(L["Time Frame"])
:SetFont("ITEM_BODY3")
:SetJustifyH("LEFT")
:SetTextInfo("time", private.TableGetTimeText)
:SetSortInfo("time")
:Commit()
:Commit()
:SetQuery(private.query)
:SetSelectionDisabled(true)
)
end
-- ============================================================================
-- Scrolling Table Helper Functions
-- ============================================================================
function private.TableGetTypeText(typeValue)
return TYPE_STR_LOOKUP[typeValue]
end
function private.TableGetTimeText(timevalue)
return SecondsToTime(time() - timevalue)
end
-- ============================================================================
-- Local Script Handlers
-- ============================================================================
function private.DropdownChangedCommon(dropdown)
private.UpdateQuery()
dropdown:GetElement("__parent.__parent.table"):UpdateData(true)
end
-- ============================================================================
-- Private Helper Functions
-- ============================================================================
function private.UpdateQuery()
private.query:ResetFilters()
:Equal("recordType", private.recordType)
if Table.Count(private.typeFilter) ~= #TYPE_KEYS[private.recordType] then
private.query:InTable("type", private.typeFilter)
end
if Table.Count(private.characterFilter) ~= #private.characters then
private.query:InTable("player", private.characterFilter)
end
if private.timeFrameFilter ~= 0 then
private.query:GreaterThan("time", time() - private.timeFrameFilter)
end
end

View File

@@ -0,0 +1,329 @@
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
local _, TSM = ...
local Transactions = TSM.MainUI.Ledger.Common:NewPackage("Transactions")
local L = TSM.Include("Locale").GetTable()
local Money = TSM.Include("Util.Money")
local String = TSM.Include("Util.String")
local Table = TSM.Include("Util.Table")
local Theme = TSM.Include("Util.Theme")
local ItemInfo = TSM.Include("Service.ItemInfo")
local Settings = TSM.Include("Service.Settings")
local UIElements = TSM.Include("UI.UIElements")
local SECONDS_PER_DAY = 24 * 60 * 60
local private = {
settings = nil,
query = nil,
characters = {},
characterFilter = {},
typeFilter = {},
searchFilter = "",
groupFilter = {},
rarityList = {},
rarityFilter = {},
timeFrameFilter = 30 * SECONDS_PER_DAY,
type = nil
}
local TYPE_LIST = { L["Auction"], COD, TRADE, L["Vendor"] }
local TYPE_KEYS = { "Auction", "COD", "Trade", "Vendor" }
do
for _, key in ipairs(TYPE_KEYS) do
private.typeFilter[key] = true
end
for i = 1, 4 do
tinsert(private.rarityList, _G[format("ITEM_QUALITY%d_DESC", i)])
private.rarityFilter[i] = true
end
end
local TIME_LIST = { L["All Time"], L["Last 3 Days"], L["Last 7 Days"], L["Last 14 Days"], L["Last 30 Days"], L["Last 60 Days"] }
local TIME_KEYS = { 0, 3 * SECONDS_PER_DAY, 7 * SECONDS_PER_DAY, 14 * SECONDS_PER_DAY, 30 * SECONDS_PER_DAY, 60 * SECONDS_PER_DAY }
-- ============================================================================
-- Module Functions
-- ============================================================================
function Transactions.OnInitialize()
private.settings = Settings.NewView()
:AddKey("global", "mainUIContext", "ledgerTransactionsScrollingTable")
TSM.MainUI.Ledger.Expenses.RegisterPage(L["Purchases"], private.DrawPurchasesPage)
TSM.MainUI.Ledger.Revenue.RegisterPage(L["Sales"], private.DrawSalesPage)
end
-- ============================================================================
-- Transactions UIs
-- ============================================================================
function private.DrawPurchasesPage()
TSM.UI.AnalyticsRecordPathChange("main", "ledger", "expenses", "purchases")
private.type = "buy"
return private.DrawTransactionPage()
end
function private.DrawSalesPage()
TSM.UI.AnalyticsRecordPathChange("main", "ledger", "revenue", "sales")
private.type = "sale"
return private.DrawTransactionPage()
end
function private.DrawTransactionPage()
private.query = private.query or TSM.Accounting.Transactions.CreateQuery()
private.query:Reset()
:Equal("type", private.type)
:Distinct("player")
:Select("player")
wipe(private.characters)
for _, character in private.query:Iterator() do
tinsert(private.characters, character)
private.characterFilter[character] = true
end
private.query:Reset()
:InnerJoin(ItemInfo.GetDBForJoin(), "itemString")
:LeftJoin(TSM.Groups.GetItemDBForJoin(), "itemString")
:VirtualField("total", "number", private.GetTotal)
:VirtualField("auctions", "number", private.GetAuctions)
:OrderBy("time", false)
private.UpdateQuery()
local numItems = private.query:Sum("quantity") or 0
local total = private.query:Sum("total") or 0
return UIElements.New("Frame", "content")
:SetLayout("VERTICAL")
:AddChild(UIElements.New("Frame", "row1")
:SetLayout("HORIZONTAL")
:SetHeight(24)
:SetMargin(8)
:AddChild(UIElements.New("Input", "filter")
:SetMargin(0, 8, 0, 0)
:SetIconTexture("iconPack.18x18/Search")
:SetClearButtonEnabled(true)
:AllowItemInsert()
:SetHintText(L["Filter by keyword"])
:SetValue(private.searchFilter)
:SetScript("OnValueChanged", private.SearchFilterChanged)
)
:AddChild(UIElements.New("GroupSelector", "group")
:SetWidth(240)
:SetHintText(L["Filter by groups"])
:SetScript("OnSelectionChanged", private.GroupFilterChanged)
)
)
:AddChild(UIElements.New("Frame", "row2")
:SetLayout("HORIZONTAL")
:SetHeight(24)
:SetMargin(8, 8, 0, 8)
:AddChild(UIElements.New("MultiselectionDropdown", "type")
:SetMargin(0, 8, 0, 0)
:SetItems(TYPE_LIST, TYPE_KEYS)
:SetSettingInfo(private, "typeFilter")
:SetSelectionText(L["No Types"], L["%d Types"], L["All Types"])
:SetScript("OnSelectionChanged", private.DropdownCommonOnSelectionChanged)
)
:AddChild(UIElements.New("MultiselectionDropdown", "rarity")
:SetMargin(0, 8, 0, 0)
:SetItems(private.rarityList)
:SetSettingInfo(private, "rarityFilter")
:SetSelectionText(L["No Rarities"], L["%d Rarities"], L["All Rarities"])
:SetScript("OnSelectionChanged", private.DropdownCommonOnSelectionChanged)
)
:AddChild(UIElements.New("MultiselectionDropdown", "character")
:SetMargin(0, 8, 0, 0)
:SetItems(private.characters, private.characters)
:SetSettingInfo(private, "characterFilter")
:SetSelectionText(L["No Characters"], L["%d Characters"], L["All Characters"])
:SetScript("OnSelectionChanged", private.DropdownCommonOnSelectionChanged)
)
:AddChild(UIElements.New("SelectionDropdown", "time")
:SetItems(TIME_LIST, TIME_KEYS)
:SetSelectedItemByKey(private.timeFrameFilter)
:SetSettingInfo(private, "timeFrameFilter")
:SetScript("OnSelectionChanged", private.DropdownCommonOnSelectionChanged)
)
)
:AddChild(UIElements.New("QueryScrollingTable", "scrollingTable")
:SetSettingsContext(private.settings, "ledgerTransactionsScrollingTable")
:GetScrollingTableInfo()
:NewColumn("item")
:SetTitle(L["Item"])
:SetFont("ITEM_BODY3")
:SetJustifyH("LEFT")
:SetTextInfo("itemString", TSM.UI.GetColoredItemName)
:SetTooltipInfo("itemString")
:SetSortInfo("name")
:DisableHiding()
:Commit()
:NewColumn("player")
:SetTitle(PLAYER)
:SetFont("ITEM_BODY3")
:SetJustifyH("LEFT")
:SetTextInfo("otherPlayer")
:SetSortInfo("otherPlayer")
:Commit()
:NewColumn("type")
:SetTitle(L["Type"])
:SetFont("ITEM_BODY3")
:SetJustifyH("LEFT")
:SetTextInfo("source")
:SetSortInfo("source")
:Commit()
:NewColumn("stack")
:SetTitle(L["Stack"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo("stackSize")
:SetSortInfo("stackSize")
:Commit()
:NewColumn("auctions")
:SetTitle(L["Auctions"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo("auctions")
:SetSortInfo("auctions")
:Commit()
:NewColumn("perItem")
:SetTitle(L["Per Item"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo("price", private.TableGetPriceText)
:SetSortInfo("price")
:Commit()
:NewColumn("total")
:SetTitle(L["Total"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo("total", private.TableGetPriceText)
:SetSortInfo("total")
:Commit()
:NewColumn("time")
:SetTitle(L["Time Frame"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo("time", private.TableGetTimeframeText)
:SetSortInfo("time")
:Commit()
:Commit()
:SetQuery(private.query)
:SetScript("OnRowClick", private.TableSelectionChanged)
)
:AddChild(UIElements.New("Texture", "line")
:SetHeight(2)
:SetTexture("ACTIVE_BG")
)
:AddChild(UIElements.New("Frame", "footer")
:SetLayout("HORIZONTAL")
:SetHeight(40)
:SetPadding(8)
:SetBackgroundColor("PRIMARY_BG")
:AddChild(UIElements.New("Text", "num")
:SetWidth("AUTO")
:SetFont("BODY_BODY2_MEDIUM")
:SetText(format(private.type == "sale" and L["%s Items Sold"] or L["%s Items Bought"], Theme.GetColor("INDICATOR"):ColorText(FormatLargeNumber(numItems))))
)
:AddChild(UIElements.New("Texture", "line")
:SetMargin(4, 8, 0, 0)
:SetWidth(2)
:SetTexture("ACTIVE_BG")
)
:AddChild(UIElements.New("Text", "profit")
:SetWidth("AUTO")
:SetFont("BODY_BODY2_MEDIUM")
:SetText(format(L["%s Total"], Money.ToString(total)))
)
:AddChild(UIElements.New("Spacer", "spacer"))
)
end
-- ============================================================================
-- Scrolling Table Helper Functions
-- ============================================================================
function private.TableGetPriceText(price)
return Money.ToString(price)
end
function private.TableGetTimeframeText(record)
return SecondsToTime(time() - record)
end
-- ============================================================================
-- Local Script Handlers
-- ============================================================================
function private.DropdownCommonOnSelectionChanged(dropdown)
private.UpdateQuery()
local numItems = private.query:Sum("quantity") or 0
local total = private.query:Sum("total") or 0
dropdown:GetElement("__parent.__parent.scrollingTable")
:UpdateData(true)
local footer = dropdown:GetElement("__parent.__parent.footer")
footer:GetElement("num"):SetText(format(private.type == "sale" and L["%s Items Sold"] or L["%s Items Bought"], Theme.GetColor("INDICATOR"):ColorText(FormatLargeNumber(numItems))))
footer:GetElement("profit"):SetText(format(L["%s Total"], Money.ToString(total)))
footer:Draw()
end
function private.SearchFilterChanged(input)
private.searchFilter = input:GetValue()
private.DropdownCommonOnSelectionChanged(input)
end
function private.GroupFilterChanged(groupSelector)
wipe(private.groupFilter)
for groupPath in groupSelector:SelectedGroupIterator() do
private.groupFilter[groupPath] = true
end
private.DropdownCommonOnSelectionChanged(groupSelector)
end
-- ============================================================================
-- Private Helper Functions
-- ============================================================================
function private.GetTotal(row)
return row:GetField("price") * row:GetField("quantity")
end
function private.GetAuctions(row)
return row:GetField("quantity") / row:GetField("stackSize")
end
function private.UpdateQuery()
private.query:ResetFilters()
:Equal("type", private.type)
if private.searchFilter ~= "" then
private.query:Matches("name", String.Escape(private.searchFilter))
end
if Table.Count(private.typeFilter) ~= #TYPE_KEYS then
private.query:InTable("source", private.typeFilter)
end
if Table.Count(private.rarityFilter) ~= #private.rarityList then
private.query:InTable("quality", private.rarityFilter)
end
if Table.Count(private.characterFilter) ~= #private.characters then
private.query:InTable("player", private.characterFilter)
end
if private.timeFrameFilter ~= 0 then
private.query:GreaterThan("time", time() - private.timeFrameFilter)
end
if next(private.groupFilter) then
private.query:InTable("groupPath", private.groupFilter)
end
end
function private.TableSelectionChanged(scrollingTable, row)
TSM.MainUI.Ledger.ShowItemDetail(scrollingTable:GetParentElement():GetParentElement(), row:GetField("itemString"), private.type)
end

View File

@@ -0,0 +1,524 @@
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
local _, TSM = ...
local Ledger = TSM.MainUI:NewPackage("Ledger")
local L = TSM.Include("Locale").GetTable()
local TempTable = TSM.Include("Util.TempTable")
local Table = TSM.Include("Util.Table")
local Money = TSM.Include("Util.Money")
local Theme = TSM.Include("Util.Theme")
local Log = TSM.Include("Util.Log")
local ItemInfo = TSM.Include("Service.ItemInfo")
local Settings = TSM.Include("Service.Settings")
local UIElements = TSM.Include("UI.UIElements")
local SECONDS_PER_DAY = 24 * 60 * 60
local private = {
settings = nil,
pages = {},
childPages = {},
callback = {},
contextPath = nil,
contextItemString = nil,
itemDetailType = "sale",
}
local NUM_TOP_PLAYERS = 3
local PAGE_PATH_SEP = "`"
-- ============================================================================
-- Module Functions
-- ============================================================================
function Ledger.OnInitialize()
private.settings = Settings.NewView()
:AddKey("global", "mainUIContext", "ledgerDetailScrollingTable")
TSM.MainUI.RegisterTopLevelPage(L["Ledger"], private.GetLedgerFrame)
end
function Ledger.RegisterPage(name, callback)
tinsert(private.pages, name)
private.callback[name] = callback
end
function Ledger.RegisterChildPage(parentName, childName, callback)
local path = parentName..PAGE_PATH_SEP..childName
private.childPages[parentName] = private.childPages[parentName] or {}
tinsert(private.childPages[parentName], childName)
private.callback[path] = callback
end
function Ledger.ShowItemDetail(frame, itemString, detailType)
assert(detailType == "sale" or detailType == "buy")
private.contextItemString = itemString
private.itemDetailType = detailType
frame:SetPath("itemDetail", true)
end
-- ============================================================================
-- Ledger UI
-- ============================================================================
function private.GetLedgerFrame()
TSM.UI.AnalyticsRecordPathChange("main", "ledger")
local defaultPage = private.pages[1]
local frame = UIElements.New("Frame", "ledger")
:SetLayout("HORIZONTAL")
:SetBackgroundColor("PRIMARY_BG_ALT")
:AddChild(UIElements.New("Frame", "navigation")
:SetLayout("VERTICAL")
:SetWidth(160)
:SetPadding(12, 12, 1, 9)
)
:AddChild(UIElements.New("Texture", "divider")
:SetWidth(2)
:SetTexture("ACTIVE_BG")
)
:AddChild(UIElements.New("Frame", "contentFrame")
:SetLayout("VERTICAL")
:AddChild(UIElements.New("ViewContainer", "content")
:SetNavCallback(private.ContentNavCallback)
:AddPath("itemDetail")
)
)
:SetScript("OnHide", private.NavButtonOnHide)
local content = frame:GetElement("contentFrame.content")
local navFrame = frame:GetElement("navigation")
for _, pageName in ipairs(private.pages) do
navFrame:AddChild(UIElements.New("Button", pageName)
:SetHeight(20)
:SetMargin(0, 0, 8, 0)
:SetFont("BODY_BODY2_BOLD")
:SetJustifyH("LEFT")
:SetContext(pageName)
:SetText(pageName)
:SetScript("OnClick", private.NavButtonOnClick)
)
content:AddPath(pageName, pageName == defaultPage)
if private.childPages[pageName] then
for _, childPageName in ipairs(private.childPages[pageName]) do
local path = pageName..PAGE_PATH_SEP..childPageName
navFrame:AddChild(UIElements.New("Button", path)
:SetHeight(20)
:SetMargin(9, 0, 8, 0)
:SetFont("BODY_BODY3_MEDIUM")
:SetJustifyH("LEFT")
:SetContext(path)
:SetText(childPageName)
:SetScript("OnClick", private.NavButtonOnClick)
)
content:AddPath(path, path == defaultPage)
end
end
end
-- make all the navigation align to the top
navFrame:AddChild(UIElements.New("Spacer", "spacer"))
private.UpdateNavFrame(navFrame, defaultPage)
private.contextPath = L["Inventory"]
return frame
end
function private.ContentNavCallback(self, path)
if path == "itemDetail" then
return private.GetItemDetail()
else
return private.callback[path]()
end
end
-- ============================================================================
-- Local Script Handlers
-- ============================================================================
function private.NavButtonOnClick(button)
local path = button:GetContext()
if private.contextPath == path then
return
end
if private.childPages[path] then
-- select the first child
path = path..PAGE_PATH_SEP..private.childPages[path][1]
end
local ledgerFrame = button:GetParentElement():GetParentElement()
local contentFrame = ledgerFrame:GetElement("contentFrame")
local navFrame = ledgerFrame:GetElement("navigation")
private.UpdateNavFrame(navFrame, path)
navFrame:Draw()
contentFrame:GetElement("content"):SetPath(path, private.contextPath ~= path)
private.contextPath = path
end
function private.NavButtonOnHide(button)
private.contextPath = nil
end
-- ============================================================================
-- Private Helper Functions
-- ============================================================================
function private.UpdateNavFrame(navFrame, selectedPath)
local selectedPage = strsplit(PAGE_PATH_SEP, selectedPath)
for _, pageName in ipairs(private.pages) do
navFrame:GetElement(pageName):SetTextColor(pageName == selectedPage and "TEXT" or "ACTIVE_BG_ALT")
if private.childPages[pageName] then
for _, childPageName in ipairs(private.childPages[pageName]) do
local path = pageName..PAGE_PATH_SEP..childPageName
if pageName == selectedPage then
navFrame:GetElement(path)
:SetTextColor(path == selectedPath and "INDICATOR" or "TEXT")
:Show()
else
navFrame:GetElement(path):Hide()
end
end
end
end
end
function private.GetItemDetail()
local query = TSM.Accounting.Transactions.CreateQuery()
:Equal("itemString", private.contextItemString)
:OrderBy("time", false)
local topPlayersQuantity = TempTable.Acquire()
local topPlayers = TempTable.Acquire()
for _, row in query:Iterator() do
local recordType, otherPlayer, quantity = row:GetFields("type", "otherPlayer", "quantity")
if recordType == private.itemDetailType then
if not topPlayersQuantity[otherPlayer] then
topPlayersQuantity[otherPlayer] = 0
tinsert(topPlayers, otherPlayer)
end
topPlayersQuantity[otherPlayer] = topPlayersQuantity[otherPlayer] + quantity
end
end
Table.SortWithValueLookup(topPlayers, topPlayersQuantity, true)
local numTopPlayers = min(#topPlayers, NUM_TOP_PLAYERS)
local topPlayersText = ""
if numTopPlayers > 0 then
for i = 1, numTopPlayers do
local player = topPlayers[i]
local quantity = topPlayersQuantity[player]
topPlayers[i] = player..Theme.GetColor("INDICATOR_ALT"):ColorText(" (" .. quantity .. ")")
end
topPlayersText = table.concat(topPlayers, ", ", 1, numTopPlayers)
else
topPlayersText = L["None"]
end
TempTable.Release(topPlayers)
TempTable.Release(topPlayersQuantity)
return UIElements.New("Frame", "content")
:SetLayout("VERTICAL")
:AddChild(UIElements.New("Frame", "top")
:SetLayout("VERTICAL")
:SetPadding(8)
:SetBackgroundColor("PRIMARY_BG_ALT")
:AddChild(UIElements.New("Frame", "header")
:SetLayout("HORIZONTAL")
:SetHeight(24)
:AddChild(UIElements.New("ActionButton", "button")
:SetWidth(64)
:SetIcon("iconPack.14x14/Chevron/Right@180")
:SetText(BACK)
:SetScript("OnClick", private.ItemDetailBackButtonOnClick)
)
:AddChild(UIElements.New("Button", "icon")
:SetSize(24, 24)
:SetMargin(14, 8, 0, 0)
:SetBackground(ItemInfo.GetTexture(private.contextItemString))
:SetTooltip(private.contextItemString)
)
:AddChild(UIElements.New("Text", "itemName")
:SetFont("ITEM_BODY1")
:SetText(TSM.UI.GetColoredItemName(private.contextItemString))
)
)
:AddChild(UIElements.New("Frame", "content")
:SetLayout("VERTICAL")
:SetMargin(0, 0, 8, 0)
:SetPadding(12, 12, 8, 10)
:SetBackgroundColor("PRIMARY_BG_ALT", true)
:SetBorderColor("ACTIVE_BG")
:AddChild(UIElements.New("Frame", "heading")
:SetLayout("HORIZONTAL")
:SetHeight(20)
:AddChild(UIElements.New("Button", "saleBtn")
:SetWidth("AUTO")
:SetMargin(0, 8, 0, 0)
:SetFont("BODY_BODY2_BOLD")
:SetTextColor(private.itemDetailType == "sale" and "INDICATOR" or "ACTIVE_BG_ALT")
:SetContext("sale")
:SetText(L["Sale Data"])
:SetScript("OnClick", private.ItemDetailTabOnClick)
)
:AddChild(UIElements.New("Button", "buyBtn")
:SetWidth("AUTO")
:SetMargin(0, 8, 0, 0)
:SetFont("BODY_BODY2_BOLD")
:SetTextColor(private.itemDetailType == "buy" and "INDICATOR" or "ACTIVE_BG_ALT")
:SetContext("buy")
:SetText(L["Purchase Data"])
:SetScript("OnClick", private.ItemDetailTabOnClick)
)
:AddChild(UIElements.New("Spacer", "spacer"))
:AddChild(UIElements.New("Text", "total")
:SetWidth(120)
:SetMargin(0, 8, 0, 0)
:SetFont("BODY_BODY3_MEDIUM")
:SetJustifyH("RIGHT")
:SetText(L["Total"])
)
:AddChild(UIElements.New("Text", "last7")
:SetWidth(120)
:SetMargin(0, 8, 0, 0)
:SetFont("BODY_BODY3_MEDIUM")
:SetJustifyH("RIGHT")
:SetText(L["Last 7 Days"])
)
:AddChild(UIElements.New("Text", "last30")
:SetWidth(120)
:SetFont("BODY_BODY3_MEDIUM")
:SetJustifyH("RIGHT")
:SetText(L["Last 30 Days"])
)
)
:AddChild(UIElements.New("Frame", "quantity")
:SetLayout("HORIZONTAL")
:SetHeight(20)
:SetMargin(0, 0, 8, 0)
:AddChild(UIElements.New("Text", "label")
:SetMargin(0, 8, 0, 0)
:SetFont("BODY_BODY3")
:SetTextColor("TEXT_ALT")
:SetText(private.itemDetailType == "sale" and L["Quantity Sold:"] or L["Quantity Purchased:"])
)
:AddChild(UIElements.New("Text", "total")
:SetWidth(120)
:SetMargin(0, 8, 0, 0)
:SetFont("TABLE_TABLE1")
:SetJustifyH("RIGHT")
:SetText(TSM.Accounting.Transactions.GetQuantity(private.contextItemString, nil, private.itemDetailType))
)
:AddChild(UIElements.New("Text", "last7")
:SetWidth(120)
:SetMargin(0, 8, 0, 0)
:SetFont("TABLE_TABLE1")
:SetJustifyH("RIGHT")
:SetText(TSM.Accounting.Transactions.GetQuantity(private.contextItemString, SECONDS_PER_DAY * 7, private.itemDetailType))
)
:AddChild(UIElements.New("Text", "last30")
:SetWidth(120)
:SetFont("TABLE_TABLE1")
:SetJustifyH("RIGHT")
:SetText(TSM.Accounting.Transactions.GetQuantity(private.contextItemString, SECONDS_PER_DAY * 30, private.itemDetailType))
)
)
:AddChild(UIElements.New("Frame", "avgPrice")
:SetLayout("HORIZONTAL")
:SetHeight(20)
:SetMargin(0, 0, 8, 0)
:AddChild(UIElements.New("Text", "label")
:SetMargin(0, 8, 0, 0)
:SetFont("BODY_BODY3")
:SetTextColor("TEXT_ALT")
:SetText(L["Average Prices:"])
)
:AddChild(UIElements.New("Text", "total")
:SetWidth(120)
:SetMargin(0, 8, 0, 0)
:SetFont("TABLE_TABLE1")
:SetJustifyH("RIGHT")
:SetText(Money.ToString(TSM.Accounting.Transactions.GetAveragePrice(private.contextItemString, nil, private.itemDetailType)))
)
:AddChild(UIElements.New("Text", "last7")
:SetWidth(120)
:SetMargin(0, 8, 0, 0)
:SetFont("TABLE_TABLE1")
:SetJustifyH("RIGHT")
:SetText(Money.ToString(TSM.Accounting.Transactions.GetAveragePrice(private.contextItemString, SECONDS_PER_DAY * 7, private.itemDetailType)))
)
:AddChild(UIElements.New("Text", "last30")
:SetWidth(120)
:SetFont("TABLE_TABLE1")
:SetJustifyH("RIGHT")
:SetText(Money.ToString(TSM.Accounting.Transactions.GetAveragePrice(private.contextItemString, SECONDS_PER_DAY * 30, private.itemDetailType)))
)
)
:AddChild(UIElements.New("Frame", "totalPrice")
:SetLayout("HORIZONTAL")
:SetHeight(20)
:SetMargin(0, 0, 8, 0)
:AddChild(UIElements.New("Text", "label")
:SetMargin(0, 8, 0, 0)
:SetFont("BODY_BODY3")
:SetTextColor("TEXT_ALT")
:SetText(L["Total Prices:"])
)
:AddChild(UIElements.New("Text", "total")
:SetWidth(120)
:SetMargin(0, 8, 0, 0)
:SetFont("TABLE_TABLE1")
:SetJustifyH("RIGHT")
:SetText(Money.ToString(TSM.Accounting.Transactions.GetTotalPrice(private.contextItemString, nil, private.itemDetailType)))
)
:AddChild(UIElements.New("Text", "last7")
:SetWidth(120)
:SetMargin(0, 8, 0, 0)
:SetFont("TABLE_TABLE1")
:SetJustifyH("RIGHT")
:SetText(Money.ToString(TSM.Accounting.Transactions.GetTotalPrice(private.contextItemString, SECONDS_PER_DAY * 7, private.itemDetailType)))
)
:AddChild(UIElements.New("Text", "last30")
:SetWidth(120)
:SetFont("TABLE_TABLE1")
:SetJustifyH("RIGHT")
:SetText(Money.ToString(TSM.Accounting.Transactions.GetTotalPrice(private.contextItemString, SECONDS_PER_DAY * 30, private.itemDetailType)))
)
)
:AddChild(UIElements.New("Frame", "top")
:SetLayout("HORIZONTAL")
:SetHeight(20)
:SetMargin(0, 0, 8, 0)
:AddChild(UIElements.New("Text", "label")
:SetWidth("AUTO")
:SetMargin(0, 8, 0, 0)
:SetFont("BODY_BODY3")
:SetTextColor("TEXT_ALT")
:SetText(private.itemDetailType == "sale" and L["Top Buyers"]..":" or L["Top Sellers"]..":")
)
:AddChild(UIElements.New("Text", "value")
:SetFont("BODY_BODY3")
:SetText(topPlayersText)
)
)
)
)
:AddChild(UIElements.New("QueryScrollingTable", "scrollingTable")
:SetSettingsContext(private.settings, "ledgerDetailScrollingTable")
:GetScrollingTableInfo()
:NewColumn("activityType")
:SetTitle(L["Activity Type"])
:SetFont("ITEM_BODY3")
:SetJustifyH("LEFT")
:SetTextInfo("type", private.TableGetActivityTypeText)
:Commit()
:NewColumn("source")
:SetTitle(L["Source"])
:SetFont("ITEM_BODY3")
:SetJustifyH("LEFT")
:SetTextInfo("source")
:Commit()
:NewColumn("buyerSeller")
:SetTitle(L["Buyer/Seller"])
:SetFont("ITEM_BODY3")
:SetJustifyH("LEFT")
:SetTextInfo("otherPlayer")
:Commit()
:NewColumn("qty")
:SetTitle(L["Qty"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo("quantity")
:Commit()
:NewColumn("perItem")
:SetTitle(L["Per Item"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo(nil, private.TableGetPerItemText)
:Commit()
:NewColumn("totalPrice")
:SetTitle(L["Total Price"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo(nil, private.TableGetTotalPriceText)
:Commit()
:NewColumn("time")
:SetTitle(L["Time"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo("time", private.TableGetTimeframeText)
:Commit()
:Commit()
:SetQuery(query)
:SetAutoReleaseQuery(true)
:SetSelectionDisabled(true)
:SetScript("OnRowClick", private.ItemDetailScrollingTableOnRowClick)
)
end
function private.ItemDetailBackButtonOnClick(button)
button:GetParentElement():GetParentElement():GetParentElement():GetParentElement():SetPath(private.contextPath, true)
end
function private.ItemDetailTabOnClick(button)
private.itemDetailType = button:GetContext()
button:GetParentElement():GetParentElement():GetParentElement():GetParentElement():GetParentElement():ReloadContent()
end
function private.ItemDetailScrollingTableOnRowClick(scrollingTable, row, button)
if button ~= "RightButton" then
return
elseif not TSM.Accounting.Transactions.CanDeleteByUUID(row:GetUUID()) then
Log.PrintUser(L["This record belongs to another account and can only be deleted on that account."])
return
end
local subtitle = nil
local recordType, itemString, quantity, otherPlayer, price = row:GetFields("type", "itemString", "quantity", "otherPlayer", "price")
local name = TSM.UI.GetColoredItemName(itemString) or "?"
local amount = Money.ToString(price * quantity)
if recordType == "sale" then
subtitle = format(L["Sold %d of %s to %s for %s"], quantity, name, otherPlayer, amount)
elseif recordType == "buy" then
subtitle = format(L["Bought %d of %s from %s for %s"], quantity, name, otherPlayer, amount)
else
error("Unexpected Type: "..tostring(recordType))
end
scrollingTable:GetBaseElement():ShowConfirmationDialog(L["Delete Record?"], subtitle, private.DeleteRecordConfirmed, row:GetUUID())
end
function private.DeleteRecordConfirmed(uuid)
TSM.Accounting.Transactions.RemoveRowByUUID(uuid)
end
-- ============================================================================
-- Scrolling Table Helper Functions
-- ============================================================================
function private.TableGetActivityTypeText(recordType)
if recordType == "sale" then
return L["Sale"]
elseif recordType == "buy" then
return L["Buy"]
else
error("Unexpected Type: "..tostring(recordType))
end
end
function private.TableGetTimeframeText(timestamp)
return SecondsToTime(time() - timestamp)
end
function private.TableGetTotalPriceText(row)
return Money.ToString(row:GetField("price") * row:GetField("quantity"))
end
function private.TableGetPerItemText(row)
return Money.ToString(row:GetField("price"))
end

View File

@@ -0,0 +1,23 @@
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
local _, TSM = ...
local Expenses = TSM.MainUI.Ledger:NewPackage("Expenses")
local L = TSM.Include("Locale").GetTable()
-- ============================================================================
-- Module Functions
-- ============================================================================
function Expenses.OnInitialize()
TSM.MainUI.Ledger.RegisterPage(L["Expenses"])
end
function Expenses.RegisterPage(name, callback)
TSM.MainUI.Ledger.RegisterChildPage(L["Expenses"], name, callback)
end

View File

@@ -0,0 +1,23 @@
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
local _, TSM = ...
local FailedAuctions = TSM.MainUI.Ledger:NewPackage("FailedAuctions")
local L = TSM.Include("Locale").GetTable()
-- ============================================================================
-- Module Functions
-- ============================================================================
function FailedAuctions.OnInitialize()
TSM.MainUI.Ledger.RegisterPage(L["Failed Auctions"])
end
function FailedAuctions.RegisterPage(name, callback)
TSM.MainUI.Ledger.RegisterChildPage(L["Failed Auctions"], name, callback)
end

View File

@@ -0,0 +1,329 @@
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
local _, TSM = ...
local Inventory = TSM.MainUI.Ledger:NewPackage("Inventory")
local L = TSM.Include("Locale").GetTable()
local TempTable = TSM.Include("Util.TempTable")
local Money = TSM.Include("Util.Money")
local String = TSM.Include("Util.String")
local Math = TSM.Include("Util.Math")
local Database = TSM.Include("Util.Database")
local ItemInfo = TSM.Include("Service.ItemInfo")
local CustomPrice = TSM.Include("Service.CustomPrice")
local BagTracking = TSM.Include("Service.BagTracking")
local GuildTracking = TSM.Include("Service.GuildTracking")
local AuctionTracking = TSM.Include("Service.AuctionTracking")
local MailTracking = TSM.Include("Service.MailTracking")
local AltTracking = TSM.Include("Service.AltTracking")
local InventoryService = TSM.Include("Service.Inventory")
local Settings = TSM.Include("Service.Settings")
local UIElements = TSM.Include("UI.UIElements")
local private = {
settings = nil,
db = nil,
query = nil,
searchFilter = "",
groupFilter = {},
valuePriceSource = "dbmarket", -- luacheck: ignore 1005 - hidden modify via SetSettingInfo()
}
-- ============================================================================
-- Module Functions
-- ============================================================================
function Inventory.OnInitialize()
private.settings = Settings.NewView()
:AddKey("global", "mainUIContext", "ledgerInventoryScrollingTable")
TSM.MainUI.Ledger.RegisterPage(L["Inventory"], private.DrawInventoryPage)
end
function Inventory.OnEnable()
private.db = Database.NewSchema("LEDGER_INVENTORY")
:AddUniqueStringField("itemString")
:Commit()
private.query = private.db:NewQuery()
:VirtualField("bagQuantity", "number", BagTracking.GetBagsQuantityByBaseItemString, "itemString")
:VirtualField("guildQuantity", "number", private.GuildQuantityVirtualField, "itemString")
:VirtualField("auctionQuantity", "number", AuctionTracking.GetQuantityByBaseItemString, "itemString")
:VirtualField("mailQuantity", "number", MailTracking.GetQuantityByBaseItemString, "itemString")
:VirtualField("altQuantity", "number", AltTracking.GetQuantityByBaseItemString, "itemString")
:VirtualField("totalQuantity", "number", private.TotalQuantityVirtualField)
:VirtualField("totalValue", "number", private.TotalValueVirtualField)
:VirtualField("totalBankQuantity", "number", private.GetTotalBankQuantity)
:InnerJoin(ItemInfo.GetDBForJoin(), "itemString")
:LeftJoin(TSM.Groups.GetItemDBForJoin(), "itemString")
:OrderBy("name", true)
end
-- ============================================================================
-- Inventory UI
-- ============================================================================
function private.DrawInventoryPage()
TSM.UI.AnalyticsRecordPathChange("main", "ledger", "inventory")
local items = TempTable.Acquire()
for _, itemString in BagTracking.BaseItemIterator() do
items[itemString] = true
end
for _, itemString in GuildTracking.BaseItemIterator() do
items[itemString] = true
end
for _, itemString in AuctionTracking.BaseItemIterator() do
items[itemString] = true
end
for _, itemString in MailTracking.BaseItemIterator() do
items[itemString] = true
end
for _, itemString in AltTracking.BaseItemIterator() do
items[itemString] = true
end
private.db:TruncateAndBulkInsertStart()
for itemString in pairs(items) do
private.db:BulkInsertNewRow(itemString)
end
private.db:BulkInsertEnd()
TempTable.Release(items)
private.UpdateQuery()
return UIElements.New("Frame", "content")
:SetLayout("VERTICAL")
:AddChild(UIElements.New("Frame", "row1")
:SetLayout("HORIZONTAL")
:SetHeight(24)
:SetMargin(8)
:AddChild(UIElements.New("Input", "filter")
:SetMargin(0, 8, 0, 0)
:SetIconTexture("iconPack.18x18/Search")
:SetClearButtonEnabled(true)
:AllowItemInsert()
:SetHintText(L["Filter by keyword"])
:SetValue(private.searchFilter)
:SetScript("OnValueChanged", private.SearchFilterChanged)
)
:AddChild(UIElements.New("GroupSelector", "group")
:SetWidth(240)
:SetHintText(L["Filter by groups"])
:SetScript("OnSelectionChanged", private.GroupFilterChanged)
)
)
:AddChild(UIElements.New("Frame", "row2")
:SetLayout("HORIZONTAL")
:SetHeight(24)
:SetMargin(8, 8, 0, 8)
:AddChild(UIElements.New("Text", "label")
:SetWidth("AUTO")
:SetFont("BODY_BODY3")
:SetText(L["Value Price Source"])
)
:AddChild(UIElements.New("Input", "input")
:SetMargin(4, 8, 0, 0)
:SetBackgroundColor("PRIMARY_BG_ALT")
:SetBorderColor("ACTIVE_BG")
:SetFont("TABLE_TABLE1")
:SetValidateFunc("CUSTOM_PRICE")
:SetSettingInfo(private, "valuePriceSource")
:SetScript("OnValueChanged", private.FilterChangedCommon)
)
:AddChild(UIElements.New("Frame", "value")
:SetLayout("HORIZONTAL")
:SetWidth(240)
:AddChild(UIElements.New("Spacer", "spacer"))
:AddChild(UIElements.New("Text", "label")
:SetWidth("AUTO")
:SetFont("BODY_BODY3")
:SetMargin(0, 4, 0, 0)
:SetText(L["Total Value"]..":")
)
:AddChild(UIElements.New("Text", "value")
:SetWidth("AUTO")
:SetFont("TABLE_TABLE1")
:SetText(Money.ToString(private.GetTotalValue()))
)
)
)
:AddChild(UIElements.New("Frame", "accountingScrollingTableFrame")
:SetLayout("VERTICAL")
:AddChild(UIElements.New("QueryScrollingTable", "scrollingTable")
:SetSettingsContext(private.settings, "ledgerInventoryScrollingTable")
:GetScrollingTableInfo()
:NewColumn("item")
:SetTitle(L["Item"])
:SetFont("ITEM_BODY3")
:SetJustifyH("LEFT")
:SetTextInfo("itemString", TSM.UI.GetColoredItemName)
:SetTooltipInfo("itemString")
:SetSortInfo("name")
:DisableHiding()
:Commit()
:NewColumn("totalItems")
:SetTitle(L["Total"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo("totalQuantity")
:SetSortInfo("totalQuantity")
:Commit()
:NewColumn("bags")
:SetTitle(L["Bags"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo("bagQuantity")
:SetSortInfo("bagQuantity")
:Commit()
:NewColumn("banks")
:SetTitle(L["Banks"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo("totalBankQuantity")
:SetSortInfo("totalBankQuantity")
:Commit()
:NewColumn("mail")
:SetTitle(L["Mail"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo("mailQuantity")
:SetSortInfo("mailQuantity")
:Commit()
:NewColumn("alts")
:SetTitle(L["Alts"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo("altQuantity")
:SetSortInfo("altQuantity")
:Commit()
:NewColumn("guildVault")
:SetTitle(L["GVault"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo("guildQuantity")
:SetSortInfo("guildQuantity")
:Commit()
:NewColumn("auctionHouse")
:SetTitle(L["AH"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo("auctionQuantity")
:SetSortInfo("auctionQuantity")
:Commit()
:NewColumn("totalValue")
:SetTitle(L["Value"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo("totalValue", private.TableGetTotalValueText)
:SetSortInfo("totalValue")
:Commit()
:Commit()
:SetSelectionDisabled(true)
:SetQuery(private.query)
)
)
end
-- ============================================================================
-- Local Script Handlers
-- ============================================================================
function private.FilterChangedCommon(element)
private.UpdateQuery()
element:GetElement("__parent.__parent.accountingScrollingTableFrame.scrollingTable")
:SetQuery(private.query, true)
element:GetElement("__parent.__parent.row2.value.value")
:SetText(Money.ToString(private.GetTotalValue()))
:Draw()
end
function private.SearchFilterChanged(input)
private.searchFilter = input:GetValue()
private.FilterChangedCommon(input)
end
function private.GroupFilterChanged(groupSelector)
wipe(private.groupFilter)
for groupPath in groupSelector:SelectedGroupIterator() do
private.groupFilter[groupPath] = true
end
private.FilterChangedCommon(groupSelector)
end
-- ============================================================================
-- Scrolling Table Helper Functions
-- ============================================================================
function private.TableGetTotalValueText(totalValue)
return Math.IsNan(totalValue) and "" or Money.ToString(totalValue)
end
-- ============================================================================
-- Private Helper Functions
-- ============================================================================
function private.GuildQuantityVirtualField(itemString)
local totalNum = 0
for guildName in pairs(TSM.db.factionrealm.internalData.guildVaults) do
local guildQuantity = InventoryService.GetGuildQuantity(itemString, guildName)
totalNum = totalNum + guildQuantity
end
return totalNum
end
function private.TotalQuantityVirtualField(row)
local bagQuantity, totalBankQuantity, guildQuantity, auctionQuantity, mailQuantity, altQuantity = row:GetFields("bagQuantity", "totalBankQuantity", "guildQuantity", "auctionQuantity", "mailQuantity", "altQuantity")
return bagQuantity + totalBankQuantity + guildQuantity + auctionQuantity + mailQuantity + altQuantity
end
function private.TotalValueVirtualField(row)
local itemString, totalQuantity = row:GetFields("itemString", "totalQuantity")
local price = CustomPrice.GetValue(private.valuePriceSource, itemString)
if not price then
return Math.GetNan()
end
return price * totalQuantity
end
function private.GetTotalBankQuantity(row)
local itemString = row:GetField("itemString")
local bankQuantity = BagTracking.GetBankQuantityByBaseItemString(itemString)
local reagentBankQuantity = BagTracking.GetReagentBankQuantityByBaseItemString(itemString)
return bankQuantity + reagentBankQuantity
end
function private.GetTotalValue()
-- can't lookup the value of items while the query is iteratoring, so grab the list of items first
local itemQuantities = TempTable.Acquire()
for _, row in private.query:Iterator() do
local itemString, total = row:GetFields("itemString", "totalQuantity")
itemQuantities[itemString] = total
end
local totalValue = 0
for itemString, total in pairs(itemQuantities) do
local price = CustomPrice.GetValue(private.valuePriceSource, itemString)
if price then
totalValue = totalValue + price * total
end
end
TempTable.Release(itemQuantities)
return totalValue
end
function private.UpdateQuery()
private.query:ResetFilters()
if private.searchFilter ~= "" then
private.query:Matches("name", String.Escape(private.searchFilter))
end
if next(private.groupFilter) then
private.query:InTable("groupPath", private.groupFilter)
end
end

View File

@@ -0,0 +1,23 @@
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
local _, TSM = ...
local Revenue = TSM.MainUI.Ledger:NewPackage("Revenue")
local L = TSM.Include("Locale").GetTable()
-- ============================================================================
-- Module Functions
-- ============================================================================
function Revenue.OnInitialize()
TSM.MainUI.Ledger.RegisterPage(L["Revenue"])
end
function Revenue.RegisterPage(name, callback)
TSM.MainUI.Ledger.RegisterChildPage(L["Revenue"], name, callback)
end

View File

@@ -0,0 +1,299 @@
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
local _, TSM = ...
local Resale = TSM.MainUI.Ledger.Revenue:NewPackage("Resale")
local L = TSM.Include("Locale").GetTable()
local Table = TSM.Include("Util.Table")
local Money = TSM.Include("Util.Money")
local Theme = TSM.Include("Util.Theme")
local ItemInfo = TSM.Include("Service.ItemInfo")
local Settings = TSM.Include("Service.Settings")
local UIElements = TSM.Include("UI.UIElements")
local SECONDS_PER_DAY = 24 * 60 * 60
local private = {
settings = nil,
summaryQuery = nil,
characters = {},
characterFilter = {},
typeFilter = {},
rarityList = {},
rarityFilter = {},
groupFilter = {},
searchFilter = "",
timeFrameFilter = 30 * SECONDS_PER_DAY
}
local TYPE_LIST = { L["Auction"], COD, TRADE, L["Vendor"] }
local TYPE_KEYS = { "Auction", "COD", "Trade", "Vendor" }
do
for _, key in ipairs(TYPE_KEYS) do
private.typeFilter[key] = true
end
for i = 1, 4 do
tinsert(private.rarityList, _G[format("ITEM_QUALITY%d_DESC", i)])
private.rarityFilter[i] = true
end
end
local TIME_LIST = { L["All Time"], L["Last 3 Days"], L["Last 7 Days"], L["Last 14 Days"], L["Last 30 Days"], L["Last 60 Days"] }
local TIME_KEYS = { 0, 3 * SECONDS_PER_DAY, 7 * SECONDS_PER_DAY, 14 * SECONDS_PER_DAY, 30 * SECONDS_PER_DAY, 60 * SECONDS_PER_DAY }
-- ============================================================================
-- Module Functions
-- ============================================================================
function Resale.OnInitialize()
private.settings = Settings.NewView()
:AddKey("global", "mainUIContext", "ledgerResaleScrollingTable")
TSM.MainUI.Ledger.Revenue.RegisterPage(L["Resale"], private.DrawResalePage)
end
-- ============================================================================
-- Resale UI
-- ============================================================================
function private.DrawResalePage()
TSM.UI.AnalyticsRecordPathChange("main", "ledger", "revenue", "resale")
wipe(private.characters)
TSM.Accounting.Transactions.GetCharacters(private.characters)
for _, character in ipairs(private.characters) do
private.characterFilter[character] = true
end
private.summaryQuery = private.summaryQuery or TSM.Accounting.Transactions.CreateSummaryQuery()
:InnerJoin(ItemInfo.GetDBForJoin(), "itemString")
:OrderBy("name", true)
private.UpdateQuery()
local totalProfit = 0
local numItems = 0
for _, row in private.summaryQuery:Iterator() do
totalProfit = totalProfit + row:GetField("totalProfit")
numItems = numItems + min(row:GetFields("sold", "bought"))
end
return UIElements.New("Frame", "content")
:SetLayout("VERTICAL")
:AddChild(UIElements.New("Frame", "row1")
:SetLayout("HORIZONTAL")
:SetHeight(24)
:SetMargin(8)
:AddChild(UIElements.New("Input", "filter")
:SetMargin(0, 8, 0, 0)
:SetIconTexture("iconPack.18x18/Search")
:SetClearButtonEnabled(true)
:AllowItemInsert()
:SetHintText(L["Filter by keyword"])
:SetValue(private.searchFilter)
:SetScript("OnValueChanged", private.SearchFilterChanged)
)
:AddChild(UIElements.New("GroupSelector", "group")
:SetWidth(240)
:SetHintText(L["Filter by groups"])
:SetScript("OnSelectionChanged", private.GroupFilterChanged)
)
)
:AddChild(UIElements.New("Frame", "row2")
:SetLayout("HORIZONTAL")
:SetHeight(24)
:SetMargin(8, 8, 0, 8)
:AddChild(UIElements.New("MultiselectionDropdown", "type")
:SetMargin(0, 8, 0, 0)
:SetItems(TYPE_LIST, TYPE_KEYS)
:SetSettingInfo(private, "typeFilter")
:SetSelectionText(L["No Types"], L["%d Types"], L["All Types"])
:SetScript("OnSelectionChanged", private.FilterChangedCommon)
)
:AddChild(UIElements.New("MultiselectionDropdown", "rarity")
:SetMargin(0, 8, 0, 0)
:SetItems(private.rarityList)
:SetSettingInfo(private, "rarityFilter")
:SetSelectionText(L["No Rarities"], L["%d Rarities"], L["All Rarities"])
:SetScript("OnSelectionChanged", private.FilterChangedCommon)
)
:AddChild(UIElements.New("MultiselectionDropdown", "character")
:SetMargin(0, 8, 0, 0)
:SetItems(private.characters, private.characters)
:SetSettingInfo(private, "characterFilter")
:SetSelectionText(L["No Characters"], L["%d Characters"], L["All Characters"])
:SetScript("OnSelectionChanged", private.FilterChangedCommon)
)
:AddChild(UIElements.New("SelectionDropdown", "time")
:SetItems(TIME_LIST, TIME_KEYS)
:SetSelectedItemByKey(private.timeFrameFilter)
:SetSettingInfo(private, "timeFrameFilter")
:SetScript("OnSelectionChanged", private.FilterChangedCommon)
)
)
:AddChild(UIElements.New("QueryScrollingTable", "scrollingTable")
:SetSettingsContext(private.settings, "ledgerResaleScrollingTable")
:GetScrollingTableInfo()
:NewColumn("item")
:SetTitle(L["Item"])
:SetFont("ITEM_BODY3")
:SetJustifyH("LEFT")
:SetTextInfo("itemString", TSM.UI.GetColoredItemName)
:SetSortInfo("name")
:SetTooltipInfo("itemString")
:DisableHiding()
:Commit()
:NewColumn("bought")
:SetTitle(L["Bought"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo("bought")
:SetSortInfo("bought")
:Commit()
:NewColumn("avgBuyPrice")
:SetTitle(L["Avg Buy Price"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo("avgBuyPrice", private.GetMoneyText)
:SetSortInfo("avgBuyPrice")
:Commit()
:NewColumn("sold")
:SetTitle(L["Sold"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo("sold")
:SetSortInfo("sold")
:Commit()
:NewColumn("avgSellPrice")
:SetTitle(L["Avg Sell Price"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo("avgSellPrice", private.GetMoneyText)
:SetSortInfo("avgSellPrice")
:Commit()
:NewColumn("avgProfit")
:SetTitle(L["Avg Profit"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo("avgProfit", private.GetColoredMoneyText)
:SetSortInfo("avgProfit")
:Commit()
:NewColumn("totalProfit")
:SetTitle(L["Total Profit"])
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo("totalProfit", private.GetColoredMoneyText)
:SetSortInfo("totalProfit")
:Commit()
:NewColumn("profitPct")
:SetTitle("%")
:SetFont("ITEM_BODY3")
:SetJustifyH("RIGHT")
:SetTextInfo("profitPct", private.GetPctText)
:SetSortInfo("profitPct")
:Commit()
:Commit()
:SetQuery(private.summaryQuery)
:SetScript("OnRowClick", private.TableSelectionChanged)
)
:AddChild(UIElements.New("Texture", "line")
:SetHeight(2)
:SetTexture("ACTIVE_BG")
)
:AddChild(UIElements.New("Frame", "footer")
:SetLayout("HORIZONTAL")
:SetHeight(40)
:SetPadding(8)
:SetBackgroundColor("PRIMARY_BG")
:AddChild(UIElements.New("Text", "num")
:SetWidth("AUTO")
:SetFont("BODY_BODY2_MEDIUM")
:SetText(format(L["%s Items Resold"], Theme.GetColor("INDICATOR"):ColorText(FormatLargeNumber(numItems))))
)
:AddChild(UIElements.New("Texture", "line")
:SetMargin(4, 8, 0, 0)
:SetWidth(2)
:SetTexture("ACTIVE_BG")
)
:AddChild(UIElements.New("Text", "profit")
:SetWidth("AUTO")
:SetFont("BODY_BODY2_MEDIUM")
:SetText(format(L["%s Total Profit"], Money.ToString(totalProfit)))
)
:AddChild(UIElements.New("Spacer", "spacer"))
)
end
-- ============================================================================
-- Scrolling Table Helper Functions
-- ============================================================================
function private.GetMoneyText(value)
return Money.ToString(value)
end
function private.GetColoredMoneyText(value)
return Money.ToString(value, Theme.GetFeedbackColor(value >= 0 and "GREEN" or "RED"):GetTextColorPrefix())
end
function private.GetPctText(value)
return Theme.GetFeedbackColor(value >= 0 and "GREEN" or "RED"):ColorText(value.."%")
end
-- ============================================================================
-- Local Script Handlers
-- ============================================================================
function private.FilterChangedCommon(dropdown)
private.UpdateQuery()
local totalProfit = 0
local numItems = 0
for _, row in private.summaryQuery:Iterator() do
totalProfit = totalProfit + row:GetField("totalProfit")
numItems = numItems + min(row:GetFields("sold", "bought"))
end
dropdown:GetElement("__parent.__parent.scrollingTable"):UpdateData(true)
local footer = dropdown:GetElement("__parent.__parent.footer")
footer:GetElement("num"):SetText(format(L["%s Items Resold"], Theme.GetColor("INDICATOR"):ColorText(FormatLargeNumber(numItems))))
footer:GetElement("profit"):SetText(format(L["%s Total Profit"], Money.ToString(totalProfit)))
footer:Draw()
end
function private.SearchFilterChanged(input)
private.searchFilter = input:GetValue()
private.FilterChangedCommon(input)
end
function private.GroupFilterChanged(groupSelector)
wipe(private.groupFilter)
for groupPath in groupSelector:SelectedGroupIterator() do
private.groupFilter[groupPath] = true
end
private.FilterChangedCommon(groupSelector)
end
-- ============================================================================
-- Private Helper Functions
-- ============================================================================
function private.UpdateQuery()
private.summaryQuery:ResetFilters()
local groupFilter = next(private.groupFilter) and private.groupFilter or nil
local searchFilter = private.searchFilter ~= "" and private.searchFilter or nil
local typeFilter = Table.Count(private.typeFilter) ~= #TYPE_KEYS and private.typeFilter or nil
local characterFilter = Table.Count(private.characterFilter) ~= #private.characters and private.characterFilter or nil
local minTime = private.timeFrameFilter ~= 0 and (time() - private.timeFrameFilter) or nil
TSM.Accounting.Transactions.UpdateSummaryData(groupFilter, searchFilter, typeFilter, characterFilter, minTime)
if Table.Count(private.rarityFilter) ~= #private.rarityList then
private.summaryQuery:InTable("quality", private.rarityFilter)
end
end
function private.TableSelectionChanged(scrollingTable, row)
TSM.MainUI.Ledger.ShowItemDetail(scrollingTable:GetParentElement():GetParentElement(), row:GetField("itemString"), "sale")
end