Project

General

Profile

Download (47.5 KB) Statistics
| Branch: | Tag: | Revision:
8254b552 Benjamin Dauvergne
# -*- coding: utf-8 -*-
825ebd95 Mikaël Ates
import tempfile
8254b552 Benjamin Dauvergne
3ac2302c Mikaël Ates
from datetime import date, datetime
8254b552 Benjamin Dauvergne
from dateutil.relativedelta import relativedelta
26c45baa Benjamin Dauvergne
from decimal import Decimal
8254b552 Benjamin Dauvergne
fd0f45e5 Benjamin Dauvergne
from django.db import models
792d07a1 Benjamin Dauvergne
from django.db.models import Max, Q
8254b552 Benjamin Dauvergne
from model_utils import Choices

f9edfea1 Mikaël Ates
from calebasse.dossiers.models import PatientRecord
37ef36c7 Mikaël Ates
from calebasse.ressources.models import (ServiceLinkedManager, PricePerAct,
HealthCenter)
8254b552 Benjamin Dauvergne
import list_acts
825ebd95 Mikaël Ates
import progor
8254b552 Benjamin Dauvergne
6dba0e20 Mikaël Ates
from batches import build_batches

18889f61 Benjamin Dauvergne
def social_security_id_full(nir):
old = nir
try:
# Corse dpt 2A et 2B
minus = 0
if nir[6] in ('A', 'a'):
nir = [c for c in nir]
nir[6] = '0'
nir = ''.join(nir)
minus = 1000000
elif nir[6] in ('B', 'b'):
nir = [c for c in nir]
nir[6] = '0'
nir = ''.join(nir)
minus = 2000000
nir = int(nir) - minus
65c6bac5 Benjamin Dauvergne
return old + ' %0.2d' % (97 - (nir % 97))
18889f61 Benjamin Dauvergne
except Exception, e:
65c6bac5 Benjamin Dauvergne
return old + ' 00'
18889f61 Benjamin Dauvergne
8254b552 Benjamin Dauvergne
def quarter_start_and_end_dates(today=None):
'''Returns the first and last day of the current quarter'''
if today is None:
today = date.today()
a5ae3c51 Mikaël Ates
quarter = (today.month - 1) / 3
start_date = date(day=1, month=((quarter*3) + 1), year=today.year)
777d5c42 Benjamin Dauvergne
end_date = start_date + relativedelta(months=3) + relativedelta(days=-1)
8254b552 Benjamin Dauvergne
return start_date, end_date

class InvoicingManager(ServiceLinkedManager):
def current_for_service(self, service):
'''Return the currently open invoicing'''
if service.name != 'CMPP':
start_date, end_date = quarter_start_and_end_dates()
a1a9815a Mikaël Ates
invoicing, created = \
self.get_or_create(start_date=start_date,
11c4e940 Mikaël Ates
end_date=end_date, service=service)
if created:
invoicing.status = Invoicing.STATUS.closed
invoicing.save()
8254b552 Benjamin Dauvergne
else:
try:
invoicing = self.get(service=service,
82c98061 Mikaël Ates
status=Invoicing.STATUS.open)
8254b552 Benjamin Dauvergne
except Invoicing.DoesNotExist:
82c98061 Mikaël Ates
today = date.today()
start_date = date(day=today.day, month=today.month, year=today.year)
8254b552 Benjamin Dauvergne
invoicing, created = self.get_or_create(service=service,
3ac2302c Mikaël Ates
start_date=start_date,
82c98061 Mikaël Ates
status=Invoicing.STATUS.open)
8254b552 Benjamin Dauvergne
return invoicing

82c98061 Mikaël Ates
def last_for_service(self, service):
current = self.current_for_service(service)
last_seq_id = current.seq_id - 1
try:
return self.get(service=service,
seq_id=last_seq_id)
except:
return None

3ac2302c Mikaël Ates
def build_invoices_from_acts(acts_diagnostic, acts_treatment):
invoices = {}
len_invoices = 0
len_invoices_hors_pause = 0
len_acts_invoiced = 0
len_acts_invoiced_hors_pause = 0
4e38c429 Benjamin Dauvergne
pricing = PricePerAct.pricing()
3ac2302c Mikaël Ates
for patient, acts in acts_diagnostic.items():
invoices[patient] = []
act, hc = acts[0]
e035621e Mikaël Ates
invoice = dict()
4e38c429 Benjamin Dauvergne
invoice['ppa'] = pricing.price_at_date(act.date)
3ac2302c Mikaël Ates
invoice['year'] = act.date.year
invoice['acts'] = [(act, hc)]
74d65534 Mikaël Ates
if len(acts) > 1:
for act, hc in acts[1:]:
4e38c429 Benjamin Dauvergne
if invoice['ppa'] != pricing.price_at_date(act.date) or \
74d65534 Mikaël Ates
invoice['year'] != act.date.year:
invoices[patient].append(invoice)
9aacfe43 Mikaël Ates
len_invoices += 1
len_acts_invoiced += len(invoice['acts'])
74d65534 Mikaël Ates
if not patient.pause:
9aacfe43 Mikaël Ates
len_invoices_hors_pause += 1
len_acts_invoiced_hors_pause += len(invoice['acts'])
e035621e Mikaël Ates
invoice = dict()
4e38c429 Benjamin Dauvergne
invoice['ppa'] = pricing.price_at_date(act.date)
74d65534 Mikaël Ates
invoice['year'] = act.date.year
invoice['acts'] = [(act, hc)]
else:
invoice['acts'].append((act, hc))
3ac2302c Mikaël Ates
invoices[patient].append(invoice)
9aacfe43 Mikaël Ates
len_invoices += 1
len_acts_invoiced += len(invoice['acts'])
3ac2302c Mikaël Ates
if not patient.pause:
9aacfe43 Mikaël Ates
len_invoices_hors_pause += 1
len_acts_invoiced_hors_pause += len(invoice['acts'])
4e38c429 Benjamin Dauvergne
pricing = PricePerAct.pricing()
3ac2302c Mikaël Ates
for patient, acts in acts_treatment.items():
if not patient in invoices:
invoices[patient] = []
act, hc = acts[0]
74d65534 Mikaël Ates
invoice = dict()
4e38c429 Benjamin Dauvergne
invoice['ppa'] = pricing.price_at_date(act.date)
3ac2302c Mikaël Ates
invoice['year'] = act.date.year
invoice['acts'] = [(act, hc)]
74d65534 Mikaël Ates
if len(acts) > 1:
for act, hc in acts[1:]:
4e38c429 Benjamin Dauvergne
if invoice['ppa'] != pricing.price_at_date(act.date) or \
74d65534 Mikaël Ates
invoice['year'] != act.date.year:
invoices[patient].append(invoice)
9aacfe43 Mikaël Ates
len_invoices += 1
len_acts_invoiced += len(invoice['acts'])
74d65534 Mikaël Ates
if not patient.pause:
9aacfe43 Mikaël Ates
len_invoices_hors_pause += 1
len_acts_invoiced_hors_pause += len(invoice['acts'])
74d65534 Mikaël Ates
invoice = dict()
4e38c429 Benjamin Dauvergne
invoice['ppa'] = pricing.price_at_date(act.date)
74d65534 Mikaël Ates
invoice['year'] = act.date.year
invoice['acts'] = [(act, hc)]
else:
invoice['acts'].append((act, hc))
3ac2302c Mikaël Ates
invoices[patient].append(invoice)
9aacfe43 Mikaël Ates
len_invoices += 1
len_acts_invoiced += len(invoice['acts'])
3ac2302c Mikaël Ates
if not patient.pause:
9aacfe43 Mikaël Ates
len_invoices_hors_pause += 1
len_acts_invoiced_hors_pause += len(invoice['acts'])
3ac2302c Mikaël Ates
return (invoices, len_invoices, len_invoices_hors_pause,
len_acts_invoiced, len_acts_invoiced_hors_pause)

