0

Account flows

In the Accounts table, I have a view called Flows with the following script. It gives the correct dataset but would like to filter out from that dataset the selected account ledger line items (that is, xAccountId).

in other words, using another analogy, give me all products that a customer also purchased when they purchased Product X but do not list Product X.

"PURPOSE: SELECT ALL TRANSACTION LINE ITEMS WHERE JOURNAL ENTRY NUMBER EQUALS ALL JOURNAL ENTRY NUMBERS IN ACCOUNT";
let xAccountId := number(Id);
let xLedgerId := text(unique(concat((select Ledger)[Accounts.Id = xAccountId].Journal.Id)));
(select Ledger)[contains(xLedgerId, text(Journal.Id))]

52 replies

null
    • Fred
    • 4 mths ago
    • Reported - view
     said:
    Not working yet.

     Can you write out an example using the records in your DB?

    When I use Alain's example in your view in the Flow tab of the Groceries record (Account Id = 731)  it seems to work for me.

      • Fred
      • 4 mths ago
      • Reported - view

      Can you add the DrCr field as a column then you can use the Column sum feature?

      • Erik_Ivan_Bech
      • 4 mths ago
      • Reported - view

       Yes, that is what I do now. However, I would like a column that shows a running total after each ledger line item, as your monthly bank account statement from your bank would show. If the ledger line items are sorted by date and then by Id, the running total should display the accumulated sum of the DrCr column. The ending running balance should agree to the sum of the DrCr, as you mentioned. 

      • Fred
      • 4 mths ago
      • Reported - view
       said:
      I would like a column that shows a running total after each ledger line item

      Currently the DrCr field in the Ledger table is a formula field that converts the data in the Amount field into a positive or negative value.

      Forgive my lack of knowledge of accounting, I am unsure what do you trying to sum. At the Ledger table there is no 1:N link to another table to sum.

      • Erik_Ivan_Bech
      • 4 mths ago
      • Reported - view

       In the accounts table ledger view, it shows the ledger line items for the selected account. This view includes the DrCr column with a sum at the bottom of that column. This sum is the account’s balance (assuming no filters are put on the date column). I would like a running total of the account balance on each ledger line item. That is, the accumulated sum of a ledger line item for that date and prior. 

      For example, 

      Date                 DrCr  Balance

      2023-11-15     1.00         1.00

      2023-11-21     3.50         4.50

      2023-11-29   -2.75          1.75

      Sum                 1.75

      By the way, the DrCr column represents positive amounts are debits. Negative amounts are credits. 

      The balance needs to recalculate if a new journal entry is subsequently entered which is back-dated, or an existing entry is edited.

    • Fred
    • 4 mths ago
    • Reported - view
      • Erik_Ivan_Bech
      • 4 mths ago
      • Reported - view

       I tried but didn’t work in the Accounts Ledger view as a calculated field called Balance

      let t := this;
      sum((select Ledger)[Date <= t.Date].DrCr)
       

    • Fred
    • 4 mths ago
    • Reported - view

    You can also put this in a formula column in the Ledger view element. This method is dependent on the view element being sort ascending by Journal.Date. If you sort by any other way the column will not make any sense.

    let curLedger := this;
    let relatedLedger := (select Ledger where Accounts = curLedger.Accounts);
    let olderLedger := relatedLedger[Journal.Date < curLedger.Journal.Date];
    let sameDateLedger := relatedLedger[Journal.Date = curLedger.Journal.Date];
    let final := if count(sameDateLedger) > 1 then
            array(olderLedger, sameDateLedger[number(Id) <= curLedger.number(Id)])
        else
            relatedLedger[Journal.Date <= curLedger.Journal.Date]
        end;
    sum(final.DrCr)
    

    When you have a view element you are working from that Table, so we are in the Ledger table even when are physically in the Accounts table.

    Line 1: set the variable curLedger to equal the record of the ledger record for each line.

    Line 2: finds all Ledger records that have matching Accounts and puts it in a variable.

    Line 3: takes the records in line 2 and finds all records that have a Journal.Data that is older than Journal.Date of the current record. Why only the Dates less than, what do you do if you have multiple entries with the same date?

    Line 4: takes the records in line 2 and filters for Journal.Date that equal the current record.

    Line 5: creates an if statement that checks to see if there are more than one result from line 4. If true then it will create a new array with the results from line 3 and combines it with records in line 4 that have a record Id that is lower than or equal to the current record. If not true then it takes the records form line 2 and filters by Journal.Date that is less than or equal to the current record Journal.Date. Then puts the results into a variable.

    Line 10: uses the sum() command to find the total of all DrCr in the found records from line 5.

      • Erik_Ivan_Bech
      • 4 mths ago
      • Reported - view

      Thank you very much indeed! Of course I meant to say re Line 3 that it’s less than or equal to, that’s what I meant by sorting by date and then by ledger Id so the balance is updated in the correct sequence of line items. I have changed line 3 to be <= instead of <. The view appears blank for about 30 seconds then it works. Slow.  Anyway to make it faster? My live database has over 100 accounts, 17k journal and 50k ledger records. 

      • Fred
      • 4 mths ago
      • Reported - view

      You can try this in another formula field.

      let curLedger := this;
      let relatedLedger := ((select Ledger where Accounts = curLedger.Accounts) order by Journal.Date);
      let curLedgerIndex := index(relatedLedger, curLedger);
      if curLedgerIndex = 0 then
          DrCr
      else
          item(relatedLedger, curLedgerIndex - 1).DrCr +
          item(relatedLedger, curLedgerIndex).DrCr
      end
      

      It still has a select statement but it ends up only with two records to sum so it might be faster. You can create a new formula field in Ledger and put that above in it. Then add that field as a column in your view element.

      • Fred
      • 4 mths ago
      • Reported - view

      oops, this doesn't work beyond two records. :)

    • Fred
    • 4 mths ago
    • Reported - view

    Ok take a look at the button in Accounts > Ledger tab.

    I've added a number field in Ledger called Balance and the button does the math for all related Ledger records.

    This can be scripted to set all of the Ledgers, but you should test it out first to make sure it does what is should. Stress test it by adding new records at the end. Or adding records that are back dated, etc.

      • Erik_Ivan_Bech
      • 4 mths ago
      • Reported - view

      Thank you very much indeed! Testing still in progress. How do I filter the records in the button so that Ledger.Fund lookup field value is = “BEB”? I have a fund field in the Journal table, since a fund can have many transactions and an account can have many funds. The Account Ledger view is filtered on the BEB fund and would like to run the button on this fund’s records and then do the same on the EIB fund. That way I have the correct account balance in the Balance field which currently is the combination of both the EIB and BEB funds. 

    • Fred
    • 4 mths ago
    • Reported - view

    If the button works you can put the following formula in the Trigger after update of the Amount field in Ledger:

    let t := this;
    let xLedger := (Accounts.Ledger order by Journal.Date);
    for loop1 in xLedger do
        let xLoc := index(xLedger, loop1);
        if xLoc = 0 then
            loop1.(Balance := loop1.DrCr)
        else
            loop1.(Balance := item(xLedger, xLoc - 1).Balance + loop1.DrCr)
        end
    end
    

    Hopefully with no select statement this will run without undue delay.

    • Fred
    • 4 mths ago
    • Reported - view
     said:
    How do I filter the records in the button so that Ledger.Fund lookup field value is = “BEB”?

    Easiest is: BEB = 2.

    let xLedger := ((Ledger where Journal.Fund = 2)order by Journal.Date);
    

    When I have time I can modify the whole script to take into account the different funds.

      • Erik_Ivan_Bech
      • 4 mths ago
      • Reported - view

       Not sure it will work as intended since an account can have more than one fund unless I have a separate Balance field for each fund. That is, a Balance for both funds combined, a Balance field for fund 1, and a Balance field for fund 2. 

      • Fred
      • 4 mths ago
      • Reported - view

      Do I need to reply to this or does the other button take care of this?

      • Erik_Ivan_Bech
      • 4 mths ago
      • Reported - view

       I have resolved the issue by deciding to copy the database so that each fund has their own database rather than two funds combined in one database. 

    • Fred
    • 4 mths ago
    • Reported - view

    I would upload a file, but v3.10.10 broke the Export to Ninox function of the MacOS app.

    You can put this in a new button in the Accounts table > Ledger tab:

    let xFund := unique(Ledger.Journal.Fund);
    for loop1 in xFund do
        let loopLedger := (Ledger[Journal.Fund = loop1] order by Journal.Date);
        for loop2 in loopLedger do
            let xLoc := index(loopLedger, loop2);
            if xLoc = 0 then
                loop2.(Balance := loop2.DrCr)
            else
                loop2.(Balance := item(loopLedger, xLoc - 1).Balance + loop2.DrCr)
            end
        end
    end

    Line 1 creates a unique array of the Funds associated with the Account.

    Line 2 starts a loop using the array in line 1.

    Line 3 filters the linked Ledger records to only have the Funds in the current loop then orders the results by Date.

    Line 4 starts a sub loop using the results from line 3.

    Line 5 - 9 are just the same as last time just modified to fit the new loop structure.

    You can then group the Ledger tab view element by Fund and see the results.

    Then you have to update the Trigger after update of the Amount field in the Ledger table to:

    let t := this;
    let xLedger := (Accounts.Ledger[Journal.Fund = t.Journal.Fund] order by Journal.Date);
    for loop1 in xLedger do
        let xLoc := index(xLedger, loop1);
        if xLoc = 0 then
            loop1.(Balance := loop1.DrCr)
        else
            loop1.(Balance := item(xLedger, xLoc - 1).Balance + loop1.DrCr)
        end
    end
      • Erik_Ivan_Bech
      • 4 mths ago
      • Reported - view

       Thank you very much indeed! How is that trigger after update supposed to update the Accounts ledger view? It doesn’t seem to update after adding a new journal entry unless I manually press the button. Do I need to press the button whenever there is a change to the Amount field?

      • Fred
      • 4 mths ago
      • Reported - view
       said:
      How is that trigger after update supposed to update the Accounts ledger view?

      It is on the Trigger after update of the Amount field so after you modify the field the trigger will run. Then the balance will show up wherever you display it. Since Amount is a number field, I thought you would manually enter the data. So that is where I put the trigger. If that is not your work flow then you can put it anywhere else.

      • Erik_Ivan_Bech
      • 4 mths ago
      • Reported - view

       it’s working now.  The balance field updated each time I revisit the accounts table ledger view. Amazing! Thank you very much indeed! 

      • Fred
      • 4 mths ago
      • Reported - view

      You are very welcome. When you get a chance please mark the post answered. Thanks,

      • Erik_Ivan_Bech
      • 4 mths ago
      • Reported - view

       if I want a balance field for the Accounts table Open view and Closed view, I basically need to create a separate Balance field for each in the ledger table like OpenBalance and ClosedBalance and have a corresponding script that filters on the Reconciled ledger field for null items and not null items?

      • Fred
      • 4 mths ago
      • Reported - view

       

       said:
      I basically need to create a separate Balance field for each in the ledger table like OpenBalance and ClosedBalance and have a corresponding script that filters on the Reconciled ledger field for null items and not null items?

       That is one way, or you can use the Balance field and then sort by Open/Closed then do the balance by that. I'm guessing a Ledger item can only be one or the other. Thus you can put it the Trigger after update for the Open/Closed. I don't know if you need it to run if Open, but definitely when you mark a record closed you would want it to run.

      Then you can either group the view by open/closed or do an open view and a closed view.

      • Erik_Ivan_Bech
      • 4 mths ago
      • Reported - view

       Am I able to export records from a view?

Content aside

  • Status Answered
  • 4 mths agoLast active
  • 52Replies
  • 330Views
  • 4 Following