Project

General

Profile

Download (13.7 KB) Statistics
| Branch: | Tag: | Revision:
591ca598 Benjamin Dauvergne
# -*- coding: utf-8 -*-
0d5f763c Jérôme Schneider
import datetime
import logging
fa500e83 Benjamin Dauvergne
import os
591ca598 Benjamin Dauvergne
import os.path
import tempfile
2584bbc9 Benjamin Dauvergne
import textwrap
0d5f763c Jérôme Schneider
591ca598 Benjamin Dauvergne
from decimal import Decimal
from collections import defaultdict

from xhtml2pdf.pisa import CreatePDF
fa500e83 Benjamin Dauvergne
from django.template import loader, Context
93844deb Mikaël Ates
from django.conf import settings
591ca598 Benjamin Dauvergne
from invoice_template import InvoiceTemplate
from ..pdftk import PdfTk
ceb458a3 Benjamin Dauvergne
from batches import build_batches
2f2a7de9 Mikaël Ates
from calebasse.utils import get_nir_control_key
80f2dbfe Benjamin Dauvergne
0d5f763c Jérôme Schneider
logger = logging.getLogger(__name__)
c743d1bf Mikaël Ates
80f2dbfe Benjamin Dauvergne
class Counter(object):
def __init__(self, initial_value=0):
self.counter = initial_value

def increment(self):
self.counter += 1
return (self.counter-1)

def __str__(self):
return str(self.counter)
591ca598 Benjamin Dauvergne
fa500e83 Benjamin Dauvergne
def render_to_pdf_file(templates, ctx, prefix='tmp', delete=False):
temp = tempfile.NamedTemporaryFile(prefix=prefix, suffix='.pdf',
delete=False)
try:
t = loader.select_template(templates)
html = t.render(Context(ctx))
CreatePDF(html, temp)
temp.flush()
return temp.name
except:
if delete:
try:
os.unlink(temp.name)
except:
pass
raise

81e91620 Serghei MIHAI
0f05168e Serghei MIHAI
def price_details(service, invoicing,
header_service_template = 'facturation/bordereau-%s.html',
header_template = 'facturation/prices-details.html',
delete = False):
2ef43cdf Serghei MIHAI
context = {'invoicings': invoicing.get_stats_per_price_per_year()}
return render_to_pdf_file((header_service_template % service.slug,
header_template),
context,
delete = delete)