b0222841 Mikaël Ates
# The firts cmpp invoicing with calebasse
INVOICING_OFFSET = 134
3ac2302c Mikaël Ates
8254b552 Benjamin Dauvergne
class Invoicing(models.Model):
'''Represent a batch of invoices:

end_date - only acts before this date will be considered
status - current status of the invoicing
acts - acts bounded to this invoicing when the invoicing is validated

STATUS - the possible status:
- open, the invoicing is open for new acts
- closed, invoicing has been closed, no new acts will be accepted after
the end_date,
82c98061 Mikaël Ates
- validated,
8254b552 Benjamin Dauvergne
'''
STATUS = Choices('open', 'closed', 'validated', 'sent')

seq_id = models.IntegerField(blank=True, null=True)

b63305ca Mikaël Ates
service = models.ForeignKey('ressources.Service', on_delete=models.PROTECT)
8254b552 Benjamin Dauvergne
start_date = models.DateField(
verbose_name=u'Ouverture de la facturation')

end_date = models.DateField(
verbose_name=u'Clôturation de la facturation',
blank=True,
null=True)

status = models.CharField(
verbose_name=u'Statut',
choices=STATUS,
default=STATUS.open,
max_length=20)

acts = models.ManyToManyField('actes.Act')

objects = InvoicingManager()

class Meta:
fe1b46f3 Benjamin Dauvergne
unique_together = (('seq_id', 'service'),)
8254b552 Benjamin Dauvergne
def allocate_seq_id(self):
'''Allocate a new sequence id for a new invoicing.'''
82c98061 Mikaël Ates
seq_id = 1
max_seq_id = Invoicing.objects.for_service(self.service) \
.aggregate(Max('seq_id'))['seq_id__max']
ff8d6077 Mikaël Ates
if not max_seq_id:
if self.service.name == 'CMPP':
seq_id = INVOICING_OFFSET
else:
seq_id = max_seq_id + 1
82c98061 Mikaël Ates
return seq_id
8254b552 Benjamin Dauvergne
def list_for_billing(self):
3ac2302c Mikaël Ates
'''Return the acts candidates for billing'''
8254b552 Benjamin Dauvergne
if self.service.name == 'CMPP':
82c98061 Mikaël Ates
end_date = self.end_date
if not end_date:
today = date.today()
end_date = date(day=today.day, month=today.month, year=today.year)
523c5aaf Mikaël Ates
return list_acts.list_acts_for_billing_CMPP(end_date,
3ac2302c Mikaël Ates
service=self.service)
8254b552 Benjamin Dauvergne
elif self.service.name == 'CAMSP':
return list_acts.list_acts_for_billing_CAMSP(self.start_date,
self.end_date, service=self.service)
1368bb27 Mikaël Ates
elif 'SESSAD' in self.service.name:
8254b552 Benjamin Dauvergne
return list_acts.list_acts_for_billing_SESSAD(self.start_date,
self.end_date, service=self.service)
else:
raise RuntimeError('Unknown service', self.service)

6dba0e20 Mikaël Ates
def get_batches(self):
batches = list()
for hc, bs in build_batches(self).iteritems():
for batch in bs:
amount_rejected = sum([invoice.decimal_amount
for invoice in batch.invoices
if invoice.rejected])
versement = batch.total - amount_rejected
batches.append((hc, batch, amount_rejected, versement))
return batches

0f275ef5 Mikaël Ates
def get_stats_per_price_per_year(self):
stats_final = dict()
stats_final['total'] = (0, 0)
stats_final['detail'] = dict()
if self.service.name != 'CMPP' or \
self.status in (Invoicing.STATUS.open,
Invoicing.STATUS.closed):
return stats_final
stats = stats_final['detail']
invoices = self.invoice_set.all()
for invoice in invoices:
a9f8f019 Mikaël Ates
if not invoice.list_dates:
0f275ef5 Mikaël Ates
continue
# All acts of an invoice are the same year and at the same price
a9f8f019 Mikaël Ates
dates = invoice.list_dates.split('$')
year = datetime.strptime(dates[0], "%d/%m/%Y").year
0f275ef5 Mikaël Ates
ppa = invoice.decimal_ppa
if year not in stats:
stats[year] = dict()
if ppa not in stats[year]:
stats[year][ppa] = (0, 0)
nb_acts, amount = stats[year][ppa]
a9f8f019 Mikaël Ates
nb_acts += len(dates)
0f275ef5 Mikaël Ates
amount += invoice.decimal_amount
stats[year][ppa] = (nb_acts, amount)
nb_acts_f, amount_f = stats_final['total']
nb_acts_f += invoice.acts.count()
amount_f += invoice.decimal_amount
stats_final['total'] = (nb_acts_f, amount_f)
return stats_final
792d07a1 Benjamin Dauvergne
3ac2302c Mikaël Ates
def get_stats_or_validate(self, commit=False):
'''
If the invoicing is in state open or closed and commit is False
Return the stats of the billing
If the invoicing is in state open or closed and commit is True
60af3866 Mikaël Ates
Proceed to invoices creation, healthcare charging, acts as billed
3ac2302c Mikaël Ates
Return the stats of the billing
If the invoicing is in state validated or sent
Return the stats of the billing
'''
a49f011d Mikaël Ates
days_not_locked = 0
3ac2302c Mikaël Ates
if self.service.name == 'CMPP':
if self.status in (Invoicing.STATUS.open,
Invoicing.STATUS.closed):
'''
The stats are build dynamiccaly according to the
acts billable and the healthcares
'''
(acts_not_locked, days_not_locked, acts_not_valide,
bc7e290e Mikaël Ates
acts_not_billable, acts_pause, acts_diagnostic,
e32de143 Mikaël Ates
acts_treatment, acts_losts,
36f1b357 Mikaël Ates
acts_losts_missing_policy,
acts_losts_missing_birthdate) = \
bc7e290e Mikaël Ates
self.list_for_billing()
3ac2302c Mikaël Ates
(invoices, len_invoices, len_invoices_hors_pause,
len_acts_invoiced, len_acts_invoiced_hors_pause) = \
build_invoices_from_acts(acts_diagnostic, acts_treatment)
len_patient_invoiced = len(invoices.keys())
len_patient_invoiced_hors_pause = 0
for patient in invoices.keys():
if not patient.pause:
len_patient_invoiced_hors_pause = len_patient_invoiced_hors_pause + 1

