create_subscriptions_invoices.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. # -*- coding: utf-8 -*-
  2. import datetime
  3. from dateutil.relativedelta import relativedelta
  4. from django.http import HttpResponse
  5. from django.db.models import Q
  6. from coin.offers.models import Offer, OfferSubscription
  7. from coin.members.models import Member
  8. from coin.billing.models import Invoice, InvoiceDetail
  9. def create_all_members_invoices_for_a_period(date):
  10. """
  11. Pour chaque membre ayant au moins un abonnement actif, génère les factures
  12. en prenant la date comme premier mois de la période de facturation
  13. """
  14. members = Member.objects.filter(
  15. Q(offersubscription__resign_date__isnull=True) |
  16. Q(offersubscription__resign_date__gte=datetime.date.today()))
  17. for member in members:
  18. create_member_invoice_for_a_period(member,date)
  19. def create_member_invoice_for_a_period(member, date):
  20. """
  21. Créé si necessaire une facture pour un membre en prenant la date passée
  22. en paramètre comme premier mois de période. Renvoi la facture générée
  23. ou None si aucune facture n'était pas necessaire.
  24. """
  25. invoice = None
  26. # Récupère les abonnements en cours du membre
  27. offer_subscriptions = member.get_active_subscriptions(date)
  28. # Pour chaque abonnement
  29. for offer_subscription in offer_subscriptions:
  30. # Récupère l'offre de l'abonnement
  31. offer = offer_subscription.offer
  32. # Recherche dans les factures déjà existantes de ce membre des items
  33. # ayant cet abonnement pour lesquels la période de facturation englobe
  34. # la date
  35. invoicedetail_test_before = InvoiceDetail.objects.filter(
  36. offersubscription__exact=offer_subscription.pk,
  37. period_from__lte=date,
  38. period_to__gte=date,
  39. invoice__member__exact=member.pk)
  40. # Si une telle facture n'existe pas, alors ajout l'item à facturer à la
  41. # facture à générer
  42. if not invoicedetail_test_before.exists():
  43. # Si l'object facture n'a pas encore été créé, le créé
  44. if invoice is None:
  45. invoice = Invoice.objects.create(
  46. date_due=datetime.date.today(),
  47. member=member
  48. )
  49. # Vérifie s'il s'agit de la première facture d'un abonnement,
  50. # Alors facture en plus les frais de mise en service
  51. invoicedetail_test_first = InvoiceDetail.objects.filter(
  52. offersubscription__exact=offer_subscription.pk,
  53. invoice__member__exact=member.pk)
  54. if not invoicedetail_test_first.exists():
  55. invoice.details.create(
  56. label=offer.name + " - Frais de mise en service",
  57. amount=offer.initial_fees,
  58. offersubscription=offer_subscription,
  59. period_from=None,
  60. period_to=None)
  61. # Période de facturation de l'item par defaut
  62. # - Du début du mois de la date passée en paramètre
  63. # - Jusqu'à la fin du mois de la période de facturation de l'offre
  64. period_from = datetime.date(date.year, date.month, 1)
  65. period_to = (datetime.date(date.year, date.month, 1) +
  66. relativedelta(months=+offer.billing_period) -
  67. relativedelta(days=+1))
  68. # Recherche dans les factures déjà existantes de ce membre des
  69. # items ayant cet abonnement pour lesquels la période de
  70. # facturation commence avant la fin de notre période de facturation
  71. # actuelle
  72. invoicedetail_test_after = InvoiceDetail.objects.filter(
  73. offersubscription__exact=offer_subscription.pk,
  74. period_from__lte=period_to,
  75. period_from__gte=period_from,
  76. invoice__member__exact=member.pk)
  77. # Si une telle facture existe, récupère la date de début de
  78. # facturation pour en faire la date de fin de facturation
  79. if invoicedetail_test_after.exists():
  80. invoicedetail_after = invoicedetail_test_after.first()
  81. period_to = (
  82. datetime.date(invoicedetail_after.period_from.year,
  83. invoicedetail_after.period_from.month, 1) -
  84. relativedelta(days=+1))
  85. # Ajout l'item de l'offre correspondant à l'abonnement à la facture
  86. invoice.details.create(label=offer.name,
  87. amount=offer.period_fees,
  88. offersubscription=offer_subscription,
  89. period_from=period_from,
  90. period_to=period_to)
  91. invoice.save()
  92. return invoice