===========================
Saturday, February 21, 2015
===========================


235 stale controllables
=======================

I am investigating what to do with the 235 stale controllables in Eupen.

.. currentmodule:: lino.modlib.contenttypes.models

In :mod:`lino.modlib.contenttypes`, I changed ``StaleControllables``
to :class:`StaleGenericRelateds` and ``StaleControllablesByModel`` to
:class:`StaleGenericRelatedByModel`. They no longer detect only stale
`owner` fields of :class:`Controllable` rows but any stale
GenericForeignKey field in the database.

Added a new test module for testing this table:
:mod:`test_stale_gfk <lino_welfare.projects.eupen.tests.test_stale_gfk>`.

Which made me discover that when I delete an object, Django *does*
automatically delete any objects which have a GenericForeignKey
pointing at it as well. Already in `1.6
<https://docs.djangoproject.com/en/5.2/ref/contrib/contenttypes/>`_.

So theoretically I can remove my custom :meth:`Model.delete
<lino.core.model.Model.delete>` method which did exactly that.
I have been reinventing the wheel once more.  And I am going to adapt
Lino to Django.  Yes (sigh!), that's the disadvantage of being a poor
lonesome codeboy.

One problem is that in Lino you can configure the cascading behaviour
using the :attr:`allow_stale_generic_foreignkey
<lino.core.model.Model.allow_stale_generic_foreignkey>`.  Okay, in
Django you can write a pre_delete signal.

Another problem is that in Lino you can inform the user and ask for
confirmation before deleting them.

Another problem is that in Django this automatism happens only if the
object being deleted has a `GenericRelation
<https://docs.djangoproject.com/en/5.2/ref/contrib/contenttypes/#django.contrib.contenttypes.fields.GenericRelation>`_
field. Which is confirmed by `Why won't my GenericForeignKey cascade
when deleting?
<https://stackoverflow.com/questions/6803018/why-wont-my-genericforeignkey-cascade-when-deleting>`_.
OTOH this statement seems to be wrong: it happens also in my projects
which do *not* use any `GenericRelation`.  As :mod:`test_broken_gfk
<lino_welfare.projects.eupen.tests.test_broken_gfk>` shows.

Which means that :class:`Change <lino.modlib.changes.models.Change>`
objects are currently *not* preserved if their `master` or `object`
pointer becomes stale.  See :ticket:`30` (Keep change records when
partner gets deleted).  I must probably write a signal handler for
`pre_delete`. A minor problem, though.  `Clear nullable foreign keys
on delete <https://djangosnippets.org/snippets/1231/>`_.

All this raises the question: How then did these stale generic
pointers get into the database in Eupen?  Okay, I can imagine that if
some bug in some user code raises an exception at the right (i.e. the
wrong) moment.

And last but not least: 

- how then can I artificially produce some stale GenericRelated
  objects for testing purposes?
- how to clean up these?


About Journals and Invoices
===========================

While working on :ticket:`9`, Mahmoud correctly pointed out that there
were some redundant table definitions in :mod:`lino.modlib.trading` and
:mod:`lino.modlib.accounting`.