patients = set(acts_not_locked.keys() + acts_not_valide.keys() + \
acts_not_billable.keys() + acts_diagnostic.keys() + acts_treatment.keys() + \
36f1b357 Mikaël Ates
acts_losts.keys() + acts_pause.keys() + acts_losts_missing_policy.keys() + \
acts_losts_missing_birthdate.keys())
3ac2302c Mikaël Ates
fa696406 Mikaël Ates
patients_stats = []
3ac2302c Mikaël Ates
len_patient_with_lost_acts = 0
len_acts_lost = 0
bc7e290e Mikaël Ates
len_patient_acts_paused = 0
len_acts_paused = 0
e32de143 Mikaël Ates
len_patient_with_lost_acts_missing_policy = 0
len_acts_losts_missing_policy = 0
36f1b357 Mikaël Ates
len_patient_with_lost_acts_missing_birthdate = 0
len_acts_losts_missing_birthdate = 0
3d7a840a Thomas NOEL
batches = {}
last_batch = {}
3ac2302c Mikaël Ates
for patient in patients:
fa696406 Mikaël Ates
dic = {}
3ac2302c Mikaël Ates
if patient in invoices.keys():
fa696406 Mikaël Ates
dic['invoices'] = invoices[patient]
3ac2302c Mikaël Ates
if commit and not patient.pause:
c6dcd2b6 Benjamin Dauvergne
policy_holder = patient.policyholder
try:
address = unicode(policy_holder.addresses.filter(place_of_life=True)[0])
except:
try:
address = unicode(policy_holder.addresses.all()[0])
except:
address = u''
792d07a1 Benjamin Dauvergne
invoice_kwargs = dict(
patient_id=patient.id,
patient_last_name=patient.last_name,
patient_first_name=patient.first_name,
f9f1ab0d Benjamin Dauvergne
patient_social_security_id=patient.social_security_id or '',
792d07a1 Benjamin Dauvergne
patient_birthdate=patient.birthdate,
patient_twinning_rank=patient.twinning_rank,
patient_healthcenter=patient.health_center,
f28b22e1 Benjamin Dauvergne
patient_other_health_center=patient.other_health_center or '',
patient_entry_date=patient.entry_date,
c6dcd2b6 Benjamin Dauvergne
patient_exit_date=patient.exit_date,
792d07a1 Benjamin Dauvergne
policy_holder_id=policy_holder.id,
policy_holder_last_name=policy_holder.last_name,
policy_holder_first_name=policy_holder.first_name,
policy_holder_social_security_id=policy_holder.social_security_id,
2a0a0f7c Thomas NOEL
policy_holder_other_health_center=policy_holder.other_health_center or '',
4b8fd7af Benjamin Dauvergne
policy_holder_healthcenter=policy_holder.health_center,
c6dcd2b6 Benjamin Dauvergne
policy_holder_address=address)
3ac2302c Mikaël Ates
for invoice in invoices[patient]:
b85f1d9a Benjamin Dauvergne
ppa = invoice['ppa'] * 100
3ac2302c Mikaël Ates
acts = invoice['acts']
amount = ppa * len(acts)
cea5307c Mikaël Ates
list_dates = '$'.join([act.date.strftime('%d/%m/%Y') for act, hc in acts])
792d07a1 Benjamin Dauvergne
in_o = Invoice(
invoicing=self,
b85f1d9a Benjamin Dauvergne
ppa=ppa,
792d07a1 Benjamin Dauvergne
amount=amount,
cea5307c Mikaël Ates
list_dates = list_dates,
792d07a1 Benjamin Dauvergne
**invoice_kwargs)
3ac2302c Mikaël Ates
in_o.save()
for act, hc in acts:
act.is_billed = True
act.healthcare = hc
act.save()
in_o.acts.add(act)
cea5307c Mikaël Ates
in_o.first_tag = acts[0][0].get_hc_tag()
in_o.save()
3d7a840a Thomas NOEL
# calcule le numero de lot pour cette facture
hc = in_o.health_center
hc_dest = hc.hc_invoice or hc
dest = hc_dest.large_regime.code + ' ' + hc_dest.dest_organism
if dest not in batches:
batches[dest] = {}
if hc not in batches[dest]:
nb1 = Invoice.objects.new_batch_number(health_center=hc_dest, invoicing=self)
nb2 = Invoice.objects.new_batch_number(health_center=hc, invoicing=self)
nb = max(nb1, nb2, last_batch.get(dest,0) + 1)
last_batch[dest] = nb
batches[dest][hc] = [{ 'batch': nb, 'size': 2, 'invoices': [], }]
# pas plus de 950 lignes par lot (le fichier B2 final ne doit
# pas depasser 999 lignes au total) :
b = batches[dest][hc].pop()
b2_size = in_o.acts.count() + 2
if (b['size'] + b2_size) > 950:
batches[dest][hc].append(b)
nb = last_batch.get(dest, 0) + 1
last_batch[dest] = nb
b = {'batch': nb, 'size': 2, 'invoices': []}
b['invoices'].append(in_o)
b['size'] += b2_size
batches[dest][hc].append(b)

