Hello, here is a code example that illustrates how I plan to implement journals in an accounting application. The attached file models.py contains the details. I saved it (together with an empty __init__.py) in a new directory "journals" under django/tests/modeltests of my SVN working copy (which I just updated to revision 10921), then I went to django/tests and run the command::
python runtests.py --settings=settings_memory -v1 journals to test it. I'm almost happy, but I get an unexpected result in line 60:: File "L:\snapshot\django\tests\modeltests\journals\models.py", \ line 60, in modeltests.journals.models Failed example: INV.lastnum Expected: 1 Got: 2 I don't understand why INV.lastnum returns 2 and not 1 at this place. If you see the reason, then please tell me! Also, I'd be glad to get feedback on my way of solving this particular problem, and I suggest to add this to the Django tests collection once I got it working. Luc --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to django-users+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~----------~----~----~----~------~----~------~--~---
""" Author: Luc Saffre 2009-06-04 A journal is a sequence of numbered documents in accounting applications. A Journal instance knows the model used for documents in this journal. A Document instance can look at its journal to find out which subclass of Document it is. The journal also manages a counter "lastnum" to control the numbering of documents. First we create two journals and some documents:: >>> ORD = Journal(id="ORD",name="Orders",doctype=0) >>> ORD.save() >>> INV = Journal(id="INV",name="Invoices",doctype=1,force_sequence=True) >>> INV.save() >>> ORD.create_document().save() >>> INV.create_document().save() >>> ORD.create_document().save() >>> ORD.create_document().save() >>> INV.create_document().save() >>> for doc in Document.objects.all(): ... print unicode(doc) ORD#1 (1) INV#1 (2) ORD#2 (3) ORD#3 (4) INV#2 (5) You can delete any document, leaving a hole in the sequence, and this number will not be reused. >>> ORD.lastnum 3 >>> Document.objects.get(pk=1).delete() Deleting ORD#1 (1) >>> ORD.lastnum 3 >>> doc = ORD.create_document() >>> doc.save() >>> print doc ORD#4 (6) For invoices, ``force_sequence=True`` means that it is not allowed to delete documents in the middle because this would leave a hole in the sequence:: >>> Document.objects.get(pk=2).delete() Traceback (most recent call last): ... DocumentError: INV#1 (2) is not the last document in journal It's okay to delete the last invoice of a journal. This will also decrement lastnum so that the number will be reused:: >>> INV.lastnum 2 >>> doc = Document.objects.get(pk=5) >>> print doc INV#2 (5) >>> doc.delete() Deleting INV#2 (5) >>> INV.lastnum 1 >>> doc = INV.create_document() >>> doc.save() >>> print doc INV#2 (7) Here is again the list of documents in the database after these operations:: >>> for doc in Document.objects.all(): ... print unicode(doc) INV#1 (2) ORD#2 (3) ORD#3 (4) ORD#4 (6) INV#2 (7) """ from django.db import models class DocumentError(Exception): pass DOCTYPE_CLASSES = [] DOCTYPE_CHOICES = [] def register_doctype(cl): n = len(DOCTYPE_CHOICES) DOCTYPE_CHOICES.append((n,cl.__name__)) DOCTYPE_CLASSES.append(cl) 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) lastnum = models.IntegerField(blank=True,null=True,default=0) force_sequence = models.BooleanField(default=False) def create_document(self,**kw): cl = DOCTYPE_CLASSES[self.doctype] if not kw.has_key('number'): kw['number'] = self.lastnum + 1 doc = cl(journal=self,**kw) self.lastnum = kw['number'] self.save() return doc def on_delete_document(self,doc): if doc.number == self.lastnum: #print "foo", self.lastnum self.lastnum -= 1 #print "bar", self.lastnum self.save() elif self.force_sequence: raise DocumentError( "%s is not the last document in journal" % unicode(doc) ) class Document(models.Model): number = models.IntegerField() journal = models.ForeignKey(Journal) def __unicode__(self): return "%s#%d (%d)" % (self.journal.id,self.number,self.id) def delete(self): self.journal.on_delete_document(self) print "Deleting", self return super(Document,self).delete() class Order(Document): pass class Invoice(Document): pass register_doctype(Order) register_doctype(Invoice)