payslip.models: 67 total statements, 100.0% covered

Generated: Mon 2014-11-10 12:51 CET

Source file: /home/tobi/Projects/django-payslip/src/payslip/models.py

Stats: 50 executed, 0 missed, 17 excluded, 218 ignored

  1. """Models for the ``payslip`` application."""
  2. from django.db import models
  3. from django.utils.timezone import localtime, now
  4. from django.utils.translation import ugettext_lazy as _
  5. class Company(models.Model):
  6. """
  7. Model, which holds general information of a company.
  8. :name: Name of the company.
  9. :address: Full address model fields.
  10. :extra_fields: Custom fields to hold more information.
  11. """
  12. name = models.CharField(
  13. max_length=100,
  14. verbose_name=_('Name'),
  15. )
  16. address = models.TextField(
  17. verbose_name=_('Address'),
  18. blank=True, null=True,
  19. )
  20. extra_fields = models.ManyToManyField(
  21. 'payslip.ExtraField',
  22. verbose_name=_('Extra fields'),
  23. blank=True, null=True,
  24. )
  25. class Meta:
  26. ordering = ['name', ]
  27. def __unicode__(self):
  28. return '{0}'.format(self.name)
  29. class Employee(models.Model):
  30. """
  31. Model, which holds personal information of employee.
  32. :user: Connection to the django user model, to allow a login.
  33. :company: Connection to the employee's company.
  34. :hr_number: ID to connect some non-digital documents or to use as a
  35. reference.
  36. :address: Full address model fields.
  37. :title: Title of the employee.
  38. :extra_fields: Custom fields like e.g. confession, tax class.
  39. """
  40. user = models.ForeignKey(
  41. 'auth.User',
  42. verbose_name=_('User'),
  43. related_name='employees',
  44. )
  45. company = models.ForeignKey(
  46. 'payslip.Company',
  47. verbose_name=_('Company'),
  48. related_name='employees',
  49. )
  50. hr_number = models.PositiveIntegerField(
  51. verbose_name=_('HR number'),
  52. blank=True, null=True,
  53. )
  54. address = models.TextField(
  55. verbose_name=_('Address'),
  56. blank=True, null=True,
  57. )
  58. title = models.CharField(
  59. max_length=1,
  60. verbose_name=_('Title'),
  61. choices=(
  62. ('1', 'Ms.'),
  63. ('2', 'Mrs.'),
  64. ('3', 'Mr.'),
  65. ('4', 'Dr.'),
  66. )
  67. )
  68. extra_fields = models.ManyToManyField(
  69. 'payslip.ExtraField',
  70. verbose_name=_('Extra fields'),
  71. blank=True, null=True,
  72. )
  73. is_manager = models.BooleanField(
  74. default=False,
  75. verbose_name=_('is Manager'),
  76. )
  77. class Meta:
  78. ordering = ['company__name', 'user__first_name', ]
  79. def __unicode__(self):
  80. return '{0} {1}'.format(self.user.first_name, self.user.last_name)
  81. class ExtraFieldType(models.Model):
  82. """
  83. Model to create custom information holders.
  84. :name: Name of the attribute.
  85. :description: Description of the attribute.
  86. :model: Can be set in order to allow the use of only one model.
  87. :fixed_values: Can transform related exta fields into choices.
  88. """
  89. name = models.CharField(
  90. max_length=100,
  91. verbose_name=_('Name'),
  92. )
  93. description = models.CharField(
  94. max_length=100,
  95. blank=True, null=True,
  96. verbose_name=_('Description'),
  97. )
  98. model = models.CharField(
  99. max_length=10,
  100. choices=(
  101. ('Employee', 'Employee'),
  102. ('Payment', 'Payment'),
  103. ('Company', 'Company'),
  104. ),
  105. verbose_name=_('Model'),
  106. blank=True, null=True,
  107. )
  108. fixed_values = models.BooleanField(
  109. default=False,
  110. verbose_name=_('Fixed values'),
  111. )
  112. class Meta:
  113. ordering = ['name', ]
  114. def __unicode__(self):
  115. return '{0}'.format(self.name)
  116. class ExtraField(models.Model):
  117. """
  118. Model to create custom fields.
  119. :field_type: Connection to the field type.
  120. :value: Current value of this extra field.
  121. """
  122. field_type = models.ForeignKey(
  123. 'payslip.ExtraFieldType',
  124. verbose_name=_('Field type'),
  125. related_name='extra_fields',
  126. help_text=_('Only field types with fixed values can be chosen to add'
  127. ' global values.'),
  128. )
  129. value = models.CharField(
  130. max_length=200,
  131. verbose_name=_('Value'),
  132. )
  133. class Meta:
  134. ordering = ['field_type__name', ]
  135. def __unicode__(self):
  136. return '{0} ({1}) - {2}'.format(
  137. self.field_type, self.field_type.get_model_display() or 'general',
  138. self.value)
  139. class PaymentType(models.Model):
  140. """
  141. Model to create payment types.
  142. :name: Name of the type.
  143. :rrule: Recurring rule setting.
  144. :description: Description of the type.
  145. """
  146. name = models.CharField(
  147. max_length=100,
  148. verbose_name=_('Name'),
  149. )
  150. rrule = models.CharField(
  151. max_length=10,
  152. verbose_name=_('Recurring rule'),
  153. blank=True,
  154. choices=(
  155. ('MONTHLY', _('Monthly')),
  156. ('YEARLY', _('Yearly')),
  157. )
  158. )
  159. description = models.CharField(
  160. max_length=100,
  161. blank=True, null=True,
  162. verbose_name=_('Description'),
  163. )
  164. class Meta:
  165. ordering = ['name', ]
  166. def __unicode__(self):
  167. if self.rrule:
  168. return '{0} ({1})'.format(self.name, self.get_rrule_display())
  169. return '{0}'.format(self.name)
  170. class Payment(models.Model):
  171. """
  172. Model, which represents one single payment.
  173. :payment_type: Type of the payment.
  174. :employee: Connection to the payment receiver.
  175. :amount: Current amount of the payment.
  176. :date: Date the payment should accrue.
  177. :end_date: Optional end date, if payment type has a rrule.
  178. :extra_fields: Custom fields like e.g. quantity, bonus.
  179. """
  180. payment_type = models.ForeignKey(
  181. 'payslip.PaymentType',
  182. verbose_name=_('Payment type'),
  183. related_name='payments',
  184. )
  185. employee = models.ForeignKey(
  186. 'payslip.Employee',
  187. verbose_name=_('Employee'),
  188. related_name='payments',
  189. )
  190. amount = models.DecimalField(
  191. decimal_places=2,
  192. max_digits=10,
  193. verbose_name=_('Amount'),
  194. )
  195. date = models.DateTimeField(
  196. verbose_name=_('Date'),
  197. default=now().today(),
  198. )
  199. end_date = models.DateTimeField(
  200. verbose_name=_('End of recurring period'),
  201. blank=True, null=True,
  202. help_text=_('This field is only considered, if the payment type has a'
  203. ' recurring rule.'),
  204. )
  205. extra_fields = models.ManyToManyField(
  206. 'payslip.ExtraField',
  207. verbose_name=_('Extra fields'),
  208. blank=True, null=True,
  209. )
  210. description = models.CharField(
  211. max_length=100,
  212. blank=True, null=True,
  213. verbose_name=_('Description'),
  214. )
  215. class Meta:
  216. ordering = ['employee__user__first_name', '-date', ]
  217. def __unicode__(self):
  218. return '{0} - {1} ({2})'.format(self.payment_type, self.amount,
  219. self.employee)
  220. def get_date_without_tz(self):
  221. return localtime(self.date).replace(tzinfo=None)
  222. def get_end_date_without_tz(self):
  223. return localtime(self.end_date).replace(tzinfo=None)
  224. @property
  225. def is_recurring(self):
  226. return self.payment_type.rrule