in_o.batch = b['batch']
in_o.save()

3ac2302c Mikaël Ates
pass
if patient in acts_losts.keys():
# TODO: More details about healthcare
fa696406 Mikaël Ates
dic['losts'] = acts_losts[patient]
9aacfe43 Mikaël Ates
len_patient_with_lost_acts += 1
len_acts_lost += len(acts_losts[patient])
bc7e290e Mikaël Ates
if patient in acts_pause.keys():
fa696406 Mikaël Ates
dic['acts_paused'] = acts_pause[patient]
9aacfe43 Mikaël Ates
len_patient_acts_paused += 1
len_acts_paused += len(acts_pause[patient])
e32de143 Mikaël Ates
if patient in acts_losts_missing_policy.keys():
# TODO: More details about healthcare
dic['losts_missing_policy'] = acts_losts_missing_policy[patient]
9aacfe43 Mikaël Ates
len_patient_with_lost_acts_missing_policy += 1
len_acts_losts_missing_policy += len(acts_losts_missing_policy[patient])
36f1b357 Mikaël Ates
if patient in acts_losts_missing_birthdate.keys():
dic['losts_missing_birthdate'] = acts_losts_missing_birthdate[patient]
9aacfe43 Mikaël Ates
len_patient_with_lost_acts_missing_birthdate += 1
len_acts_losts_missing_birthdate += len(acts_losts_missing_birthdate[patient])
7ff22999 Mikaël Ates
if dic:
patients_stats.append((patient, dic))
fa696406 Mikaël Ates
patients_stats = sorted(patients_stats, key=lambda patient: (patient[0].last_name, patient[0].first_name))
bc7e290e Mikaël Ates
fa696406 Mikaël Ates
len_patients = len(patients_stats)
3ac2302c Mikaël Ates
if commit:
self.status = Invoicing.STATUS.validated
self.save()

else:
'''
Grab stats from the invoices
'''
len_patients = 0
len_invoices = 0
len_acts_invoiced = 0
patients_stats = {}
09de66b4 Mikaël Ates
days_not_locked = []
3ac2302c Mikaël Ates
invoices = self.invoice_set.all()
da8cf4cb Mikaël Ates
patients = {}
3ac2302c Mikaël Ates
for invoice in invoices:
len_invoices = len_invoices + 1
5866801c Mikaël Ates
if invoice.list_dates:
len_acts_invoiced += len(invoice.list_dates.split('$'))
da8cf4cb Mikaël Ates
patient = None
if not invoice.patient_id in patients.keys():
try:
patient = PatientRecord.objects.get(id=invoice.patient_id)
except:
e2e4192d Mikaël Ates
patient = PatientRecord(last_name=invoice.patient_last_name, first_name=invoice.patient_first_name)
9eed5e4c Mikaël Ates
patients[invoice.patient_id] = patient
3ac2302c Mikaël Ates
len_patients = len_patients + 1
da8cf4cb Mikaël Ates
patients_stats[patient] = {}
295d8d9e Mikaël Ates
patients_stats[patient]['invoices'] = []
3ac2302c Mikaël Ates
else:
9eed5e4c Mikaël Ates
patient = patients[invoice.patient_id]
295d8d9e Mikaël Ates
patients_stats[patient]['invoices'].append(invoice)
e8dec70c Mikaël Ates
patients_stats = sorted(patients_stats.items(), key=lambda patient: (patient[0].last_name, patient[0].first_name))
3ac2302c Mikaël Ates
# all patients in the invoicing are invoiced
len_patient_invoiced = 0
# These stats are not necessary because excluded form the validated invoicing
len_invoices_hors_pause = 0
len_acts_invoiced_hors_pause = 0
len_patient_invoiced_hors_pause = 0
len_acts_lost = 0
len_patient_with_lost_acts = 0
bc7e290e Mikaël Ates
len_patient_acts_paused = 0
len_acts_paused = 0
e32de143 Mikaël Ates
len_patient_with_lost_acts_missing_policy = 0
len_acts_losts_missing_policy = 0
36f1b357 Mikaël Ates
len_patient_with_lost_acts_missing_birthdate = 0
len_acts_losts_missing_birthdate = 0
3ac2302c Mikaël Ates
return (len_patients, len_invoices, len_invoices_hors_pause,
len_acts_invoiced, len_acts_invoiced_hors_pause,
len_patient_invoiced, len_patient_invoiced_hors_pause,
bc7e290e Mikaël Ates
len_acts_lost, len_patient_with_lost_acts, patients_stats,
days_not_locked, len_patient_acts_paused,
e32de143 Mikaël Ates
len_acts_paused, len_acts_losts_missing_policy,
36f1b357 Mikaël Ates
len_patient_with_lost_acts_missing_policy,
len_acts_losts_missing_birthdate,
len_patient_with_lost_acts_missing_birthdate)
09de66b4 Mikaël Ates
elif self.service.name == 'CAMSP':
if self.status in Invoicing.STATUS.closed:
(acts_not_locked, days_not_locked, acts_not_valide,
bc7e290e Mikaël Ates
acts_not_billable, acts_pause, acts_bad_state,
38c89917 Mikaël Ates
acts_accepted, patients_missing_policy) = self.list_for_billing()
09de66b4 Mikaël Ates
len_patient_pause = 0
len_patient_hors_pause = 0
len_acts_pause = 0
len_acts_hors_pause = 0
bc7e290e Mikaël Ates
len_patient_acts_paused = 0
len_acts_paused = 0
patients = set(acts_accepted.keys() + acts_pause.keys())
fa696406 Mikaël Ates
patients_stats = []
bc7e290e Mikaël Ates
for patient in patients:
fa696406 Mikaël Ates
dic = {}
bc7e290e Mikaël Ates
if patient in acts_accepted.keys():
acts = acts_accepted[patient]
fa696406 Mikaël Ates
dic['accepted'] = acts
bc7e290e Mikaël Ates
if patient.pause:
9aacfe43 Mikaël Ates
len_patient_pause += 1
len_acts_pause += len(acts)
bc7e290e Mikaël Ates
else:
9aacfe43 Mikaël Ates
len_patient_hors_pause += 1
len_acts_hors_pause += len(acts)
bc7e290e Mikaël Ates
if commit:
e2e4192d Mikaël Ates
policy_holder = patient.policyholder
try:
address = unicode(policy_holder.addresses.filter(place_of_life=True)[0])
except:
try:
address = unicode(policy_holder.addresses.all()[0])
except:
address = u''
invoice_kwargs = dict(
patient_id=patient.id,
patient_last_name=patient.last_name,
patient_first_name=patient.first_name,
patient_social_security_id=patient.social_security_id or '',
patient_birthdate=patient.birthdate,
patient_twinning_rank=patient.twinning_rank,
patient_healthcenter=patient.health_center,
patient_other_health_center=patient.other_health_center or '',
patient_entry_date=patient.entry_date,
patient_exit_date=patient.exit_date,
policy_holder_id=policy_holder.id,
policy_holder_last_name=policy_holder.last_name,
policy_holder_first_name=policy_holder.first_name,
policy_holder_social_security_id=policy_holder.social_security_id or '',
policy_holder_other_health_center=policy_holder.other_health_center or '',
policy_holder_healthcenter=policy_holder.health_center,
policy_holder_address=address)
if policy_holder.management_code:
management_code = policy_holder.management_code
invoice_kwargs['policy_holder_management_code'] = management_code.code
invoice_kwargs['policy_holder_management_code_name'] = management_code.name
cea5307c Mikaël Ates
list_dates = '$'.join([act.date.strftime('%d/%m/%Y') for act in acts])
e2e4192d Mikaël Ates
invoice = Invoice(
invoicing=self,
ppa=0, amount=0,
cea5307c Mikaël Ates
list_dates=list_dates,
e2e4192d Mikaël Ates
**invoice_kwargs)
invoice.save()
bc7e290e Mikaël Ates
for act in acts:
e2e4192d Mikaël Ates
act.is_billed = True
act.save()
invoice.acts.add(act)
bc7e290e Mikaël Ates
if patient in acts_pause.keys():
fa696406 Mikaël Ates
dic['acts_paused'] = acts_pause[patient]
9aacfe43 Mikaël Ates
len_patient_acts_paused += 1
len_acts_paused += len(acts_pause[patient])
fa696406 Mikaël Ates
patients_stats.append((patient, dic))
patients_stats = sorted(patients_stats, key=lambda patient: (patient[0].last_name, patient[0].first_name))
09de66b4 Mikaël Ates
if commit:
self.status = Invoicing.STATUS.validated
self.save()
else:
bc7e290e Mikaël Ates
patients_stats = {}
09de66b4 Mikaël Ates
len_patient_pause = 0
len_patient_hors_pause = 0
len_acts_pause = 0
len_acts_hors_pause = 0
bc7e290e Mikaël Ates
len_patient_acts_paused = 0
len_acts_paused = 0
09de66b4 Mikaël Ates
days_not_locked = []
38c89917 Mikaël Ates
patients_missing_policy = []
e2e4192d Mikaël Ates
invoices = self.invoice_set.all()
for invoice in invoices:
9aacfe43 Mikaël Ates
len_patient_hors_pause += 1
5866801c Mikaël Ates
if invoice.list_dates:
len_acts_hors_pause += len(invoice.list_dates.split('$'))
e2e4192d Mikaël Ates
patient = None
try:
patient = PatientRecord.objects.get(id=invoice.patient_id)
except:
patient = PatientRecord(last_name=invoice.patient_last_name, first_name=invoice.patient_first_name)
patients_stats[patient] = {}
patients_stats[patient]['accepted'] = invoice.acts.all()
e8dec70c Mikaël Ates
patients_stats = sorted(patients_stats.items(), key=lambda patient: (patient[0].last_name, patient[0].first_name))
09de66b4 Mikaël Ates
return (len_patient_pause, len_patient_hors_pause,
bc7e290e Mikaël Ates
len_acts_pause, len_acts_hors_pause, patients_stats,
days_not_locked, len_patient_acts_paused,
38c89917 Mikaël Ates
len_acts_paused, patients_missing_policy)
3ac2302c Mikaël Ates
else:
1368bb27 Mikaël Ates
if self.status in Invoicing.STATUS.closed:
(acts_not_locked, days_not_locked, acts_not_valide,
bc7e290e Mikaël Ates
acts_not_billable, acts_pause, acts_bad_state,
38c89917 Mikaël Ates
acts_missing_valid_notification, acts_accepted,
patients_missing_policy) = \
bc7e290e Mikaël Ates
self.list_for_billing()