fa500e83 Benjamin Dauvergne
def header_file(service, invoicing, health_center, batches,
header_service_template='facturation/bordereau-%s.html',
header_template='facturation/bordereau.html',
80f2dbfe Benjamin Dauvergne
delete=False,
counter=None):
591ca598 Benjamin Dauvergne
synthesis = {
'total': sum(batch.total for batch in batches),
'number_of_acts': sum(batch.number_of_acts for batch in batches),
'number_of_invoices': sum(batch.number_of_invoices for batch in batches),
}
ctx = {
fa500e83 Benjamin Dauvergne
'now': datetime.datetime.now(),
'health_center': health_center,
591ca598 Benjamin Dauvergne
'service': service,
'batches': batches,
'synthesis': synthesis,
80f2dbfe Benjamin Dauvergne
'counter': counter,
591ca598 Benjamin Dauvergne
}
2ef43cdf Serghei MIHAI
fa500e83 Benjamin Dauvergne
prefix = '%s-invoicing-%s-healthcenter-%s-' % (
service.slug, invoicing.id, health_center.id)
return render_to_pdf_file(
(header_service_template % service.slug,
header_template), ctx, prefix=prefix, delete=delete)
591ca598 Benjamin Dauvergne
fa500e83 Benjamin Dauvergne
80f2dbfe Benjamin Dauvergne
def invoice_files(service, invoicing, batch, invoice, counter=None):
591ca598 Benjamin Dauvergne
template_path = os.path.join(
os.path.dirname(__file__),
'static',
'facturation',
'invoice.pdf')
fa500e83 Benjamin Dauvergne
tpl = InvoiceTemplate(
template_path=template_path,
prefix='%s-invoicing-%s-invoice-%s-'
% ( service.slug, invoicing.id, invoice.id),
suffix='-%s.pdf' % datetime.datetime.now())
7c757f94 Benjamin Dauvergne
health_center = invoice.health_center
code_organisme = u'%s - %s %s' % (
health_center.large_regime.code,
health_center.dest_organism,
health_center.name)
2584bbc9 Benjamin Dauvergne
address = textwrap.fill(invoice.policy_holder_address, 40)
0074915c Mikaël Ates
if not invoice.first_tag:
subtitle = 'INDEFINI'
elif invoice.first_tag[0] == 'D':
80f2dbfe Benjamin Dauvergne
subtitle = 'DIAGNOSTIC'
else:
subtitle = 'TRAITEMENT'
7c757f94 Benjamin Dauvergne
ctx = {
'NUM_FINESS': '420788606',
'NUM_LOT': unicode(batch.number),
'NUM_FACTURE': unicode(invoice.number),
'NUM_ENTREE': unicode(invoice.patient_id),
'IDENTIFICATION_ETABLISSEMENT': '''%s SAINT ETIENNE
591ca598 Benjamin Dauvergne
66/68, RUE MARENGO
7c757f94 Benjamin Dauvergne
42000 SAINT ETIENNE''' % service.name,
'DATE_ELABORATION': datetime.datetime.now().strftime('%d/%m/%Y'),
'NOM_BENEFICIAIRE': u' '.join((invoice.patient_first_name,
80f2dbfe Benjamin Dauvergne
invoice.patient_last_name.upper())),
18889f61 Benjamin Dauvergne
'NIR_BENEFICIAIRE': invoice.patient_social_security_id_full,
7c757f94 Benjamin Dauvergne
'DATE_NAISSANCE_RANG': u' '.join(
(unicode(invoice.patient_birthdate),
unicode(invoice.patient_twinning_rank))),
'CODE_ORGANISME': code_organisme,
'ABSENCE_SIGNATURE': True,
80f2dbfe Benjamin Dauvergne
'ADRESSE_ASSURE': address,
'SUBTITLE': subtitle,
73aae71e Benjamin Dauvergne
'PART_OBLIGATOIRE': True,
'PART_COMPLEMENTAIRE': True,
7c757f94 Benjamin Dauvergne
}
80f2dbfe Benjamin Dauvergne
if counter is not None:
ctx['COUNTER'] = counter.increment()
fa500e83 Benjamin Dauvergne
if invoice.patient_entry_date is not None:
7c757f94 Benjamin Dauvergne
ctx['DATE_ENTREE'] = invoice.patient_entry_date.strftime('%d/%m/%Y')
fa500e83 Benjamin Dauvergne
if invoice.patient_exit_date is not None:
7c757f94 Benjamin Dauvergne
ctx['DATE_SORTIE'] = invoice.patient_exit_date.strftime('%d/%m/%Y')
80f2dbfe Benjamin Dauvergne
if invoice.policy_holder_id != invoice.patient_id:
7c757f94 Benjamin Dauvergne
ctx.update({
'NOM_ASSURE': u' '.join((
invoice.policy_holder_first_name,
80f2dbfe Benjamin Dauvergne
invoice.policy_holder_last_name.upper())),
18889f61 Benjamin Dauvergne
'NIR_ASSURE': invoice.policy_holder_social_security_id_full,
7c757f94 Benjamin Dauvergne
})
591ca598 Benjamin Dauvergne
total1 = Decimal(0)
total2 = Decimal(0)
7c757f94 Benjamin Dauvergne
tableau1 = []
tableau2 = []
0074915c Mikaël Ates
dates = []
if invoice.list_dates:
dates = invoice.list_dates.split('$')
if dates:
15f04e07 Mikaël Ates
if len(dates) > 30:
0074915c Mikaël Ates
raise RuntimeError('Too much acts in invoice %s' % invoice.id)
kind = 'X'
offset = 0
prestation = u'X'
if invoice.first_tag:
kind = invoice.first_tag[0]
offset = int(invoice.first_tag[1:])
prestation = u'SNS' if kind == 'T' else u'SD'
15f04e07 Mikaël Ates
for date in dates[:15]:
0074915c Mikaël Ates
tableau1.append([u'19', u'320', prestation, date, date,
invoice.decimal_ppa, 1, invoice.decimal_ppa, kind + str(offset)])
total1 += invoice.decimal_ppa
offset += 1
15f04e07 Mikaël Ates
for date in dates[15:30]:
0074915c Mikaël Ates
tableau2.append([u'19', u'320', prestation, date, date,
invoice.decimal_ppa, 1, invoice.decimal_ppa, kind + str(offset)])
total2 += invoice.decimal_ppa
offset += 1
7c757f94 Benjamin Dauvergne
ctx.update({
'TABLEAU1': tableau1,
'TABLEAU2': tableau2,
})
ctx['SOUS_TOTAL1'] = total1
591ca598 Benjamin Dauvergne
if total2 != Decimal(0):
7c757f94 Benjamin Dauvergne
ctx['SOUS_TOTAL2'] = total2
278102b7 Mikaël Ates
ctx['TOTAL'] = invoice.decimal_amount
c0c89c25 Serghei MIHAI
try:
repeat = settings.BATCH_CONTENT_TIMES_IN_INVOINCING_FILE
except:
repeat = 1

