Gnucash Lots?

Linas Vepstas linas@linas.org
Thu, 23 May 2002 12:50:37 -0500


On Wed, May 22, 2002 at 08:31:24PM -0400, Derek Atkins was heard to remark:
> linas@linas.org (Linas Vepstas) writes:
> 
> > My example ws for a 'typical' invoice, and they tyupically have a
> > balance due and sometimes other subtotals showing (e.g. balances before
> > a discount).
> 
> Hmm, honestly I could never see how this would be useful..  To me, I
> can see a customer account summary, or showing an individual invoice
> to show what was done at a particular time, but a combination of the
> two, like you seem to be proposing, just doesn't make sense to me.

To you, or to the customer? 
-- I did not mean to propose to change your gui.
-- The utility opf having various totals and subtotals on a page allows
   you and/or the customer have an easier job of visually reconciling
   it against other scraps of paper.   Remeber, the other party won't
   have access to your books.
   (Althought this leads to another *very* interesting/revolutionary thing 
   I tripped over, a kind of P2P secure, verifiable accounting system.
   But that's a whole nother topic.)

-- The point of showing totals before discount is, I think, mostly
   an advertising gimmick, a kind of "see this is how much you saved by
   shopping with us" thing.

> We had this dicussion about 6 months ago, however I will reiterate
> my reasons here.
> 
> 1) Entries need to be tied to both Invoices and Orders, which means
>    you need multiple pointers.  Both of these would have to be stored
>    in kvp entries in the Split.

Let me be thick-headed/lazy. What's an 'order'?

> 2) Splits want to be tied to an account, but I don't want to touch any
>    accounts until you post the invoice.  This means you would need to
>    store the account information in a KVP until you actually post.

Hmm. So if I understand correctly, you can start creating an invoice
one one day, stop, save, shut down gnucash, come back another day,
continue editing the invoice, and post sometime later?  

This kind of feals like a "shopping cart", where nothing is 'posted'
until the shopper "checks out" ... right?

What's really the real-world example of needing this feature?

> In other words, almost ALL the information would be stored in the kvp
> of a Split, if Splits were being used.  Very little information would
> actually be stored in the Split itself.  

That's OK, that was the intent of adding KVP's in general: an extension
mechanism ...

> When you wanted to search for
> an Entry, it would make it much harder if you had to search by KVP.

Ah-ha!  Searching is hard!

Do we need to generalize query?

Would the following routine be useful?

