Project

General

Profile

Download (12.1 KB) Statistics
| Branch: | Tag: | Revision:
# -*- coding: utf-8 -*-
import os
import os.path
import tempfile
import datetime
import textwrap
from decimal import Decimal
from collections import defaultdict

from xhtml2pdf.pisa import CreatePDF
from django.template import loader, Context

from invoice_template import InvoiceTemplate
from ..pdftk import PdfTk
from batches import build_batches
from calebasse.utils import get_nir_control_key

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)


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


def header_file(service, invoicing, health_center, batches,
header_service_template='facturation/bordereau-%s.html',
header_template='facturation/bordereau.html',
delete=False,
counter=None):
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 = {
'now': datetime.datetime.now(),
'health_center': health_center,
'service': service,
'batches': batches,
'synthesis': synthesis,
'counter': counter,
}
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)


def invoice_files(service, invoicing, batch, invoice, counter=None):
template_path = os.path.join(
os.path.dirname(__file__),
'static',
'facturation',
'invoice.pdf')
tpl = InvoiceTemplate(
template_path=template_path,
prefix='%s-invoicing-%s-invoice-%s-'
% ( service.slug, invoicing.id, invoice.id),
suffix='-%s.pdf' % datetime.datetime.now())
health_center = invoice.health_center
code_organisme = u'%s - %s %s' % (
health_center.large_regime.code,
health_center.dest_organism,
health_center.name)
address = textwrap.fill(invoice.policy_holder_address, 40)
if invoice.acts.all()[0].get_hc_tag()[0] == 'D':
subtitle = 'DIAGNOSTIC'
else:
subtitle = 'TRAITEMENT'
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
66/68, RUE MARENGO
42000 SAINT ETIENNE''' % service.name,
'DATE_ELABORATION': datetime.datetime.now().strftime('%d/%m/%Y'),
'NOM_BENEFICIAIRE': u' '.join((invoice.patient_first_name,
invoice.patient_last_name.upper())),
'NIR_BENEFICIAIRE': invoice.patient_social_security_id_full,
'DATE_NAISSANCE_RANG': u' '.join(
(unicode(invoice.patient_birthdate),
unicode(invoice.patient_twinning_rank))),
'CODE_ORGANISME': code_organisme,
'ABSENCE_SIGNATURE': True,
'ADRESSE_ASSURE': address,
'SUBTITLE': subtitle,
'PART_OBLIGATOIRE': True,
'PART_COMPLEMENTAIRE': True,
}
if counter is not None:
ctx['COUNTER'] = counter.increment()
if invoice.patient_entry_date is not None:
ctx['DATE_ENTREE'] = invoice.patient_entry_date.strftime('%d/%m/%Y')
if invoice.patient_exit_date is not None:
ctx['DATE_SORTIE'] = invoice.patient_exit_date.strftime('%d/%m/%Y')
if invoice.policy_holder_id != invoice.patient_id:
ctx.update({
'NOM_ASSURE': u' '.join((
invoice.policy_holder_first_name,
invoice.policy_holder_last_name.upper())),
'NIR_ASSURE': invoice.policy_holder_social_security_id_full,
})
total1 = Decimal(0)
total2 = Decimal(0)
acts = invoice.acts.order_by('date')
if len(acts) > 24:
raise RuntimeError('Too much acts in invoice %s' % invoice.id)
tableau1 = []
tableau2 = []
for act in acts[:12]:
hc_tag = act.get_hc_tag()
prestation = u'SNS' if hc_tag.startswith('T') else u'SD'
d = act.date.strftime('%d/%m/%Y')
total1 += invoice.decimal_ppa
tableau1.append([u'19', u'320', prestation, d, d, invoice.decimal_ppa,
1, invoice.decimal_ppa, act.get_hc_tag()])
for act in acts[12:24]:
hc_tag = act.get_hc_tag()
prestation = u'SNS' if hc_tag.startswith('T') else u'SD'
d = act.date.strftime('%d/%m/%Y')
total2 += invoice.decimal_ppa
tableau2.append([u'19', u'320', prestation, d, d, invoice.decimal_ppa,
1, invoice.decimal_ppa, act.get_hc_tag()])
ctx.update({
'TABLEAU1': tableau1,
'TABLEAU2': tableau2,
})
ctx['SOUS_TOTAL1'] = total1
if total2 != Decimal(0):
ctx['SOUS_TOTAL2'] = total2
assert invoice.decimal_amount == (total1+total2), "decimal_amount(%s) != " \
"total1+total2(%s), ppa: %s len(acts): %s" % (invoice.decimal_amount,
total1+total2, invoice.ppa, len(acts))
ctx['TOTAL'] = total1+total2
return [tpl.generate(ctx)]

def render_not_cmpp_header(invoicing):
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)

def render_not_cmpp_content(invoicing):
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 = ''
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
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 = ''
if invoice.patient_last_name:
name = invoice.patient_last_name.upper()
if invoice.patient_first_name:
name += ' ' + invoice.patient_first_name
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()})
list_patients.sort(key=lambda dic: dic['policy_holder'])
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)


def render_invoicing(invoicing, delete=False, headers=True, invoices=True):
service = invoicing.service
now = datetime.datetime.now()
output_file = None
all_files = []
try:
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:
header = render_not_cmpp_header(invoicing)
all_files.append(header)
content = render_not_cmpp_content(invoicing)
all_files.append(content)
output_file = tempfile.NamedTemporaryFile(prefix='%s-invoicing-%s-' %
(service.slug, invoicing.id), suffix='-%s.pdf' % now, delete=False)
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:
for path in all_files:
try:
os.unlink(path)
except:
pass


def batches_files(service, invoicing, health_center, batches, delete=False,
headers=True, invoices=True, counter=None):
files = []
try:
if headers:
files.append(header_file(service, invoicing, health_center,
batches, delete=delete, counter=counter))

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
files.extend(invoice_files(service, invoicing, batch, invoice, counter=counter))
return files
except:
# cleanup
if delete:
for path in files:
try:
os.unlink(path)
except:
pass
raise
(6-6/14)