1368bb27 Mikaël Ates
len_patient_pause = 0
len_patient_hors_pause = 0
len_acts_pause = 0
len_acts_hors_pause = 0
bc7e290e Mikaël Ates
len_patient_acts_paused = 0
len_acts_paused = 0
len_patient_missing_notif = 0
len_acts_missing_notif = 0
38c89917 Mikaël Ates
patients = set(acts_accepted.keys() + \
acts_missing_valid_notification.keys() + \
acts_pause.keys())
fa696406 Mikaël Ates
patients_stats = []
38c89917 Mikaël Ates
patients_missing_notif = []
bc7e290e Mikaël Ates
for patient in patients:
fa696406 Mikaël Ates
dic = {}
e2e4192d Mikaël Ates
acts_to_commit = []
bc7e290e Mikaël Ates
if patient in acts_accepted.keys():
acts = acts_accepted[patient]
e2e4192d Mikaël Ates
acts_to_commit.extend(acts)
fa696406 Mikaël Ates
dic['accepted'] = acts
bc7e290e Mikaël Ates
if patient.pause:
9aacfe43 Mikaël Ates
len_patient_pause += 1
len_acts_pause += len(acts)
bc7e290e Mikaël Ates
else:
9aacfe43 Mikaël Ates
len_patient_hors_pause += 1
len_acts_hors_pause += len(acts)
bc7e290e Mikaël Ates
if patient in acts_missing_valid_notification.keys():
38c89917 Mikaël Ates
patients_missing_notif.append(patient)
bc7e290e Mikaël Ates
acts = acts_missing_valid_notification[patient]
e2e4192d Mikaël Ates
acts_to_commit.extend(acts)
fa696406 Mikaël Ates
dic['missings'] = acts
9aacfe43 Mikaël Ates
len_patient_missing_notif += 1
len_acts_missing_notif += len(acts)
e2e4192d Mikaël Ates
if patient.pause:
if not 'accepted' in dic:
9aacfe43 Mikaël Ates
len_patient_pause += 1
len_acts_pause += len(acts)
e2e4192d Mikaël Ates
else:
if not 'accepted' in dic:
9aacfe43 Mikaël Ates
len_patient_hors_pause += 1
len_acts_hors_pause += len(acts)
e2e4192d Mikaël Ates
if commit and acts_to_commit:
policy_holder = patient.policyholder
try:
address = unicode(policy_holder.addresses.filter(place_of_life=True)[0])
except:
try:
address = unicode(policy_holder.addresses.all()[0])
except:
address = u''
invoice_kwargs = dict(
patient_id=patient.id,
patient_last_name=patient.last_name,
patient_first_name=patient.first_name,
patient_social_security_id=patient.social_security_id or '',
patient_birthdate=patient.birthdate,
patient_twinning_rank=patient.twinning_rank,
patient_healthcenter=patient.health_center,
patient_other_health_center=patient.other_health_center or '',
patient_entry_date=patient.entry_date,
patient_exit_date=patient.exit_date,
policy_holder_id=policy_holder.id,
policy_holder_last_name=policy_holder.last_name,
policy_holder_first_name=policy_holder.first_name,
policy_holder_social_security_id=policy_holder.social_security_id or '',
policy_holder_other_health_center=policy_holder.other_health_center or '',
policy_holder_healthcenter=policy_holder.health_center,
policy_holder_address=address)
if policy_holder.management_code:
management_code = policy_holder.management_code
invoice_kwargs['policy_holder_management_code'] = management_code.code
invoice_kwargs['policy_holder_management_code_name'] = management_code.name
3a88daad Mikaël Ates
list_dates = '$'.join([act.date.strftime('%d/%m/%Y') for act in acts_to_commit])
e2e4192d Mikaël Ates
invoice = Invoice(
invoicing=self,
ppa=0, amount=0,
cea5307c Mikaël Ates
list_dates=list_dates,
e2e4192d Mikaël Ates
**invoice_kwargs)
invoice.save()
for act in acts_to_commit:
act.is_billed = True
act.save()
invoice.acts.add(act)
bc7e290e Mikaël Ates
if patient in acts_pause.keys():
fa696406 Mikaël Ates
dic['acts_paused'] = acts_pause[patient]
9aacfe43 Mikaël Ates
len_patient_acts_paused += 1
len_acts_paused += len(acts_pause[patient])
fa696406 Mikaël Ates
patients_stats.append((patient, dic))
patients_stats = sorted(patients_stats, key=lambda patient: (patient[0].last_name, patient[0].first_name))
1368bb27 Mikaël Ates
if commit:
self.status = Invoicing.STATUS.validated
self.save()
else:
bc7e290e Mikaël Ates
patients_stats = {}
1368bb27 Mikaël Ates
len_patient_pause = 0
len_patient_hors_pause = 0
len_acts_pause = 0
len_acts_hors_pause = 0
bc7e290e Mikaël Ates
len_patient_acts_paused = 0
len_acts_paused = 0
1368bb27 Mikaël Ates
len_patient_missing_notif = 0
len_acts_missing_notif = 0
days_not_locked = []
38c89917 Mikaël Ates
patients_missing_policy = []
patients_missing_notif = []
e2e4192d Mikaël Ates
invoices = self.invoice_set.all()
for invoice in invoices:
9aacfe43 Mikaël Ates
len_patient_hors_pause += 1
5866801c Mikaël Ates
if invoice.list_dates:
len_acts_hors_pause += len(invoice.list_dates.split('$'))
e2e4192d Mikaël Ates
patient = None
try:
patient = PatientRecord.objects.get(id=invoice.patient_id)
except:
patient = PatientRecord(last_name=invoice.patient_last_name, first_name=invoice.patient_first_name)
patients_stats[patient] = {}
patients_stats[patient]['accepted'] = invoice.acts.all()
e8dec70c Mikaël Ates
patients_stats = sorted(patients_stats.items(), key=lambda patient: (patient[0].last_name, patient[0].first_name))
1368bb27 Mikaël Ates
return (len_patient_pause, len_patient_hors_pause,
len_acts_pause, len_acts_hors_pause,
len_patient_missing_notif, len_acts_missing_notif,
bc7e290e Mikaël Ates
patients_stats, days_not_locked,
38c89917 Mikaël Ates
len_patient_acts_paused, len_acts_paused,
patients_missing_policy, patients_missing_notif)
3ac2302c Mikaël Ates
8254b552 Benjamin Dauvergne
def save(self, *args, **kwargs):
if not self.seq_id:
self.seq_id = self.allocate_seq_id()
super(Invoicing, self).save(*args, **kwargs)