output = tpl.generate(ctx)
return [output for i in xrange(repeat)]
fa500e83 Benjamin Dauvergne
98f6a43c Mikaël Ates
def render_not_cmpp_header(invoicing):
2f2a7de9 Mikaël Ates
header_template='facturation/bordereau_not_cmpp_header.html'
management_codes = dict()
total_acts = 0
for invoice in invoicing.invoice_set.all():
total_acts += invoice.acts.count()
if invoice.policy_holder_management_code:
management_codes.setdefault(invoice.policy_holder_management_code, []).append(invoice)
list_management_codes = list()
for mc, invoices in management_codes.iteritems():
dic = dict()
dic['code'] = mc
dic['title'] = invoices[0].policy_holder_management_code_name
dic['nb_files'] = len(invoices)
nb_acts = 0
for invoice in invoices:
nb_acts += invoice.acts.count()
dic['nb_acts'] = nb_acts
list_management_codes.append(dic)
list_management_codes.sort(key=lambda dic: dic['code'])
ctx = {
'now': datetime.datetime.now(),
'service': invoicing.service,
'start_date': invoicing.start_date,
'end_date': invoicing.end_date,
'list_management_codes': list_management_codes,
'total_files': invoicing.invoice_set.count(),
'total_acts': total_acts
}
prefix = '%s-invoicing-header-%s' % (
invoicing.service.slug, invoicing.id)
return render_to_pdf_file(
(header_template, ), ctx, prefix=prefix, delete=True)

98f6a43c Mikaël Ates
def render_not_cmpp_content(invoicing):
2f2a7de9 Mikaël Ates
header_template='facturation/bordereau_not_cmpp_content.html'
total_acts = 0
list_patients = list()
for invoice in invoicing.invoice_set.all():
total_acts += invoice.acts.count()
policy_holder = ''
98f6a43c Mikaël Ates
if invoice.policy_holder_last_name:
policy_holder = invoice.policy_holder_last_name.upper()
if invoice.policy_holder_first_name:
policy_holder += ' ' + invoice.policy_holder_first_name
2f2a7de9 Mikaël Ates
nir = None
if invoice.policy_holder_social_security_id:
nir = invoice.policy_holder_social_security_id + ' ' + str(get_nir_control_key(invoice.policy_holder_social_security_id))
health_center = ''
tp = ''
cai = ''
if invoice.policy_holder_healthcenter:
health_center = invoice.policy_holder_healthcenter.name
if invoice.policy_holder_healthcenter.large_regime:
tp = invoice.policy_holder_healthcenter.large_regime.code
cai = invoice.policy_holder_healthcenter.health_fund
name = ''
98f6a43c Mikaël Ates
if invoice.patient_last_name:
name = invoice.patient_last_name.upper()
if invoice.patient_first_name:
name += ' ' + invoice.patient_first_name
2f2a7de9 Mikaël Ates
list_patients.append({\
'code' : invoice.policy_holder_management_code,
'policy_holder': policy_holder,
'nir': nir,
'health_center': health_center,
'tp': tp,
'cai': cai,
'cen': invoice.policy_holder_other_health_center,
'number': invoice.patient_id,
'name': name,
'birth_date': invoice.patient_birthdate,
'inscription_date': invoice.patient_entry_date,
'sortie_date': invoice.patient_exit_date,
'nb_actes': invoice.acts.count()})
74da1939 Mikaël Ates
list_patients.sort(key=lambda dic: dic['policy_holder'])
2f2a7de9 Mikaël Ates
ctx = {
'now': datetime.datetime.now(),
'service': invoicing.service,
'start_date': invoicing.start_date,
'end_date': invoicing.end_date,
'total_files': invoicing.invoice_set.count(),
'total_acts': total_acts,
'patients': list_patients
}
prefix = '%s-invoicing-content-%s' % (
invoicing.service.slug, invoicing.id)
return render_to_pdf_file(
(header_template, ), ctx, prefix=prefix, delete=True)

