text: """
  
  A Strange Problem
  =================
  
  This testcase may also be useful as an overview on how Lino handles Documents and Journals.
  
  The following works only if you have issue 10808 solved:
  
    >>> ORD = Order.create_journal("ORD",name="Orders")
    >>> print ORD.create_document()
    ORD#1 (1)
    >>> INV = Invoice.create_journal("INV",name="Invoices")
    >>> print INV.create_document()
    INV#1 (1)
    
  
  """
  
  from django.db import models
  
  
  class AbstractDocument(models.Model):
  
      class Meta:
          abstract = True
  
      last_modified = models.DateTimeField(auto_now=True)
  
  
  DOCTYPES = []
  DOCTYPE_CHOICES = []
  
  
  def register_doctype(docclass):
      type_id = len(DOCTYPE_CHOICES)
      DOCTYPE_CHOICES.append((type_id, docclass.__name__))
      DOCTYPES.append(docclass)
      docclass.doctype = type_id
      return type_id
  
  
  def get_doctype(cl):
      i = 0
      for c in DOCTYPES:
          if c is cl:
              return i
          i += 1
      return None
  
  
  from django.utils.encoding import python_2_unicode_compatible
  
  
  @python_2_unicode_compatible
  class Journal(models.Model):
  
      id = models.CharField(max_length=4, primary_key=True)
      name = models.CharField(max_length=100)
      doctype = models.IntegerField()  # choices=DOCTYPE_CHOICES)
  
      def __str__(self):
          return self.id
  
      def get_doc_model(self):
          return DOCTYPES[self.doctype]
  
      def create_document(self, **kw):
          cl = self.get_doc_model()
          kw.update(journal=self)
          doc = cl(**kw)
          doc.full_clean()
          doc.save()
          return doc
  
      def get_next_number(self):
          self.save()
          cl = self.get_doc_model()
          d = cl.objects.filter(journal=self).aggregate(
              models.Max('number'))
          number = d['number__max']
          if number is None:
              return 1
          return number + 1
  
  
  def JournalRef(**kw):
      return models.ForeignKey(Journal, **kw)
  
  
  def DocumentRef(**kw):
      return models.IntegerField(**kw)
  
  
  @python_2_unicode_compatible
  class JournaledAbstractDocument(AbstractDocument):
  
      journal = JournalRef()
      number = DocumentRef()
  
      class Meta:
          abstract = True
  
      @classmethod
      def create_journal(cls, id, **kw):
          doctype = get_doctype(cls)
          jnl = Journal(doctype=doctype, id=id, **kw)
          jnl.save()
          return jnl
  
      @classmethod
      def get_journals(cls):
          doctype = get_doctype(cls)
          return Journal.objects.filter(doctype=doctype).order_by('pos')
  
      def __str__(self):
          if self.id is None:
              return "(Unsaved %s document (journal=%r,number=%r))" % (
                  self.__class__, self.journal, self.number)
          return "%s#%s (%d)" % (self.journal, self.number, self.id)
  
      def full_clean(self, *args, **kw):
          if self.number is None:
              self.number = self.journal.get_next_number()
          super(JournaledAbstractDocument, self).full_clean(*args, **kw)
  
      #~ def save(self,*args,**kw):
          #~ self.before_save()
          #~ r = super(AbstractDocument,self).save(*args,**kw)
          #~ self.after_save()
          #~ return r
  
      #~ def after_save(self):
          #~ pass
  
  
  class LedgerDocument(JournaledAbstractDocument):
  
      value_date = models.DateField(auto_now=True)
      ledger_remark = models.CharField("Remark for ledger",
                                       max_length=200, blank=True)
  
  
  class SalesDocument(JournaledAbstractDocument):
  
      creation_date = models.DateField(auto_now=True)
  
      #~ def before_save(self):
          #~ JournaledAbstractDocument.before_save(self)
          # ...
  
  
  class Order(SalesDocument):
      valid_until = models.DateField(auto_now=True)
  
  
  class Invoice(LedgerDocument, SalesDocument):
      due_date = models.DateField("Payable until", blank=True, null=True)
  
      #~ def before_save(self):
          # ...
          #~ super(Invoice,self).before_save()
  
  #~ class Invoice(LedgerDocument):
      #~ due_date = models.DateField(auto_now=True)
  
      #~ def before_save(self):
          # ~ # ...
          #~ super(Invoice,self).before_save()
  
  
  register_doctype(Order)
  register_doctype(Invoice)
  