82c98061 Mikaël Ates
def close(self, end_date=None):
8254b552 Benjamin Dauvergne
'''Close an open invoicing'''
82c98061 Mikaël Ates
if self.service.name != 'CMPP':
raise RuntimeError('closing Invoicing is only for the CMPP')
8254b552 Benjamin Dauvergne
if self.status != Invoicing.STATUS.open:
raise RuntimeError('closing an un-opened Invoicing')
82c98061 Mikaël Ates
if not end_date:
today = date.today()
end_date = date(day=today.day, month=today.month, year=today.year)
3ac2302c Mikaël Ates
if end_date < self.start_date:
end_date = self.start_date + relativedelta(days=1)
82c98061 Mikaël Ates
self.status = Invoicing.STATUS.closed
self.end_date = end_date
8254b552 Benjamin Dauvergne
self.save()
3ac2302c Mikaël Ates
start_date = self.end_date + relativedelta(days=1)
invoicing = Invoicing(service=self.service,
start_date=start_date,
status=Invoicing.STATUS.open)
invoicing.save()
return invoicing
8254b552 Benjamin Dauvergne
825ebd95 Mikaël Ates
def export_for_accounting(self):
'''
Il faut separer les ecritures pour l'année en cours et les années
passées.
'''
def add_ecriture(health_center, amount):
accounting_number = '0' + health_center.accounting_number[1:]
'''Le nom du compte ne devrait pas etre important et seul compter
le numéro de compte'''
name = health_center.name
if len(name) > 30:
name = name[0:30]
ecriture = progor.EcritureComptable(date, accounting_number,
name, cycle, debit=amount)
imputation = progor.ImputationAnalytique(debit=amount)
ecriture.add_imputation(imputation)
journal.add_ecriture(ecriture)
journal = progor.IdentificationJournal()
ecritures_current = dict()
ecritures_past = dict()
total_current = 0
total_past = 0
date = self.end_date.strftime("%d/%m/%Y")
cycle = str(self.seq_id)
invoice_year = datetime(self.end_date.year, 1, 1).date()
for invoice in self.invoice_set.all():
8aa691d1 Mikaël Ates
hc = invoice.health_center.hc_invoice or invoice.health_center
825ebd95 Mikaël Ates
if invoice.end_date < invoice_year:
8aa691d1 Mikaël Ates
ecritures_past.setdefault(hc, 0)
ecritures_past[hc] += invoice.amount
825ebd95 Mikaël Ates
total_past += invoice.amount
else:
8aa691d1 Mikaël Ates
ecritures_current.setdefault(hc, 0)
ecritures_current[hc] += invoice.amount
825ebd95 Mikaël Ates
total_current += invoice.amount
'''Ce qui est facturé aux caisses est en débit'''
for health_center, amount in ecritures_past.items():
add_ecriture(health_center, amount)
for health_center, amount in ecritures_current.items():
add_ecriture(health_center, amount)
'''On équilibre avec du produit en crédit'''
#Produit années précédentes
if total_past:
ecriture = progor.EcritureComptable(date, '77200000',
'PRODUITS EXERCICES ANTERIEURS', cycle, credit=total_past, type_compte='0')
imputation = progor.ImputationAnalytique(credit=total_past)
ecriture.add_imputation(imputation)
journal.add_ecriture(ecriture)
#Produit année en cours
ecriture = progor.EcritureComptable(date, '73130000',
'PRODUITS EXERCICE', cycle, credit=total_current, type_compte='0')
imputation = progor.ImputationAnalytique(credit=total_current)
ecriture.add_imputation(imputation)
journal.add_ecriture(ecriture)
content = journal.render()
service = self.service
now = datetime.now()
output_file = tempfile.NamedTemporaryFile(prefix='%s-export-%s-' %
(service.slug, self.id), suffix='-%s.txt' % now, delete=False)
output_file.write(content)
return output_file.name