591ca598 Benjamin Dauvergne
dc3ed94e Benjamin Dauvergne
def render_invoicing(invoicing, delete=False, headers=True, invoices=True):
f3ce8efd Benjamin Dauvergne
service = invoicing.service
fa500e83 Benjamin Dauvergne
now = datetime.datetime.now()
output_file = None
0f05168e Serghei MIHAI
all_files = [price_details(service, invoicing)]
fa500e83 Benjamin Dauvergne
try:
2f2a7de9 Mikaël Ates
if service.name == 'CMPP':
batches_by_health_center = build_batches(invoicing)
centers = sorted(batches_by_health_center.keys())
counter = Counter(1)
for center in centers:
if headers is not True and headers is not False and headers != center:
continue
for batch in batches_by_health_center[center]:
files = batches_files(service, invoicing, center,
[batch], delete=delete,
headers=headers, invoices=invoices, counter=counter)
all_files.extend(files)
else:
98f6a43c Mikaël Ates
header = render_not_cmpp_header(invoicing)
2f2a7de9 Mikaël Ates
all_files.append(header)
98f6a43c Mikaël Ates
content = render_not_cmpp_content(invoicing)
2f2a7de9 Mikaël Ates
all_files.append(content)
93844deb Mikaël Ates
output_file = None
0d5f763c Jérôme Schneider
if settings.INVOICING_DIRECTORY and not os.path.exists(settings.INVOICING_DIRECTORY):
logger.warning("INVOICING_DIRECTORY %r doesn't exist" % settings.INVOICING_DIRECTORY)
elif settings.INVOICING_DIRECTORY:
1e5246ef Mikaël Ates
to_path = os.path.join(settings.INVOICING_DIRECTORY, service.name)
26bdc73e Mikaël Ates
if not os.path.exists(to_path):
os.makedirs(to_path)
to_path = os.path.join(to_path, '%s-facturation-%s-%s.pdf' \
% (service.slug, invoicing.seq_id, now.strftime('%d%m%Y-%H%M')))
output_file = open(to_path, 'w')
c743d1bf Mikaël Ates
if not output_file:
93844deb Mikaël Ates
output_file = tempfile.NamedTemporaryFile(prefix='%s-invoicing-%s-' %
(service.slug, invoicing.id), suffix='-%s.pdf' % now, delete=False)
fa500e83 Benjamin Dauvergne
pdftk = PdfTk()
pdftk.concat(all_files, output_file.name)
return output_file.name
except:
if delete and output_file:
try:
os.unlink(output_file.name)
except:
pass
raise
finally:
# eventual cleanup
if delete:
7c757f94 Benjamin Dauvergne
for path in all_files:
fa500e83 Benjamin Dauvergne
try:
os.unlink(path)
except:
pass
591ca598 Benjamin Dauvergne

dc3ed94e Benjamin Dauvergne
def batches_files(service, invoicing, health_center, batches, delete=False,
80f2dbfe Benjamin Dauvergne
headers=True, invoices=True, counter=None):
591ca598 Benjamin Dauvergne
files = []
fa500e83 Benjamin Dauvergne
try:
dc3ed94e Benjamin Dauvergne
if headers:
c0c89c25 Serghei MIHAI
header = header_file(service, invoicing, health_center, batches,
delete=delete, counter=counter)

try:
repeat = settings.BATCH_HEADER_TIMES_IN_INVOICING_FILE
except:
repeat = 1
map(lambda el: files.append(header), xrange(repeat))
dc3ed94e Benjamin Dauvergne
if invoices:
for batch in batches:
for invoice in batch.invoices:
# if invoices is a sequence, skip unlisted invoices
if invoices is not True and invoice not in invoices:
continue
c0c89c25 Serghei MIHAI
80f2dbfe Benjamin Dauvergne
files.extend(invoice_files(service, invoicing, batch, invoice, counter=counter))
7c757f94 Benjamin Dauvergne
return files
fa500e83 Benjamin Dauvergne
except:
# cleanup
if delete:
7c757f94 Benjamin Dauvergne
for path in files:
fa500e83 Benjamin Dauvergne
try:
os.unlink(path)
except:
pass
raise