Compare commits
3 Commits
master
...
regularisa
Author | SHA1 | Date |
---|---|---|
Mikaël Ates | abad50d552 | |
Mikaël Ates | 2cc55ddace | |
Mikaël Ates | 8bc46b58a8 |
|
@ -16,7 +16,7 @@ from calebasse.facturation.models import Invoicing
|
|||
from batches import build_batches
|
||||
from transmission_utils import build_mail
|
||||
|
||||
DEFAULT_OUTPUT_DIRECTORY = '/var/lib/calebasse/B2'
|
||||
DEFAULT_OUTPUT_DIRECTORY = '/Donnees/devs/aps42/travail_sur_stats/b2_test/'
|
||||
DEFAULT_NORME = 'CP '
|
||||
DEFAULT_TYPE_EMETTEUR = 'TE'
|
||||
DEFAULT_APPLICATION = 'TR'
|
||||
|
@ -24,6 +24,8 @@ DEFAULT_CATEGORIE = '189'
|
|||
DEFAULT_STATUT = '60'
|
||||
DEFAULT_MODE_TARIF = '05'
|
||||
DEFAULT_MESSAGE = 'ENTROUVERT 0143350135 CALEBASSE 1307'
|
||||
DEFAULT_NUMERO_EMETTEUR = '123456789'
|
||||
DEFAULT_NOM = 'TBD'
|
||||
|
||||
# B2 informations / configuration
|
||||
# from settings.py :
|
||||
|
@ -44,14 +46,14 @@ except (ImportError, AttributeError):
|
|||
NORME = b2_transmission_settings.get('norme', DEFAULT_NORME)
|
||||
|
||||
TYPE_EMETTEUR = b2_transmission_settings.get('type_emetteur', DEFAULT_TYPE_EMETTEUR)
|
||||
NUMERO_EMETTEUR = b2_transmission_settings.get('numero_emetteur')
|
||||
NUMERO_EMETTEUR = b2_transmission_settings.get('numero_emetteur', DEFAULT_NUMERO_EMETTEUR)
|
||||
APPLICATION = b2_transmission_settings.get('application', DEFAULT_APPLICATION)
|
||||
|
||||
CATEGORIE = b2_transmission_settings.get('categorie', DEFAULT_CATEGORIE)
|
||||
STATUT = b2_transmission_settings.get('statut', DEFAULT_STATUT)
|
||||
MODE_TARIF = b2_transmission_settings.get('mode_tarif', DEFAULT_MODE_TARIF)
|
||||
|
||||
NOM = b2_transmission_settings.get('nom', '')[:40]
|
||||
NOM = b2_transmission_settings.get('nom', DEFAULT_NOM)[:40]
|
||||
NOM = NOM + ' '*(40-len(NOM))
|
||||
|
||||
MESSAGE = b2_transmission_settings.get('message', DEFAULT_MESSAGE)[:37]
|
||||
|
@ -119,69 +121,97 @@ def write128(output_file, line):
|
|||
(len(line), line))
|
||||
output_file.write(line)
|
||||
|
||||
def write_invoice(output_file, invoice):
|
||||
def write_invoice(output_file, invoice, operation='1', list_acts_prices=None):
|
||||
invoice_lines = 0
|
||||
start_date = invoice.start_date
|
||||
start_2 = '2' + NUMERO_EMETTEUR + ' ' + \
|
||||
invoice.policy_holder_social_security_id + \
|
||||
get_control_key(invoice.policy_holder_social_security_id) + \
|
||||
'000' + ('%0.9d' % invoice.number) + \
|
||||
'1' + ('%0.9d' % invoice.patient_id) + \
|
||||
invoice.policy_holder_healthcenter.large_regime.code + \
|
||||
invoice.policy_holder_healthcenter.dest_organism + \
|
||||
(invoice.policy_holder_other_health_center or '0000') + \
|
||||
'3' + b2date(start_date) + '000000' + \
|
||||
invoice.policy_holder_healthcenter.dest_organism + '000' + \
|
||||
'10' + '3' + \
|
||||
b2date(start_date) + \
|
||||
'000000000' + ' ' + \
|
||||
b2date(invoice.patient_birthdate) + \
|
||||
('%d' % invoice.patient_twinning_rank)[-1:] + \
|
||||
b2date(start_date) + b2date(invoice.end_date) + '01' + \
|
||||
'00' + filler(10)
|
||||
write128(output_file, start_2)
|
||||
invoice_lines += 1
|
||||
nb_type3 = 0
|
||||
kind = invoice.first_tag[0]
|
||||
prestation = u'SNS ' if kind == 'T' else u'SD '
|
||||
for date in invoice.list_dates.split('$'):
|
||||
line_3 = '3' + NUMERO_EMETTEUR + ' ' + \
|
||||
try:
|
||||
start_date = invoice.start_date
|
||||
start_2 = '2' + NUMERO_EMETTEUR + ' ' + \
|
||||
invoice.policy_holder_social_security_id + \
|
||||
get_control_key(invoice.policy_holder_social_security_id) + \
|
||||
'000' + ('%0.9d' % invoice.number) + \
|
||||
'19' + '320' + \
|
||||
b2date(datetime.datetime.strptime(date, "%d/%m/%Y")) + \
|
||||
b2date(datetime.datetime.strptime(date, "%d/%m/%Y")) + \
|
||||
prestation + '001' + \
|
||||
' ' + '00100' + ' ' + '00000' + \
|
||||
('%0.7d' % invoice.ppa) + \
|
||||
('%0.8d' % invoice.ppa) + \
|
||||
'100' + \
|
||||
('%0.8d' % invoice.ppa) + \
|
||||
('%0.8d' % invoice.ppa) + \
|
||||
'0000' + '000' + ' ' + filler(2) + ' ' + \
|
||||
' ' + '0000000'
|
||||
write128(output_file, line_3)
|
||||
operation + ('%0.9d' % invoice.patient_id) + \
|
||||
invoice.policy_holder_healthcenter.large_regime.code + \
|
||||
invoice.policy_holder_healthcenter.dest_organism + \
|
||||
(invoice.policy_holder_other_health_center or '0000') + \
|
||||
'3' + b2date(start_date) + '000000' + \
|
||||
invoice.policy_holder_healthcenter.dest_organism + '000' + \
|
||||
'10' + '3' + \
|
||||
b2date(start_date) + \
|
||||
'000000000' + ' ' + \
|
||||
b2date(invoice.patient_birthdate) + \
|
||||
('%d' % invoice.patient_twinning_rank)[-1:] + \
|
||||
b2date(start_date) + b2date(invoice.end_date) + '01' + \
|
||||
'00' + filler(10)
|
||||
# print "type2 : invoice.number %d" % invoice.number
|
||||
write128(output_file, start_2)
|
||||
invoice_lines += 1
|
||||
nb_type3 += 1
|
||||
nb_type3 = 0
|
||||
kind = invoice.first_tag[0]
|
||||
prestation = u'SNS ' if kind == 'T' else u'SD '
|
||||
if operation == '4' and list_acts_prices:
|
||||
for date, ppa in list_acts_prices:
|
||||
line_3 = '3' + NUMERO_EMETTEUR + ' ' + \
|
||||
invoice.policy_holder_social_security_id + \
|
||||
get_control_key(invoice.policy_holder_social_security_id) + \
|
||||
'000' + ('%0.9d' % invoice.number) + \
|
||||
'19' + '320' + \
|
||||
b2date(datetime.datetime.strptime(date, "%d/%m/%Y")) + \
|
||||
b2date(datetime.datetime.strptime(date, "%d/%m/%Y")) + \
|
||||
prestation + '001' + \
|
||||
' ' + '00100' + ' ' + '00000' + \
|
||||
('%0.7d' % ppa) + \
|
||||
('%0.8d' % ppa) + \
|
||||
'100' + \
|
||||
('%0.8d' % ppa) + \
|
||||
('%0.8d' % ppa) + \
|
||||
'0000' + '000' + ' ' + filler(2) + ' ' + \
|
||||
' ' + '0000000'
|
||||
write128(output_file, line_3)
|
||||
nb_type3 += 1
|
||||
invoice_lines += 1
|
||||
else:
|
||||
for date in invoice.list_dates.split('$'):
|
||||
line_3 = '3' + NUMERO_EMETTEUR + ' ' + \
|
||||
invoice.policy_holder_social_security_id + \
|
||||
get_control_key(invoice.policy_holder_social_security_id) + \
|
||||
'000' + ('%0.9d' % invoice.number) + \
|
||||
'19' + '320' + \
|
||||
b2date(datetime.datetime.strptime(date, "%d/%m/%Y")) + \
|
||||
b2date(datetime.datetime.strptime(date, "%d/%m/%Y")) + \
|
||||
prestation + '001' + \
|
||||
' ' + '00100' + ' ' + '00000' + \
|
||||
('%0.7d' % invoice.ppa) + \
|
||||
('%0.8d' % invoice.ppa) + \
|
||||
'100' + \
|
||||
('%0.8d' % invoice.ppa) + \
|
||||
('%0.8d' % invoice.ppa) + \
|
||||
'0000' + '000' + ' ' + filler(2) + ' ' + \
|
||||
' ' + '0000000'
|
||||
write128(output_file, line_3)
|
||||
nb_type3 += 1
|
||||
invoice_lines += 1
|
||||
# print "type3 : invoice.number %d" % invoice.number
|
||||
|
||||
end_5 = '5' + NUMERO_EMETTEUR + ' ' + \
|
||||
invoice.policy_holder_social_security_id + \
|
||||
get_control_key(invoice.policy_holder_social_security_id) + \
|
||||
'000' + ('%0.9d' % invoice.number) + \
|
||||
('%0.3d' % nb_type3) + \
|
||||
('%0.8d' % invoice.amount) + \
|
||||
('%0.8d' % invoice.amount) + \
|
||||
'00000000' + '00000000' + '00000000' + '00000000' + '00000000' + \
|
||||
filler(17) + \
|
||||
('%0.8d' % invoice.amount) + \
|
||||
filler(4+2)
|
||||
write128(output_file, end_5)
|
||||
invoice_lines += 1
|
||||
|
||||
end_5 = '5' + NUMERO_EMETTEUR + ' ' + \
|
||||
invoice.policy_holder_social_security_id + \
|
||||
get_control_key(invoice.policy_holder_social_security_id) + \
|
||||
'000' + ('%0.9d' % invoice.number) + \
|
||||
('%0.3d' % nb_type3) + \
|
||||
('%0.8d' % invoice.amount) + \
|
||||
('%0.8d' % invoice.amount) + \
|
||||
'00000000' + '00000000' + '00000000' + '00000000' + '00000000' + \
|
||||
filler(17) + \
|
||||
('%0.8d' % invoice.amount) + \
|
||||
filler(4+2)
|
||||
write128(output_file, end_5)
|
||||
invoice_lines += 1
|
||||
# print "type5 : invoice.amount %d" % invoice.amount
|
||||
except Exception, e:
|
||||
print "Invoice (ID: %d, number: %d) generation error: %s" % (invoice.id, invoice.number, e)
|
||||
return invoice_lines
|
||||
|
||||
def b2(seq_id, hc, batches):
|
||||
def b2(seq_id, hc, batches, adj_date=None, adj_price=None):
|
||||
to = hc.b2_000()
|
||||
total = sum(b.total for b in batches)
|
||||
first_batch = min(b.number for b in batches)
|
||||
|
@ -228,6 +258,7 @@ def b2(seq_id, hc, batches):
|
|||
' ' + '062007' + 'U' + filler(2+3+1+34)
|
||||
write128(output_file, start_1)
|
||||
nb_lines += 1
|
||||
# print "type1 : batch.number %d" % batch.number
|
||||
|
||||
infos['batches'].append({
|
||||
'batch': batch.number,
|
||||
|
@ -237,8 +268,30 @@ def b2(seq_id, hc, batches):
|
|||
'number_of_acts': batch.number_of_acts
|
||||
})
|
||||
|
||||
for i in batch.invoices:
|
||||
nb_lines += write_invoice(output_file, i)
|
||||
if adj_date and adj_price:
|
||||
for i in batch.invoices:
|
||||
nb_lines += write_invoice(output_file, i, operation='5')
|
||||
i.number += 1
|
||||
list_acts_prices = list()
|
||||
amount = 0
|
||||
for date in i.list_dates.split('$'):
|
||||
date_o = datetime.datetime.strptime(date, '%d/%m/%Y')
|
||||
price = None
|
||||
if date_o < adj_date:
|
||||
price = i.ppa
|
||||
else:
|
||||
price = adj_price
|
||||
amount += price
|
||||
list_acts_prices.append((date, price))
|
||||
a_tmp = i.amount
|
||||
i.amount = amount
|
||||
nb_lines += write_invoice(output_file, i, operation='4',
|
||||
list_acts_prices=list_acts_prices)
|
||||
i.amount = a_tmp
|
||||
i.number -= 1
|
||||
else:
|
||||
for i in batch.invoices:
|
||||
nb_lines += write_invoice(output_file, i)
|
||||
|
||||
end_6 = '6' + NUMERO_EMETTEUR + \
|
||||
('%0.3d' % batch.number_of_invoices) + \
|
||||
|
@ -252,6 +305,7 @@ def b2(seq_id, hc, batches):
|
|||
write128(output_file, end_6)
|
||||
nb_lines += 1
|
||||
nb_batches += 1
|
||||
# print "type6 : batch.number_of_invoices %d batch.number_of_acts %d batch.total %d" % (batch.number_of_invoices, batch.number_of_acts, batch.total)
|
||||
|
||||
if nb_lines > 990:
|
||||
raise
|
||||
|
|
|
@ -15,6 +15,7 @@ from invoice_template import InvoiceTemplate
|
|||
from ..pdftk import PdfTk
|
||||
from batches import build_batches
|
||||
from calebasse.utils import get_nir_control_key
|
||||
from calebasse.ressources.models import Service
|
||||
|
||||
|
||||
class Counter(object):
|
||||
|
@ -62,7 +63,26 @@ def header_file(service, invoicing, health_center, batches,
|
|||
header_service_template='facturation/bordereau-%s.html',
|
||||
header_template='facturation/bordereau.html',
|
||||
delete=False,
|
||||
counter=None):
|
||||
counter=None,
|
||||
adj_date=None, adj_price=None, seq_id=0):
|
||||
|
||||
if adj_date and adj_price:
|
||||
for batch in batches:
|
||||
invoices_n = list()
|
||||
amount = 0
|
||||
for i in batch.invoices:
|
||||
acts = list()
|
||||
for date in i.list_dates.split('$'):
|
||||
date_o = datetime.datetime.strptime(date, '%d/%m/%Y')
|
||||
if date_o >= adj_date:
|
||||
amount = amount + adj_price - i.ppa
|
||||
price = None
|
||||
if date_o < adj_date:
|
||||
price = i.ppa
|
||||
else:
|
||||
price = adj_price
|
||||
acts.append((date, price))
|
||||
i.list_dates = acts
|
||||
synthesis = {
|
||||
'total': sum(batch.total for batch in batches),
|
||||
'number_of_acts': sum(batch.number_of_acts for batch in batches),
|
||||
|
@ -76,24 +96,30 @@ def header_file(service, invoicing, health_center, batches,
|
|||
'synthesis': synthesis,
|
||||
'counter': counter,
|
||||
}
|
||||
|
||||
if adj_date and adj_price:
|
||||
ctx['adjustment'] = True
|
||||
if invoicing:
|
||||
seq_id = invoicing.id
|
||||
prefix = '%s-invoicing-%s-healthcenter-%s-' % (
|
||||
service.slug, invoicing.id, health_center.id)
|
||||
service.slug, seq_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):
|
||||
def invoice_files(service, invoicing, batch, invoice, counter=None,
|
||||
adjustment=False, seq_id=0):
|
||||
template_path = os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
'static',
|
||||
'facturation',
|
||||
'invoice.pdf')
|
||||
if invoicing:
|
||||
seq_id = invoicing.id
|
||||
tpl = InvoiceTemplate(
|
||||
template_path=template_path,
|
||||
prefix='%s-invoicing-%s-invoice-%s-'
|
||||
% ( service.slug, invoicing.id, invoice.id),
|
||||
% ( service.slug, seq_id, invoice.number),
|
||||
suffix='-%s.pdf' % datetime.datetime.now())
|
||||
health_center = invoice.health_center
|
||||
code_organisme = u'%s - %s %s' % (
|
||||
|
@ -144,14 +170,14 @@ def invoice_files(service, invoicing, batch, invoice, counter=None):
|
|||
})
|
||||
total1 = Decimal(0)
|
||||
total2 = Decimal(0)
|
||||
total1_a = Decimal(0)
|
||||
total2_a = Decimal(0)
|
||||
tableau1 = []
|
||||
tableau2 = []
|
||||
tableau1_a = []
|
||||
tableau2_a = []
|
||||
dates = []
|
||||
if invoice.list_dates:
|
||||
dates = invoice.list_dates.split('$')
|
||||
if dates:
|
||||
if len(dates) > 30:
|
||||
raise RuntimeError('Too much acts in invoice %s' % invoice.id)
|
||||
if adjustment:
|
||||
kind = 'X'
|
||||
offset = 0
|
||||
prestation = u'X'
|
||||
|
@ -159,32 +185,77 @@ def invoice_files(service, invoicing, batch, invoice, counter=None):
|
|||
kind = invoice.first_tag[0]
|
||||
offset = int(invoice.first_tag[1:])
|
||||
prestation = u'SNS' if kind == 'T' else u'SD'
|
||||
for date in dates[:15]:
|
||||
for date, price in invoice.list_dates[:15]:
|
||||
tableau1.append([u'19', u'320', prestation, date, date,
|
||||
invoice.decimal_ppa, 1, invoice.decimal_ppa, kind + str(offset)])
|
||||
total1 += invoice.decimal_ppa
|
||||
(invoice.decimal_ppa * (-1)), 1, (invoice.decimal_ppa * (-1)), kind + str(offset)])
|
||||
total1 += (invoice.decimal_ppa * (-1))
|
||||
tableau1_a.append([u'19', u'320', prestation, date, date,
|
||||
Decimal(price) / Decimal(100), 1, Decimal(price) / Decimal(100), kind + str(offset)])
|
||||
total1_a += Decimal(price) / Decimal(100)
|
||||
offset += 1
|
||||
for date in dates[15:30]:
|
||||
for date, price in invoice.list_dates[15:30]:
|
||||
tableau2.append([u'19', u'320', prestation, date, date,
|
||||
invoice.decimal_ppa, 1, invoice.decimal_ppa, kind + str(offset)])
|
||||
total2 += invoice.decimal_ppa
|
||||
(invoice.decimal_ppa * (-1)), 1, (invoice.decimal_ppa * (-1)), kind + str(offset)])
|
||||
total2 += (invoice.decimal_ppa * (-1))
|
||||
tableau2_a.append([u'19', u'320', prestation, date, date,
|
||||
Decimal(price) / Decimal(100), 1, Decimal(price) / Decimal(100), kind + str(offset)])
|
||||
total2_a += Decimal(price) / Decimal(100)
|
||||
offset += 1
|
||||
else:
|
||||
if invoice.list_dates:
|
||||
dates = invoice.list_dates.split('$')
|
||||
if dates:
|
||||
if len(dates) > 30:
|
||||
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'
|
||||
for date in dates[:15]:
|
||||
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
|
||||
for date in dates[15:30]:
|
||||
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
|
||||
ctx.update({
|
||||
'TABLEAU1': tableau1,
|
||||
'TABLEAU2': tableau2,
|
||||
})
|
||||
ctx['SOUS_TOTAL1'] = total1
|
||||
if total2 != Decimal(0):
|
||||
ctx['SOUS_TOTAL2'] = total2
|
||||
ctx['TOTAL'] = invoice.decimal_amount
|
||||
if adjustment:
|
||||
ctx['SOUS_TOTAL1'] = total1
|
||||
if total2 != Decimal(0):
|
||||
ctx['SOUS_TOTAL2'] = total2
|
||||
ctx['TOTAL'] = total1 + total2
|
||||
neg = tpl.generate(ctx)
|
||||
ctx['TABLEAU1'] = tableau1_a
|
||||
ctx['TABLEAU2'] = tableau2_a
|
||||
ctx['SOUS_TOTAL1'] = total1_a
|
||||
if total2 != Decimal(0):
|
||||
ctx['SOUS_TOTAL2'] = total2_a
|
||||
ctx['TOTAL'] = total1_a + total2_a
|
||||
ctx['NUM_FACTURE'] = unicode(invoice.number + 1)
|
||||
pos = tpl.generate(ctx)
|
||||
return [neg, pos]
|
||||
else:
|
||||
ctx['SOUS_TOTAL1'] = total1
|
||||
if total2 != Decimal(0):
|
||||
ctx['SOUS_TOTAL2'] = total2
|
||||
ctx['TOTAL'] = invoice.decimal_amount
|
||||
|
||||
try:
|
||||
repeat = settings.BATCH_CONTENT_TIMES_IN_INVOINCING_FILE
|
||||
except:
|
||||
repeat = 1
|
||||
try:
|
||||
repeat = settings.BATCH_CONTENT_TIMES_IN_INVOINCING_FILE
|
||||
except:
|
||||
repeat = 1
|
||||
|
||||
output = tpl.generate(ctx)
|
||||
return [output for i in xrange(repeat)]
|
||||
output = tpl.generate(ctx)
|
||||
return [output for i in xrange(repeat)]
|
||||
|
||||
def render_not_cmpp_header(invoicing):
|
||||
header_template='facturation/bordereau_not_cmpp_header.html'
|
||||
|
@ -277,14 +348,24 @@ def render_not_cmpp_content(invoicing):
|
|||
(header_template, ), ctx, prefix=prefix, delete=True)
|
||||
|
||||
|
||||
def render_invoicing(invoicing, delete=False, headers=True, invoices=True):
|
||||
service = invoicing.service
|
||||
def render_invoicing(invoicing=None, delete=False, headers=True, invoices=True,
|
||||
batches_by_health_center=None,
|
||||
adj_date=None, adj_price=None, seq_id=0):
|
||||
service = None
|
||||
if not invoicing:
|
||||
service = Service.objects.get(name='CMPP')
|
||||
else:
|
||||
service = invoicing.service
|
||||
now = datetime.datetime.now()
|
||||
output_file = None
|
||||
all_files = [price_details(service, invoicing)]
|
||||
all_files = []
|
||||
if invoicing:
|
||||
all_files = [price_details(service, invoicing)]
|
||||
seq_id = invoicing.seq_id
|
||||
try:
|
||||
if service.name == 'CMPP':
|
||||
batches_by_health_center = build_batches(invoicing)
|
||||
if invoicing and not batches_by_health_center:
|
||||
batches_by_health_center = build_batches(invoicing)
|
||||
centers = sorted(batches_by_health_center.keys())
|
||||
counter = Counter(1)
|
||||
for center in centers:
|
||||
|
@ -293,7 +374,8 @@ def render_invoicing(invoicing, delete=False, headers=True, invoices=True):
|
|||
for batch in batches_by_health_center[center]:
|
||||
files = batches_files(service, invoicing, center,
|
||||
[batch], delete=delete,
|
||||
headers=headers, invoices=invoices, counter=counter)
|
||||
headers=headers, invoices=invoices, counter=counter,
|
||||
adj_date=adj_date, adj_price=adj_price)
|
||||
all_files.extend(files)
|
||||
else:
|
||||
header = render_not_cmpp_header(invoicing)
|
||||
|
@ -306,11 +388,11 @@ def render_invoicing(invoicing, delete=False, headers=True, invoices=True):
|
|||
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')))
|
||||
% (service.slug, seq_id, now.strftime('%d%m%Y-%H%M')))
|
||||
output_file = open(to_path, 'w')
|
||||
if not output_file:
|
||||
output_file = tempfile.NamedTemporaryFile(prefix='%s-invoicing-%s-' %
|
||||
(service.slug, invoicing.id), suffix='-%s.pdf' % now, delete=False)
|
||||
(service.slug, seq_id), suffix='-%s.pdf' % now, delete=False)
|
||||
pdftk = PdfTk()
|
||||
pdftk.concat(all_files, output_file.name)
|
||||
return output_file.name
|
||||
|
@ -332,12 +414,14 @@ def render_invoicing(invoicing, delete=False, headers=True, invoices=True):
|
|||
|
||||
|
||||
def batches_files(service, invoicing, health_center, batches, delete=False,
|
||||
headers=True, invoices=True, counter=None):
|
||||
headers=True, invoices=True, counter=None,
|
||||
adj_date=None, adj_price=None, seq_id=0):
|
||||
files = []
|
||||
try:
|
||||
if headers:
|
||||
header = header_file(service, invoicing, health_center, batches,
|
||||
delete=delete, counter=counter)
|
||||
delete=delete, counter=counter,
|
||||
adj_date=adj_date, adj_price=adj_price, seq_id=seq_id)
|
||||
|
||||
try:
|
||||
repeat = settings.BATCH_HEADER_TIMES_IN_INVOICING_FILE
|
||||
|
@ -351,8 +435,9 @@ def batches_files(service, invoicing, health_center, batches, delete=False,
|
|||
# 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))
|
||||
files.extend(invoice_files(service, invoicing, batch,
|
||||
invoice, counter=counter,
|
||||
adjustment=True, seq_id=seq_id))
|
||||
return files
|
||||
except:
|
||||
# cleanup
|
||||
|
|
|
@ -176,6 +176,28 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody class="batch-content" style="border: none;">
|
||||
{% if adjustment %}
|
||||
{% for invoice in batch.invoices %}
|
||||
<tr>
|
||||
<td>{{ invoice.number }}</td>
|
||||
<td>{{ invoice.patient_first_name}} {{ invoice.patient_last_name|upper }}</td>
|
||||
<td>{% firstof invoice.policy_holder_social_security_id_full invoice.patient_social_security_id_full %}</td>
|
||||
<td>{% if invoice.kind %}{{ invoice.kind }}{% endif %}</td>
|
||||
<td>{{ invoice.start_date|date:"d/m/Y" }}</td>
|
||||
<td>{{ invoice.end_date|date:"d/m/Y" }}</td>
|
||||
<td>- {{ invoice.decimal_amount|floatformat:2 }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ invoice.number|add:'1' }}</td>
|
||||
<td>{{ invoice.patient_first_name}} {{ invoice.patient_last_name|upper }}</td>
|
||||
<td>{% firstof invoice.policy_holder_social_security_id_full invoice.patient_social_security_id_full %}</td>
|
||||
<td>{% if invoice.kind %}{{ invoice.kind }}{% endif %}</td>
|
||||
<td>{{ invoice.start_date|date:"d/m/Y" }}</td>
|
||||
<td>{{ invoice.end_date|date:"d/m/Y" }}</td>
|
||||
<td>{{ invoice.decimal_amount_corrected|floatformat:2 }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% for invoice in batch.invoices %}
|
||||
<tr>
|
||||
<td>{{ invoice.number }}</td>
|
||||
|
@ -187,6 +209,7 @@
|
|||
<td>{{ invoice.decimal_amount|floatformat:2 }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div style="text-align: right; border: none;">
|
||||
|
|
|
@ -0,0 +1,353 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Procédure
|
||||
0 - Vérifier que les lots concernés ont bien été payés et les rejets
|
||||
pointés.
|
||||
1 - Créer les fichiers de télétransmission et à imprimer sur une machine
|
||||
de dev en utilisant la branche regularisation et :
|
||||
$ python scripts/regul_fact_ppa.py -pw
|
||||
2 - Copier les fichiers de TT sur la prod:
|
||||
$ scp ./123 \
|
||||
user@prod:/path_to_b2_files/
|
||||
$ ssh prod
|
||||
$ sudo chown -r run_user.run_user ./123
|
||||
3 - Diffuser les fichiers à imprimer.
|
||||
4 - Modifier le plan de facturation (ajout de la facturation de
|
||||
regularisation) sur la production pour que l'incrémentation des
|
||||
numéros de lots se fasse bien à la suite lors des prochianes
|
||||
facturations :
|
||||
$ python scripts/regul_fact_ppa.py -e
|
||||
5 - Faire la télétransmission à partir de l'IG sur la prod.
|
||||
6 - Faire l'export comptable à partir de l'IG sur la prod.
|
||||
7 - Corriger sur la production le prix dans le passé.
|
||||
"""
|
||||
|
||||
import django.core.management
|
||||
import calebasse.settings
|
||||
django.core.management.setup_environ(calebasse.settings)
|
||||
|
||||
import sys, getopt
|
||||
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
|
||||
from django.db.models import Max, Q
|
||||
|
||||
from calebasse.facturation.models import Invoicing, Invoice
|
||||
from calebasse.facturation.b2 import b2
|
||||
from calebasse.facturation.batches import Batch
|
||||
from calebasse.facturation.invoice_header import render_invoicing
|
||||
|
||||
from calebasse.ressources.models import HealthCenter, Service
|
||||
|
||||
OLD_PPA = 13965
|
||||
NEW_PPA = 16159
|
||||
LIMIT_DATE = datetime(2013, 8, 1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
print "### START: %s" % datetime.now()
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "btdwpec:n:")
|
||||
except getopt.GetoptError:
|
||||
print 'regul_fact_ppa.py -b -t -p -d -w -e -c <hc_id> -n <nb_invoice>'
|
||||
sys.exit(2)
|
||||
build = False
|
||||
transmission = False
|
||||
one_hc = None
|
||||
number = 0
|
||||
detail = False
|
||||
pdf = False
|
||||
write = False
|
||||
export = False
|
||||
for opt, arg in opts:
|
||||
if opt == '-h':
|
||||
print 'regul_fact_ppa.py -b -t -p -d -w -e -c <hc_id> -n <nb_invoice>'
|
||||
sys.exit()
|
||||
elif opt in ("-d", "--detail"):
|
||||
detail = True
|
||||
elif opt in ("-b", "--build"):
|
||||
build = True
|
||||
elif opt in ("-w", "--write"):
|
||||
write = True
|
||||
if not build:
|
||||
build = True
|
||||
elif opt in ("-t", "--transmission"):
|
||||
transmission = True
|
||||
if not build:
|
||||
build = True
|
||||
elif opt in ("-p", "--pdf"):
|
||||
pdf = True
|
||||
if not build:
|
||||
build = True
|
||||
elif opt in ("-e", "--export"):
|
||||
export = True
|
||||
if not build:
|
||||
build = True
|
||||
elif opt in ("-c", "--center"):
|
||||
# 163 is CPAM42
|
||||
one_hc = HealthCenter.objects.get(id=int(arg))
|
||||
elif opt in ("-n", "--number"):
|
||||
if one_hc:
|
||||
number = int(arg)
|
||||
|
||||
print "Option: Build batches is %s." %str(build)
|
||||
print "Option: Transmit batches is %s." %str(transmission)
|
||||
if one_hc:
|
||||
print "Option: Health center %s found." % one_hc
|
||||
else:
|
||||
print "Option: All health centers."
|
||||
if number:
|
||||
print "Option: With %d invoices." % number
|
||||
else:
|
||||
print "Option: All invoices."
|
||||
print "Option: Detail is %s." %str(detail)
|
||||
print
|
||||
|
||||
print "### ----> Recherche des factures à régulariser"
|
||||
invoices_bad_price = Invoice.objects.filter(ppa=OLD_PPA, rejected = False).distinct()
|
||||
# invoices_bad_price = Invoice.objects.filter(ppa=OLD_PPA, acts__date__gte=LIMIT_DATE.date(), rejected = False).distinct()
|
||||
if one_hc:
|
||||
print "\tRecherche restreinte à : %s" % one_hc
|
||||
# invoices_bad_price = invoices_bad_price.filter(policy_holder_healthcenter=one_hc)
|
||||
invoices_bad_price = invoices_bad_price.filter(
|
||||
Q(patient_healthcenter=one_hc,
|
||||
policy_holder_healthcenter__isnull=True)|
|
||||
Q(policy_holder_healthcenter=one_hc))
|
||||
invoices_bad_price_l = list()
|
||||
for i in invoices_bad_price:
|
||||
found = False
|
||||
for date in i.list_dates.split('$'):
|
||||
date_o = datetime.strptime(date, '%d/%m/%Y')
|
||||
if date_o >= LIMIT_DATE:
|
||||
found = True
|
||||
break
|
||||
if found:
|
||||
invoices_bad_price_l.append(i)
|
||||
if one_hc and number:
|
||||
print "\tNombre de factures réduit à : %d" % number
|
||||
if number > len(invoices_bad_price_l):
|
||||
print "\t\tLa limite du nombre de factures est plus grand que le nombre de factures trouvées : %d" % len(invoices_bad_price_l)
|
||||
number = len(invoices_bad_price_l)
|
||||
invoices_bad_price_l = invoices_bad_price_l[:number]
|
||||
invoicings = dict()
|
||||
for i in invoices_bad_price_l:
|
||||
invoicings.setdefault(i.invoicing, dict())
|
||||
if not i.health_center:
|
||||
print "Invoice %d has no healthcenter!!!" % i.id
|
||||
sys.exit(0)
|
||||
invoicings[i.invoicing].setdefault((i.batch, i.health_center), list()).append(i)
|
||||
print "Nombre de factures à régulariser %d" % len(invoices_bad_price_l)
|
||||
print "Nombre de facturations touchées %d (%s)" % (len(invoicings), ' '.join([str(i.seq_id) for i in invoicings.keys()]))
|
||||
print
|
||||
|
||||
print "### ----> Analyse par lot"
|
||||
invoices_per_healthcenter = dict()
|
||||
regul_total = 0
|
||||
for invoicing, batch in invoicings.items():
|
||||
real_batches = invoicing.get_batches()
|
||||
billed_batches = {}
|
||||
for hc, b, amount_rejected, versement in real_batches:
|
||||
billed_batches[(b.number, hc)] = (b, amount_rejected, versement)
|
||||
# print "%d %d %s" % (invoicing.seq_id, b.number, hc)
|
||||
print "\tFacturation : %d" % invoicing.seq_id
|
||||
regul_invoicing = 0
|
||||
|
||||
for (batch_nb, health_center), invoices in batch.items():
|
||||
invoices_per_healthcenter.setdefault(health_center, list()).extend(invoices)
|
||||
print "\t\tCentre : %s" % health_center
|
||||
print "\t\tLot : %d" % batch_nb
|
||||
print "\t\t\tNb factures à régulariser : %d" % len(invoices)
|
||||
init_price_batch = 0
|
||||
regul_batch = 0
|
||||
for i in invoices:
|
||||
regul = 0
|
||||
for date in i.list_dates.split('$'):
|
||||
init_price_batch += OLD_PPA
|
||||
date_o = datetime.strptime(date, '%d/%m/%Y')
|
||||
if date_o >= LIMIT_DATE:
|
||||
regul = regul + NEW_PPA - OLD_PPA
|
||||
regul_batch += regul
|
||||
regul_invoicing += regul_batch
|
||||
try:
|
||||
hc = health_center.hc_invoice if health_center.hc_invoice else health_center
|
||||
print "\t\t\tMontant total facturé : %.2f €" % billed_batches[(batch_nb, hc)][0].total
|
||||
print "\t\t\tMontant des rejets : %.2f €" % billed_batches[(batch_nb, hc)][1]
|
||||
print "\t\t\tVersement : %.2f €" % billed_batches[(batch_nb, hc)][2]
|
||||
if (billed_batches[(batch_nb, hc)][0].total - billed_batches[(batch_nb, hc)][1]) != (Decimal(init_price_batch) / Decimal(100)):
|
||||
b = billed_batches[(batch_nb, hc)][0]
|
||||
amount = 0
|
||||
nb_f = 0
|
||||
for i in b.invoices:
|
||||
if not i.rejected:
|
||||
found = False
|
||||
for date in i.list_dates.split('$'):
|
||||
date_o = datetime.strptime(date, '%d/%m/%Y')
|
||||
if date_o >= LIMIT_DATE:
|
||||
found = True
|
||||
if not found:
|
||||
amount += i.decimal_amount
|
||||
nb_f += 1
|
||||
if amount:
|
||||
if (billed_batches[(batch_nb, hc)][0].total - billed_batches[(batch_nb, hc)][1] - amount) != (Decimal(init_price_batch) / Decimal(100)):
|
||||
print "\t\t\t!!! problème 1 : Montant : %.2f €, calcul : %.2f €, trouvé: %.2f €" % (amount, (billed_batches[(batch_nb, hc)][0].total - billed_batches[(batch_nb, hc)][1] - amount), (Decimal(init_price_batch) / Decimal(100)))
|
||||
print "\t\t\t!!! Nombre de factures dans le lot : %d" % len(b.invoices)
|
||||
print "\t\t\t!!! Nombre de factures payées et avec seulement des actes antérieurs au 01/08/2013 : %d" % nb_f
|
||||
rej = 0
|
||||
for tmp in b.invoices:
|
||||
if tmp.rejected:
|
||||
rej += 1
|
||||
print "\t\t\t!!! Nombre de factures rejetée : %d" % rej
|
||||
else:
|
||||
print "\t\t\tMontant des factures payées et avec seulement des actes antérieurs au 01/08/2013 : %.2f €" % amount
|
||||
else:
|
||||
print "\t\t\t!!! problème 2 !!!"
|
||||
except Exception, e:
|
||||
print "\t\t\t!!! Centres %s et %s, lot %d ne correspond pas" % (health_center, hc, batch_nb)
|
||||
print e
|
||||
print "\t\t\t\tMontant facturé sur mauvaises factures: %.2f €" % (Decimal(init_price_batch) / Decimal(100))
|
||||
print "\t\t\t\tMontant regularisation : %.2f €" % (Decimal(regul_batch) / Decimal(100))
|
||||
print
|
||||
regul_total += regul_invoicing
|
||||
print "\tMontant regularisation de la facturation : %.2f €" % (Decimal(regul_invoicing) / Decimal(100))
|
||||
print "Montant regularisation total : %.2f €" % (Decimal(regul_total) / Decimal(100))
|
||||
print
|
||||
|
||||
b2_fns = dict()
|
||||
if one_hc:
|
||||
invoices = invoices_per_healthcenter[one_hc]
|
||||
invoices_per_healthcenter = {one_hc: invoices}
|
||||
|
||||
for hc, invoices in invoices_per_healthcenter.items():
|
||||
old_amount = 0
|
||||
regul_total = 0
|
||||
print '### ----> Centre : %s (ID: %d)' % (str(hc), hc.id)
|
||||
for i in invoices:
|
||||
regul = 0
|
||||
for date in i.list_dates.split('$'):
|
||||
date_o = datetime.strptime(date, '%d/%m/%Y')
|
||||
if date_o >= LIMIT_DATE:
|
||||
regul = regul + NEW_PPA - OLD_PPA
|
||||
old_amount += i.amount
|
||||
regul_total += regul
|
||||
if detail:
|
||||
print '\t\tFacture ancien n°: %d (ID : %d)' % (i.number, i.id)
|
||||
print '\t\tAncien montant : %.2f €' % (Decimal(i.amount) / Decimal(100))
|
||||
print '\t\tNouveau montant : %.2f €' % (Decimal(i.amount + regul) / Decimal(100))
|
||||
print '\t\tRégularisation : %.2f €' % (Decimal(regul) / Decimal(100))
|
||||
print
|
||||
new_amount = regul_total + old_amount
|
||||
print '\tAncien montant total : %.2f €' % (Decimal(old_amount) / Decimal(100))
|
||||
print '\tNouveau montant total : %.2f €' % (Decimal(new_amount) / Decimal(100))
|
||||
print '\tRégularisation totale : %.2f €' % (Decimal(regul_total) / Decimal(100))
|
||||
print
|
||||
|
||||
last_seq_id = Invoicing.objects.filter(service=Service.objects.get(name='CMPP'), status=Invoicing.STATUS.validated).aggregate(Max('seq_id'))['seq_id__max']
|
||||
position_seq_id = last_seq_id + 1
|
||||
|
||||
batches_per_healthcenter = dict()
|
||||
batches_amount_per_healthcenter = dict()
|
||||
dest_hc = {}
|
||||
if build:
|
||||
print '### ----> Construction des lots'
|
||||
j = 1
|
||||
for hc, invoices in invoices_per_healthcenter.items():
|
||||
print 'Lots pour le centre : %s (ID: %d)' % (str(hc), hc.id)
|
||||
print "\tNombre de factures à régulariser : %d" % len(invoices)
|
||||
for i in invoices:
|
||||
i.number = position_seq_id * 1000000 + j
|
||||
j += 2
|
||||
if not hc.dest_organism[0:3]:
|
||||
print "HC has no dest org, no need to build because no transmission possible !!!!"
|
||||
continue
|
||||
hc_dest = hc.hc_invoice or hc
|
||||
if hc_dest in dest_hc.keys():
|
||||
max_bn = dest_hc[hc_dest]
|
||||
else:
|
||||
agg = Invoice.objects.filter(
|
||||
Q(patient_healthcenter=hc,
|
||||
policy_holder_healthcenter__isnull=True)|
|
||||
Q(policy_holder_healthcenter=hc)) \
|
||||
.aggregate(Max('batch'))
|
||||
max_bn = agg['batch__max']
|
||||
last_batch_id = max_bn + 1
|
||||
batches = []
|
||||
nb_batches = len(invoices)/80 + 1
|
||||
reste = len(invoices)%80
|
||||
if not reste:
|
||||
nb_batches = nb_batches - 1
|
||||
for i in range(nb_batches):
|
||||
end = (i + 1) * 80
|
||||
if (i+1) == nb_batches and reste:
|
||||
end = i * 80 + reste
|
||||
batch = Batch(number=last_batch_id + i, invoices=invoices[i*80:end])
|
||||
batch.number_of_invoices = len(batch.invoices) * 2
|
||||
nb_acts = 0
|
||||
for i in batch.invoices:
|
||||
nb_acts += (len(i.list_dates.split('$'))*2)
|
||||
batch.number_of_acts = nb_acts
|
||||
batches.append(batch)
|
||||
dest_hc[hc_dest] = last_batch_id + len(batches) - 1
|
||||
print "\tNombre de lots construits : %d" % len(batches)
|
||||
total = 0
|
||||
batches_amount = []
|
||||
for batch in batches:
|
||||
print "\t\tLot %d" % batch.number
|
||||
amount = 0
|
||||
for i in batch.invoices:
|
||||
for date in i.list_dates.split('$'):
|
||||
date_o = datetime.strptime(date, '%d/%m/%Y')
|
||||
if date_o >= LIMIT_DATE:
|
||||
amount = amount + NEW_PPA - OLD_PPA
|
||||
total += amount
|
||||
batch.total = Decimal((batch.number_of_acts * OLD_PPA + amount) / Decimal(100))
|
||||
batches_amount.append((batch, amount))
|
||||
print "\t\tNombre d'actes : %d" % batch.number_of_acts
|
||||
print "\t\tNombre de factures : %d " % batch.number_of_invoices
|
||||
print "\t\tMontant total B2 : %.2f €" % batch.total
|
||||
print "\t\tMontant de la regularisation : %.2f €" % (Decimal(amount) / Decimal(100))
|
||||
batches_per_healthcenter[hc] = batches
|
||||
batches_amount_per_healthcenter[hc] = batches_amount
|
||||
print "\tMontant de la regularisation pour le centre : %.2f €" % (Decimal(total) / Decimal(100))
|
||||
|
||||
if write:
|
||||
print '\tBuilding B2 file...'
|
||||
for batch in batches:
|
||||
b2_fns[hc] = b2(seq_id=position_seq_id, hc=hc, batches=[batch], adj_date=LIMIT_DATE, adj_price=NEW_PPA)
|
||||
print '\tBatch file written : %s' % b2_fns[hc]
|
||||
print
|
||||
|
||||
if transmission:
|
||||
print "### ----> Transmission sending emails not implemented"
|
||||
print
|
||||
|
||||
if pdf:
|
||||
print "### ----> Generate pdf files"
|
||||
path = render_invoicing(delete=False, batches_by_health_center=batches_per_healthcenter, adj_date=LIMIT_DATE, adj_price=NEW_PPA, seq_id=position_seq_id)
|
||||
print "file generated : %s" % path
|
||||
print
|
||||
|
||||
if export:
|
||||
start_date = datetime.today()
|
||||
last_seq_id = Invoicing.objects.filter(service=Service.objects.get(name='CMPP'), status=Invoicing.STATUS.validated).aggregate(Max('seq_id'))['seq_id__max']
|
||||
position_seq_id = last_seq_id + 1
|
||||
for invoicing in Invoicing.objects.filter(service=Service.objects.get(name='CMPP'), seq_id__gte=position_seq_id).order_by('-seq_id'):
|
||||
invoicing.seq_id += 1
|
||||
invoicing.save()
|
||||
invoicing = Invoicing(service=Service.objects.get(name='CMPP'),
|
||||
start_date=start_date, end_date=start_date,
|
||||
status=Invoicing.STATUS.validated, seq_id=position_seq_id)
|
||||
invoicing.save()
|
||||
n = 0
|
||||
for hc, batches_amount in batches_amount_per_healthcenter.items():
|
||||
for batch, amount in batches_amount:
|
||||
i_id = invoicing.seq_id * 1000000 + 1 + n
|
||||
invoice = Invoice(batch=batch.number, number=i_id, invoicing=invoicing, ppa=0, amount=amount, policy_holder_healthcenter=hc,
|
||||
list_dates = start_date.date().strftime('%d/%m/%Y'))
|
||||
invoice.save()
|
||||
n += 1
|
||||
|
||||
print "### END: %s" % datetime.now()
|
Reference in New Issue