3ac2302c Mikaël Ates
74d65534 Mikaël Ates
#class PricePerAct(models.Model):
# price = models.IntegerField()
# start_date = models.DateField(
# verbose_name=u"Prise d'effet",
# default=date(day=5,month=1,year=1970))
# end_date = models.DateField(
# verbose_name=u"Fin d'effet",
# blank=True,
# null=True)

# @classmethod
# def get_price(cls, at_date=None):
# if not at_date:
# at_date = date.today()
# if isinstance(at_date, datetime):
# at_date = date(day=at_date.day, month=at_date.month,
# year=at_date.year)
# found = cls.objects.filter(start_date__lte = at_date).latest('start_date')
# if not found:
# raise Exception('No price to apply')
# return found.price

# def __unicode__(self):
# val = str(self.price) + ' from ' + str(self.start_date)
# if self.end_date:
# val = val + ' to ' + str(self.end_date)
# return val


#def add_price(price, start_date=None):
# price_o = None
# ppas = PricePerAct.objects.all()
# if ppas:
# if not start_date:
# raise Exception('A start date is mandatory to add a new Price')
# last_ppa = PricePerAct.objects.latest('start_date')
# if last_ppa.start_date >= start_date:
# raise Exception('The new price cannot apply before the price that currently applies.')
# if last_ppa.end_date and last_ppa.end_date != (start_date + relativedelta(days=-1)):
# raise Exception('The new price should apply the day after the last price ends.')
# last_ppa.end_date = start_date + relativedelta(days=-1)
# last_ppa.save()
# if not start_date:
# price_o = PricePerAct(price=price)
# else:
# price_o = PricePerAct(price=price, start_date=start_date)
# price_o.save()
# return price_o
3ac2302c Mikaël Ates

792d07a1 Benjamin Dauvergne
PREVIOUS_MAX_BATCH_NUMBERS = {
'CF00000004001110': 34,
'CT00000001016421': 1,
'CT00000001016422': 141,
'CT00000001025691': 20,
'CT00000002011011': 8,
'CT00000002381421': 15,
'MA00000002381421': 48,
0fe5adff Benjamin Dauvergne
'SM00000091007381': 98, # faure 43
'SM00000091007421': 98, # faure 44
'SM00000091007422': 98, # faure 45
'SM00000091007431': 98, # faure 46
'SM00000091007691': 98, # faure 47
'SM00000091007764': 98, # faure 48

792d07a1 Benjamin Dauvergne
'SM00000092001422': 14,
'SM00000092001691': 13,
'SM00000099038939': 24,
}


class InvoiceManager(models.Manager):
def new_batch_number(self, health_center, invoicing):
'''Compute the next batch number for the given health center'''
global PREVIOUS_MAX_BATCH_NUMBERS
37ef36c7 Mikaël Ates
hcs = HealthCenter.objects.filter(hc_invoice=health_center)
792d07a1 Benjamin Dauvergne
agg = self \
0db1637f Benjamin Dauvergne
.filter(invoicing__service=invoicing.service) \
792d07a1 Benjamin Dauvergne
.filter(invoicing__seq_id__lt=invoicing.seq_id) \
.filter(
Q(patient_healthcenter=health_center,
policy_holder_healthcenter__isnull=True)|
37ef36c7 Mikaël Ates
Q(policy_holder_healthcenter=health_center) |
Q(patient_healthcenter__in=hcs,
policy_holder_healthcenter__isnull=True)|
Q(policy_holder_healthcenter__in=hcs)) \
792d07a1 Benjamin Dauvergne
.aggregate(Max('batch'))
max_bn = agg['batch__max']
if max_bn is None:
max_bn = PREVIOUS_MAX_BATCH_NUMBERS.get(health_center.b2_000(), 0)
3d7a840a Thomas NOEL
else:
max_bn = max(max_bn, PREVIOUS_MAX_BATCH_NUMBERS.get(health_center.b2_000(), 0))
792d07a1 Benjamin Dauvergne
return max_bn + 1