Split * find_split_where_kvp_value_equals (GList *splits, 
                          char * key, kvp_value * match_value)
{
   for (n=splits; n; n=n->next)
   {
     kvp_frame = ((Split *)n->data)->kvp_data;
     val = kvp_get_value (kvp_frame, key);
     if (kvp_equal (match_value, val) return ((Split *) n->data);
   }
}

Or at least a query-generalized version of the above?
-----------
The theory of kvp was that they would be good enough for general
extension tasks, and you are telling me that it didn't pass that test,
and so I now want to understand why.


> > I assume "post" translates into xaccTransCommitEdit(), right?
> > (because posting is what it was designed to do ... unless we are working
> > with different definitions of what "post" means, and, if so, I'd like
> > to figure that out now, rather than later ...
> 
> Well, yes, but xaccTransCommitEdit() is not the same as
> gncEntryCommitEdit().  The issue is that I necessarily want invoice
> items to remain out of your Chart of Accounts until the end, when you
> actually post it.  In other words, you collect the items on an
> invoice, but it's not actually moving money in your accounts until you
> click "Post Invoice".  When I say "post an Invoice", what I mean is a
> call to gncInvoicePostToAccount() which does the following:
> 
> - walk through each entry in the invoice
> - for each entry:
>   - determine the entry's value and tax value
>   - determine the account and add the value to the temporary
>     storage tied to the account
>   - determine the tax account add add the tax value to the temporary
>     storage tied to the tax account
>   - keep a running total
> - create a new Transaction
> - walk through the list of seen accounts.
> - for each seen account, create a split with the sum of values
> - create a split for the total invoice
> - commit this transaction.

:-(

I also don't understand why you did this; it seems to be causing you to 
reinvent engine features, and reinvent the ledger display ...

Naively, I would have thought that it would have been enough to just
make all of the transfers be ordinary transactions, working between
accounts in a 'pending orders' account subtree.
Days or months later, when the customer commits, you'd have a transfer
from 'pending' to 'actual' (either by creating a new transaction between
'pending' and 'actual', or by reparenting the splits from the 'pending'
subtree to the 'actual' subtree.  If the customer cancels, you could 
void out the pending order or delete it outright.  None of this would 
require a reinvention of the core objects (and maybe thereby avoided 
at least some of your storage problems?)

I guess I'm saying that the core engine objects (accounts, etc.)
were really meant to be powerful, general tools.   Unfortunately
they're a bit straight-jacketed by the GUI, which makes specific
assumptions that limits the utility of accounts, etc.  But the answer
that would be 'fix the gui', rather than 'reinvent the engine'.


> Unfortunately it is a lot of lines of code, because there are no
> Splits in the Invoices (and no SplitRegister in the Invoice Window).

:-(

> See above:  no Splits, no SplitRegister in the Invoice Window.

:-(

> No, there is too much information in the Invoice.  The Invoice really
> is tied to the transaction that is posted, not the Lot.

Well, you still have to have the invoice point at the lot.  A
transaction might be associated with multiple lots.

I presume that someday, you'll be able to manage inventory, in which
case the splits in the transaction will be parts of different lots.
In the paint example, they're will be a a split that belongs to the 
'paint' lot, that debits the amount of paint in the warehouse. 
You don't want to confuse that lot with the lot that encapsulates 
the charge for that paint (which would be in the same transaction).


> > > Except that Invoices don't use Splits.  There is a completely separate
> > > storage mechanism for Invoice line-items, because they need to exist
> > > outside the Account hierarchy 
> > 
> > Why?  I suspect/am hoping there's a 'deep' reason, not just a whim ...
> 
> See above.

Well, I still don't see the reason.  You point out that you didn't map
things onto splits, bbut you didn't explain why (other than stating that
searching would be hard; but that seems fixable ... )

> I tried using Splits.  It turns out that about 75% of the information
> I needed wasn't available in a Split, and would need to be stored in
> the kvp.  When that much information needs to be stored elsewhere, it
> certainly sounds like "I've got this hammer" syndrome to me.

No. Yes. This is *exactly* the reason that kvp is there.   iIt was
designed to have this syndrome.  The long term goal was to store 
90% or 100% of all information in kvp (i.e. even move some of the stuff
currently in the C structs to kvp instead.).  (And get rid of some of
the API routines, like 'xaccSplitGetMemo()', and replace it with 
a statement that the programmer should just look for the "memo"
kvp element on the split.)  The idea was 
that the base objects would be bags of pointers, these hard-wired 
relational structures, which serve only to make searching
and linking and associating easy.  But anything thats just plain
'data', e.g. strings, values, would be in kvp.   Some low-priority
pointers (i.e. guid's) would go in kvp as well.   e.g Books stuff 
certain guid's into kvp; these guids are 'unusual' enough that they 
didn't merit a hard link in a C struct.

That is certainly how I'm designing the lot. Its this skinny thing, with
almost nothing in it.  It sole data interface is the kvp, it stores no
other data at all. 

Now, moving all data to kvp is a kind of philosphical bent, I'm still
not clear on just how good an idea that would be. So I should add
disclaimers that the true benefit of this is uncertain ... But at the
moment, it does seem like a good idea ...

--linas


-- 
pub  1024D/01045933 2001-02-01 Linas Vepstas (Labas!) <linas@linas.org>
PGP Key fingerprint = 8305 2521 6000 0B5E 8984  3F54 64A9 9A82 0104 5933