payslip.models: 55 total statements, 100.0% covered

Generated: Sun 2014-11-09 12:02 CET

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

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