3ac2302c Mikaël Ates
class Invoice(models.Model):
ebe35728 Mikaël Ates
objects = InvoiceManager()
3ac2302c Mikaël Ates
number = models.IntegerField(blank=True, null=True)
792d07a1 Benjamin Dauvergne
batch = models.IntegerField(blank=True, null=True)
# the patient can be modified (or even deleted) after invoice creation, so
# we copy his informations here
patient_id = models.IntegerField(blank=True, null=True)
patient_last_name = models.CharField(max_length=128,
05cadd08 Benjamin Dauvergne
verbose_name=u'Nom du patient', default='', blank=True)
792d07a1 Benjamin Dauvergne
patient_first_name = models.CharField(max_length=128,
05cadd08 Benjamin Dauvergne
verbose_name=u'Prénom(s) du patient', default='', blank=True)
792d07a1 Benjamin Dauvergne
patient_social_security_id = models.CharField(max_length=13,
05cadd08 Benjamin Dauvergne
verbose_name=u"NIR", default='', blank=True)
792d07a1 Benjamin Dauvergne
patient_birthdate = models.DateField(verbose_name=u"Date de naissance",
null=True, blank=True)
patient_twinning_rank = models.IntegerField(
verbose_name=u"Rang (gémellité)",
null=True, blank=True)
patient_healthcenter = models.ForeignKey('ressources.HealthCenter',
verbose_name=u"Centre d'assurance maladie",
related_name='related_by_patient_invoices',
null=True, blank=True)
f28b22e1 Benjamin Dauvergne
patient_entry_date = models.DateField(verbose_name=u'Date d\'entrée du patient',
blank=True, null=True)
patient_exit_date = models.DateField(verbose_name=u'Date de sortie du patient',
blank=True, null=True)
792d07a1 Benjamin Dauvergne
patient_other_health_center = models.CharField(
05cadd08 Benjamin Dauvergne
verbose_name=u"Centre spécifique", max_length=4, default='',
blank=True)
792d07a1 Benjamin Dauvergne
# policy holder informations
policy_holder_id = models.IntegerField(blank=True, null=True)
policy_holder_last_name = models.CharField(max_length=128,
05cadd08 Benjamin Dauvergne
verbose_name=u'Nom de l\'assuré', default='', blank=True)
792d07a1 Benjamin Dauvergne
policy_holder_first_name = models.CharField(max_length=128,
05cadd08 Benjamin Dauvergne
verbose_name=u'Prénom(s) de l\' assuré', default='', blank=True)
792d07a1 Benjamin Dauvergne
policy_holder_social_security_id = models.CharField(max_length=13,
05cadd08 Benjamin Dauvergne
verbose_name=u"NIR de l\'assuré", default='', blank=True)
792d07a1 Benjamin Dauvergne
policy_holder_healthcenter = models.ForeignKey('ressources.HealthCenter',
verbose_name=u"Centre d'assurance maladie de l\'assuré",
related_name='related_by_policy_holder_invoices',
null=True, blank=True)
2a0a0f7c Thomas NOEL
policy_holder_other_health_center = models.CharField(
verbose_name=u"Centre spécifique de l\'assuré", max_length=4,
default='', blank=True)
05cadd08 Benjamin Dauvergne
policy_holder_address = models.CharField(max_length=128,
verbose_name=u'Adresse de l\'assuré', default='', blank=True)
e2e4192d Mikaël Ates
policy_holder_management_code = models.CharField(max_length=10,
verbose_name=u'Code de gestion', default='', blank=True)
policy_holder_management_code_name = models.CharField(max_length=256,
verbose_name=u'Libellé du code de gestion', default='', blank=True)
05cadd08 Benjamin Dauvergne
3ac2302c Mikaël Ates
created = models.DateTimeField(u'Création', auto_now_add=True)
invoicing = models.ForeignKey('facturation.Invoicing',
b63305ca Mikaël Ates
on_delete=models.PROTECT)
3ac2302c Mikaël Ates
acts = models.ManyToManyField('actes.Act')
1434dd83 Mikaël Ates
list_dates = models.CharField(max_length=2048, blank=True, null=True)
5962e6b7 Mikaël Ates
first_tag = models.CharField(max_length=128, blank=True, null=True)
3ac2302c Mikaël Ates
amount = models.IntegerField()
ppa = models.IntegerField()
273ce9f1 Mikaël Ates
rejected = models.BooleanField(verbose_name=u"Rejeté", default=False)
3ac2302c Mikaël Ates
def save(self, *args, **kwargs):
f283921f Thomas NOEL
if not self.number:
invoicing = self.invoicing
self.number = invoicing.seq_id * 1000000 + 1
max_number = invoicing.invoice_set.aggregate(Max('number'))['number__max']
if max_number:
self.number = max_number + 1
3ac2302c Mikaël Ates
super(Invoice, self).save(*args, **kwargs)

80907767 Benjamin Dauvergne
@property
def start_date(self):
res = date.max
8386ed4d Mikaël Ates
for d in self.list_dates.split('$'):
date_o = datetime.strptime(d, '%d/%m/%Y').date()
res = min(res, date_o)
80907767 Benjamin Dauvergne
return res

792d07a1 Benjamin Dauvergne
@property
def health_center(self):
return self.policy_holder_healthcenter or self.patient_healthcenter

80907767 Benjamin Dauvergne
@property
def end_date(self):
res = date.min
8386ed4d Mikaël Ates
for d in self.list_dates.split('$'):
date_o = datetime.strptime(d, '%d/%m/%Y').date()
res = max(res, date_o)
80907767 Benjamin Dauvergne
return res

26c45baa Benjamin Dauvergne
@property
def decimal_amount(self):
b85f1d9a Benjamin Dauvergne
return Decimal(self.amount) / Decimal(100)

8386ed4d Mikaël Ates
@property
def decimal_amount_corrected(self):
amount = 0
for d, ppa in self.list_dates:
amount += ppa
return Decimal(amount) / Decimal(100)

b85f1d9a Benjamin Dauvergne
@property
def decimal_ppa(self):
return Decimal(self.ppa) / Decimal(100)
26c45baa Benjamin Dauvergne
3c517695 Benjamin Dauvergne
@property
def kind(self):
66910cbc Mikaël Ates
if not self.first_tag:
return None
return self.first_tag[0]
3c517695 Benjamin Dauvergne
18889f61 Benjamin Dauvergne
@property
def patient_social_security_id_full(self):
if self.patient_social_security_id:
return social_security_id_full(self.patient_social_security_id)
else:
return ''

@property
def policy_holder_social_security_id_full(self):
if self.policy_holder_social_security_id:
return social_security_id_full(self.policy_holder_social_security_id)
else:
return ''

3ac2302c Mikaël Ates
def __unicode__(self):
74d65534 Mikaël Ates
return "Facture %d de %d euros (%d actes)" % (self.number, self.amount, len(self.acts.all()))