initial packaging files

This commit is contained in:
Serghei Mihai 2014-09-03 10:24:22 +02:00
parent e6291d48eb
commit a9d827593b
30 changed files with 34 additions and 1452 deletions

View File

@ -1,2 +0,0 @@
recursive-include src/templates *.html *.csv
recursive-include src/locale *.po *.mo

5
debian/changelog vendored Normal file
View File

@ -0,0 +1,5 @@
facturier (0.1.0.1.ge2a2da5-1) unstable; urgency=low
* source package automatically created by stdeb 0.8.2
-- Serghei Mihai <smihai@entrouvert.com> Wed, 03 Sep 2014 11:15:41 +0200

1
debian/compat vendored Normal file
View File

@ -0,0 +1 @@
7

17
debian/control vendored Normal file
View File

@ -0,0 +1,17 @@
Source: facturier
Maintainer: Serghei Mihai <smihai@entrouvert.com>
Section: python
Priority: optional
Build-Depends: python-setuptools (>= 0.6b3), python-all (>= 2.6.6-3), debhelper (>= 7)
Standards-Version: 3.9.1
Package: python-facturier
Architecture: all
Depends: ${misc:Depends}, ${python:Depends}, portail-citoyen2, python-eopayment, django-jsonfield
Description: Payment lib pluggable into portail-citoyen

9
debian/rules vendored Executable file
View File

@ -0,0 +1,9 @@
#!/usr/bin/make -f
# This file was automatically generated by stdeb 0.8.2 at
# Wed, 03 Sep 2014 11:15:41 +0200
%:
dh $@ --with python2 --buildsystem=python_distutils

1
debian/source/format vendored Normal file
View File

@ -0,0 +1 @@
3.0 (quilt)

1
debian/source/options vendored Normal file
View File

@ -0,0 +1 @@
extend-diff-ignore="\.egg-info$"

View File

@ -1,3 +0,0 @@
git+git://repos.entrouvert.org/python-entrouvert
git+git://repos.entrouvert.org/portail-citoyen2
gunicorn

125
setup.py
View File

@ -1,125 +0,0 @@
#! /usr/bin/env python
''' Setup script for Facturier app
'''
import glob
import re
import sys
import os
from setuptools import setup, find_packages
from setuptools.command.install_lib import install_lib as _install_lib
from distutils.command.build import build as _build
from distutils.command.sdist import sdist
from distutils.cmd import Command
class compile_translations(Command):
description = 'compile message catalogs to MO files via django compilemessages'
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
from django.core.management.commands.compilemessages import \
compile_messages
for path in ['src']:
if not os.path.exists(os.path.join(path, 'locale')):
continue
curdir = os.getcwd()
os.chdir(os.path.realpath(path))
compile_messages(sys.stderr)
os.chdir(curdir)
class build(_build):
sub_commands = [('compile_translations', None)] + _build.sub_commands
class eo_sdist(sdist):
def run(self):
print "creating VERSION file"
if os.path.exists('VERSION'):
os.remove('VERSION')
version = get_version()
version_file = open('VERSION', 'w')
version_file.write(version)
version_file.close()
sdist.run(self)
print "removing VERSION file"
if os.path.exists('VERSION'):
os.remove('VERSION')
class install_lib(_install_lib):
def run(self):
self.run_command('compile_translations')
_install_lib.run(self)
def get_version():
version = None
if os.path.exists('VERSION'):
version_file = open('VERSION', 'r')
version = version_file.read()
version_file.close()
return version
for d in glob.glob('*'):
if not os.path.isdir(d):
continue
module_file = os.path.join(d, '__init__.py')
if not os.path.exists(module_file):
continue
for v in re.findall("""__version__ *= *['"](.*)['"]""",
open(module_file).read()):
assert version is None
version = v
if version:
break
assert version is not None
if os.path.exists('.git'):
import subprocess
p = subprocess.Popen(['git','describe','--dirty','--match=v*'],
stdout=subprocess.PIPE)
result = p.communicate()[0]
assert p.returncode == 0, 'git returned non-zero'
new_version = result.split()[0][1:]
assert not new_version.endswith('-dirty'), 'git workdir is not clean'
assert new_version.split('-')[0] == version, '__version__ must match the last git annotated tag'
version = new_version.replace('-', '.')
return version
setup(name="facturier",
version=get_version(),
license="AGPLv3 or later",
description="Payment lib pluggable into portail-citoyen",
author="Entr'ouvert",
author_email="info@entrouvert.org",
maintainer="Entr'ouvert",
maintainer_email="info@entrouvert.com",
include_package_data=True,
packages=find_packages(),
install_requires=[
'portail-citoyen2',
'gunicorn',
'eopayment',
'django-jsonfield',
],
dependency_links = [
'git+git://repos.entrouvert.org/portail-citoyen2',
'git+git://repos.entrouvert.org/python-entrouvert'
],
cmdclass={'build': build, 'install_lib': install_lib,
'compile_translations': compile_translations,
'sdist': eo_sdist},
entry_points={
'portail_citoyen2.plugin': ['facturier = facturier:Plugin']
}
)

View File

@ -1,13 +0,0 @@
__version__ = '0.0.1'
class Plugin(object):
def get_pre_urls(self):
from . import urls
return urls.urlpatterns
def get_apps(self):
return [__name__]
def get_admin_modules(self):
from . import dashboard
return dashboard.get_admin_modules()

View File

@ -1,29 +0,0 @@
from .models import Regie, ServiceOption, RequestOption
from .models import TransactionEvent
from django.contrib import admin
class RequestOptionInline(admin.TabularInline):
model = RequestOption
class ServiceOptionInline(admin.TabularInline):
model = ServiceOption
class RegieAdmin(admin.ModelAdmin):
prepopulated_fields = {"slug": ("label",)}
list_display = ('label', 'service')
list_filter = ('service',)
inlines = (ServiceOptionInline, RequestOptionInline)
extras = 3
class TransactionEventAdmin(admin.ModelAdmin):
date_hierarchy = 'date'
list_display = ('date', 'transaction_id', 'regie', 'invoice_id', 'status',
'response', 'details')
list_filter = ('regie', 'response')
readonly_fields = ('date', 'transaction_id', 'regie', 'invoice_id',
'status', 'response', 'details', 'address', 'nameid')
search_fields = ('invoice_id', 'details', 'address', 'nameid')
admin.site.register(Regie, RegieAdmin)
admin.site.register(TransactionEvent, TransactionEventAdmin)

View File

@ -1,36 +0,0 @@
import sys
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
class AppSettings(object):
'''Thanks you, django-allauth'''
__SENTINEL = object()
def __init__(self, prefix):
self.prefix = prefix
def _setting(self, name, dflt=__SENTINEL):
from django.conf import settings
v = getattr(settings, self.prefix + name, dflt)
if v is self.__SENTINEL:
raise ImproperlyConfigured('Missing setting %r' % (self.prefix + name))
return v
@property
def download_filename(self):
return self._setting('DOWNLOAD_FILENAME',
'/var/lib/invoices/invoice_{invoice[id]}.pdf')
@property
def download_filename_mimetype(self):
return self._setting('DOWNLOAD_FILENAME_MIMETYPE', 'application/pdf')
@property
def responses_csv_key(self):
return self._setting('RESPONSES_CSV_KEY')
app_settings = AppSettings('FACTURIER_')
app_settings.__name__ = __name__
sys.modules[__name__] = app_settings

Binary file not shown.

View File

@ -1,27 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-03-26 16:22+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: models.py:88
msgid "Transaction event"
msgstr "Evenement sur une transaction"
#: models.py:89
msgid "Transaction events"
msgstr "Evenements sur les transactions"

View File

@ -1,115 +0,0 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'Regie'
db.create_table(u'facturier_regie', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('label', self.gf('django.db.models.fields.CharField')(max_length=64)),
('slug', self.gf('django.db.models.fields.SlugField')(unique=True, max_length=50)),
('description', self.gf('django.db.models.fields.TextField')()),
('service', self.gf('django.db.models.fields.CharField')(max_length=64)),
('get_url', self.gf('django.db.models.fields.related.ForeignKey')(related_name='regie_get', to=orm['data_source_plugin.DataSource'])),
('update_url', self.gf('django.db.models.fields.related.ForeignKey')(related_name='regie_update', to=orm['data_source_plugin.DataSource'])),
))
db.send_create_signal(u'facturier', ['Regie'])
# Adding model 'ServiceOption'
db.create_table(u'facturier_serviceoption', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('regie', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['facturier.Regie'])),
('name', self.gf('django.db.models.fields.CharField')(max_length=32)),
('value', self.gf('django.db.models.fields.CharField')(max_length=256)),
))
db.send_create_signal(u'facturier', ['ServiceOption'])
# Adding model 'RequestOption'
db.create_table(u'facturier_requestoption', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('regie', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['facturier.Regie'])),
('name', self.gf('django.db.models.fields.CharField')(max_length=32)),
('value', self.gf('django.db.models.fields.CharField')(max_length=256)),
))
db.send_create_signal(u'facturier', ['RequestOption'])
# Adding model 'TransactionEvent'
db.create_table(u'facturier_transactionevent', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('transaction_id', self.gf('django.db.models.fields.CharField')(max_length=128, db_index=True)),
('invoice_id', self.gf('django.db.models.fields.CharField')(max_length=128, db_index=True)),
('date', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
('event', self.gf('django.db.models.fields.CharField')(max_length=16)),
('details', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
))
db.send_create_signal(u'facturier', ['TransactionEvent'])
def backwards(self, orm):
# Deleting model 'Regie'
db.delete_table(u'facturier_regie')
# Deleting model 'ServiceOption'
db.delete_table(u'facturier_serviceoption')
# Deleting model 'RequestOption'
db.delete_table(u'facturier_requestoption')
# Deleting model 'TransactionEvent'
db.delete_table(u'facturier_transactionevent')
models = {
u'data_source_plugin.datasource': {
'Meta': {'ordering': "('name',)", 'object_name': 'DataSource'},
'allow_redirects': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'hash_algo': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '16', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'mime_type': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
'signature_key': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '128', 'blank': 'True'}),
'timeout': ('django.db.models.fields.IntegerField', [], {'default': '10'}),
'url': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
'verify_certificate': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
u'facturier.regie': {
'Meta': {'object_name': 'Regie'},
'description': ('django.db.models.fields.TextField', [], {}),
'get_url': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'regie_get'", 'to': u"orm['data_source_plugin.DataSource']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'label': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
'service': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50'}),
'update_url': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'regie_update'", 'to': u"orm['data_source_plugin.DataSource']"})
},
u'facturier.requestoption': {
'Meta': {'object_name': 'RequestOption'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
'regie': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['facturier.Regie']"}),
'value': ('django.db.models.fields.CharField', [], {'max_length': '256'})
},
u'facturier.serviceoption': {
'Meta': {'object_name': 'ServiceOption'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
'regie': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['facturier.Regie']"}),
'value': ('django.db.models.fields.CharField', [], {'max_length': '256'})
},
u'facturier.transactionevent': {
'Meta': {'object_name': 'TransactionEvent'},
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'details': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'event': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'invoice_id': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'}),
'transaction_id': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'})
}
}
complete_apps = ['facturier']

View File

@ -1,78 +0,0 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Deleting field 'TransactionEvent.event'
db.delete_column(u'facturier_transactionevent', 'event')
# Adding field 'TransactionEvent.status'
db.add_column(u'facturier_transactionevent', 'status',
self.gf('django.db.models.fields.CharField')(default='', max_length=16),
keep_default=False)
def backwards(self, orm):
# Adding field 'TransactionEvent.event'
db.add_column(u'facturier_transactionevent', 'event',
self.gf('django.db.models.fields.CharField')(default='', max_length=16),
keep_default=False)
# Deleting field 'TransactionEvent.status'
db.delete_column(u'facturier_transactionevent', 'status')
models = {
u'data_source_plugin.datasource': {
'Meta': {'ordering': "('name',)", 'object_name': 'DataSource'},
'allow_redirects': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'hash_algo': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '16', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'mime_type': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
'signature_key': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '128', 'blank': 'True'}),
'timeout': ('django.db.models.fields.IntegerField', [], {'default': '10'}),
'url': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
'verify_certificate': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
u'facturier.regie': {
'Meta': {'object_name': 'Regie'},
'description': ('django.db.models.fields.TextField', [], {}),
'get_url': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'regie_get'", 'to': u"orm['data_source_plugin.DataSource']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'label': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
'service': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50'}),
'update_url': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'regie_update'", 'to': u"orm['data_source_plugin.DataSource']"})
},
u'facturier.requestoption': {
'Meta': {'object_name': 'RequestOption'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
'regie': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['facturier.Regie']"}),
'value': ('django.db.models.fields.CharField', [], {'max_length': '256'})
},
u'facturier.serviceoption': {
'Meta': {'object_name': 'ServiceOption'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
'regie': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['facturier.Regie']"}),
'value': ('django.db.models.fields.CharField', [], {'max_length': '256'})
},
u'facturier.transactionevent': {
'Meta': {'object_name': 'TransactionEvent'},
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'details': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'invoice_id': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'}),
'status': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
'transaction_id': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'})
}
}
complete_apps = ['facturier']

View File

@ -1,80 +0,0 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'TransactionEvent.address'
db.add_column(u'facturier_transactionevent', 'address',
self.gf('django.db.models.fields.GenericIPAddressField')(max_length=39, null=True, blank=True),
keep_default=False)
# Adding field 'TransactionEvent.nameid'
db.add_column(u'facturier_transactionevent', 'nameid',
self.gf('django.db.models.fields.CharField')(max_length=256, null=True, blank=True),
keep_default=False)
def backwards(self, orm):
# Deleting field 'TransactionEvent.address'
db.delete_column(u'facturier_transactionevent', 'address')
# Deleting field 'TransactionEvent.nameid'
db.delete_column(u'facturier_transactionevent', 'nameid')
models = {
u'data_source_plugin.datasource': {
'Meta': {'ordering': "('name',)", 'object_name': 'DataSource'},
'allow_redirects': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'hash_algo': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '16', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'mime_type': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
'signature_key': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '128', 'blank': 'True'}),
'timeout': ('django.db.models.fields.IntegerField', [], {'default': '10'}),
'url': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
'verify_certificate': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
u'facturier.regie': {
'Meta': {'object_name': 'Regie'},
'description': ('django.db.models.fields.TextField', [], {}),
'get_url': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'regie_get'", 'to': u"orm['data_source_plugin.DataSource']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'label': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
'service': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50'}),
'update_url': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'regie_update'", 'to': u"orm['data_source_plugin.DataSource']"})
},
u'facturier.requestoption': {
'Meta': {'object_name': 'RequestOption'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
'regie': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['facturier.Regie']"}),
'value': ('django.db.models.fields.CharField', [], {'max_length': '256'})
},
u'facturier.serviceoption': {
'Meta': {'object_name': 'ServiceOption'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
'regie': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['facturier.Regie']"}),
'value': ('django.db.models.fields.CharField', [], {'max_length': '256'})
},
u'facturier.transactionevent': {
'Meta': {'ordering': "['date']", 'object_name': 'TransactionEvent'},
'address': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'details': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'invoice_id': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'}),
'nameid': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'}),
'status': ('django.db.models.fields.CharField', [], {'default': "'CREATED'", 'max_length': '16'}),
'transaction_id': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'})
}
}
complete_apps = ['facturier']

View File

@ -1,71 +0,0 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'TransactionEvent.regie'
db.add_column(u'facturier_transactionevent', 'regie',
self.gf('django.db.models.fields.related.ForeignKey')(default=1, to=orm['facturier.Regie']),
keep_default=False)
def backwards(self, orm):
# Deleting field 'TransactionEvent.regie'
db.delete_column(u'facturier_transactionevent', 'regie_id')
models = {
u'data_source_plugin.datasource': {
'Meta': {'ordering': "('name',)", 'object_name': 'DataSource'},
'hash_algo': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '16', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'mime_type': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
'signature_key': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '128', 'blank': 'True'}),
'url': ('django.db.models.fields.URLField', [], {'max_length': '1024'}),
'verify_certificate': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
u'facturier.regie': {
'Meta': {'object_name': 'Regie'},
'description': ('django.db.models.fields.TextField', [], {}),
'get_url': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'regie_get'", 'to': u"orm['data_source_plugin.DataSource']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'label': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
'service': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50'}),
'update_url': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'regie_update'", 'to': u"orm['data_source_plugin.DataSource']"})
},
u'facturier.requestoption': {
'Meta': {'object_name': 'RequestOption'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
'regie': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['facturier.Regie']"}),
'value': ('django.db.models.fields.CharField', [], {'max_length': '256'})
},
u'facturier.serviceoption': {
'Meta': {'object_name': 'ServiceOption'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
'regie': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['facturier.Regie']"}),
'value': ('django.db.models.fields.CharField', [], {'max_length': '256'})
},
u'facturier.transactionevent': {
'Meta': {'ordering': "['date']", 'object_name': 'TransactionEvent'},
'address': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'details': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'invoice_id': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'}),
'nameid': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'}),
'regie': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['facturier.Regie']"}),
'status': ('django.db.models.fields.CharField', [], {'default': "'CREATED'", 'max_length': '16'}),
'transaction_id': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'})
}
}
complete_apps = ['facturier']

View File

@ -1,72 +0,0 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'Regie.get_list_url'
db.add_column(u'facturier_regie', 'get_list_url',
self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='regie_get_list', null=True, to=orm['data_source_plugin.DataSource']),
keep_default=False)
def backwards(self, orm):
# Deleting field 'Regie.get_list_url'
db.delete_column(u'facturier_regie', 'get_list_url_id')
models = {
u'data_source_plugin.datasource': {
'Meta': {'ordering': "('name',)", 'object_name': 'DataSource'},
'hash_algo': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '16', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'mime_type': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
'signature_key': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '128', 'blank': 'True'}),
'url': ('django.db.models.fields.URLField', [], {'max_length': '1024'}),
'verify_certificate': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
u'facturier.regie': {
'Meta': {'object_name': 'Regie'},
'description': ('django.db.models.fields.TextField', [], {}),
'get_list_url': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'regie_get_list'", 'null': 'True', 'to': u"orm['data_source_plugin.DataSource']"}),
'get_url': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'regie_get'", 'to': u"orm['data_source_plugin.DataSource']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'label': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
'service': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50'}),
'update_url': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'regie_update'", 'to': u"orm['data_source_plugin.DataSource']"})
},
u'facturier.requestoption': {
'Meta': {'object_name': 'RequestOption'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
'regie': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['facturier.Regie']"}),
'value': ('django.db.models.fields.CharField', [], {'max_length': '256'})
},
u'facturier.serviceoption': {
'Meta': {'object_name': 'ServiceOption'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
'regie': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['facturier.Regie']"}),
'value': ('django.db.models.fields.CharField', [], {'max_length': '256'})
},
u'facturier.transactionevent': {
'Meta': {'ordering': "['date']", 'object_name': 'TransactionEvent'},
'address': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'details': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'invoice_id': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'}),
'nameid': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'}),
'regie': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['facturier.Regie']"}),
'status': ('django.db.models.fields.CharField', [], {'default': "'CREATED'", 'max_length': '16'}),
'transaction_id': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'})
}
}
complete_apps = ['facturier']

View File

@ -1,79 +0,0 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'TransactionEvent.response'
db.add_column(u'facturier_transactionevent', 'response',
self.gf('django.db.models.fields.BooleanField')(default=False),
keep_default=False)
# Changing field 'TransactionEvent.details'
db.alter_column(u'facturier_transactionevent', 'details', self.gf('jsonfield.fields.JSONField')(null=True))
def backwards(self, orm):
# Deleting field 'TransactionEvent.response'
db.delete_column(u'facturier_transactionevent', 'response')
# Changing field 'TransactionEvent.details'
db.alter_column(u'facturier_transactionevent', 'details', self.gf('django.db.models.fields.TextField')(null=True))
models = {
u'data_source_plugin.datasource': {
'Meta': {'ordering': "('name',)", 'object_name': 'DataSource'},
'hash_algo': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '16', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'mime_type': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
'signature_key': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '128', 'blank': 'True'}),
'url': ('django.db.models.fields.URLField', [], {'max_length': '1024'}),
'verify_certificate': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
u'facturier.regie': {
'Meta': {'object_name': 'Regie'},
'description': ('django.db.models.fields.TextField', [], {}),
'get_list_url': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'regie_get_list'", 'null': 'True', 'to': u"orm['data_source_plugin.DataSource']"}),
'get_url': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'regie_get'", 'to': u"orm['data_source_plugin.DataSource']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'label': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
'service': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50'}),
'update_url': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'regie_update'", 'to': u"orm['data_source_plugin.DataSource']"})
},
u'facturier.requestoption': {
'Meta': {'object_name': 'RequestOption'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
'regie': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['facturier.Regie']"}),
'value': ('django.db.models.fields.CharField', [], {'max_length': '256'})
},
u'facturier.serviceoption': {
'Meta': {'object_name': 'ServiceOption'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
'regie': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['facturier.Regie']"}),
'value': ('django.db.models.fields.CharField', [], {'max_length': '256'})
},
u'facturier.transactionevent': {
'Meta': {'ordering': "['date']", 'object_name': 'TransactionEvent'},
'address': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'details': ('jsonfield.fields.JSONField', [], {'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'invoice_id': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'}),
'nameid': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'}),
'regie': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['facturier.Regie']"}),
'response': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'status': ('django.db.models.fields.CharField', [], {'default': "'CREATED'", 'max_length': '16'}),
'transaction_id': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'})
}
}
complete_apps = ['facturier']

View File

@ -1,122 +0,0 @@
from django.db import models
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _, pgettext_lazy
from django.template import RequestContext
from jsonfield import JSONField
from portail_citoyen2.apps.data_source_plugin.models import DataSource
from cmsplugin_blurp.renderers.data_source import Data
import requests
import eopayment
SERVICES = ((eopayment.SIPS, 'SIPS'),
(eopayment.SYSTEMPAY, 'SYSTEMPAY'),
(eopayment.SPPLUS, 'SPPLUS'),
(eopayment.TIPI, 'TIPI'),
(eopayment.DUMMY, 'DUMMY'),
)
TRANSACTION_STATUS_PROD = (
('CREATED', 'CREATED'),
('PAID', 'PAID'),
('DENIED', 'DENIED'),
('CANCELED', 'CANCELED'),
('ERROR', 'ERROR'),
)
TRANSACTION_STATUS_TEST = tuple((('TEST_%s' % k, 'TEST_%s' %v)
for k,v in TRANSACTION_STATUS_PROD))
TRANSACTION_STATUS = TRANSACTION_STATUS_PROD + TRANSACTION_STATUS_TEST
class Regie(models.Model):
label = models.CharField(max_length=64)
slug = models.SlugField(unique=True)
description = models.TextField()
service = models.CharField(max_length=64, choices=SERVICES)
get_url = models.ForeignKey(DataSource, related_name='regie_get',
help_text=_('Get an invoice from this Regie'))
update_url = models.ForeignKey(DataSource, related_name='regie_update',
help_text=_('Update an invoice of this Regie'))
get_list_url = models.ForeignKey(DataSource, related_name='regie_get_list',
blank=True, null=True,
help_text=_("Get a list of invoices "\
"(RequestContext dependent, typically user's invoices)"))
def natural_key(self):
return (self.slug,)
def __unicode__(self):
return self.label
def get_invoice_list(self, request, **kwargs):
if not self.get_list_url:
return []
context = RequestContext(request, kwargs)
data_source = Data(self.get_list_url, context, limit=None, refresh=None)
content = data_source.update_content()
return content.get('data', {}).get('invoices', [])
def get_invoice(self, invoice_id, invoice_hash=None, request=None):
'''get an invoice (dict), via webservice
invoice_hash: a key to access the invoice (for example a password)
'''
context = {'regie': self,
'invoice_id': invoice_id,
'invoice_hash': invoice_hash}
if request:
context = RequestContext(request, context)
data_source = Data(self.get_url, context, limit=None, refresh=None)
content = data_source.update_content()
invoice = content.get('data', {}).get('invoice', {})
if invoice:
invoice['url'] = reverse('transaction',
args=(self.slug, invoice_id, invoice_hash))
# is this invoice in the list of invoices ? (typically, list
# of user's invoices). If yes, add a "download_url" value
if self.get_list_url and request and request.user.is_authenticated():
invoice['in_list'] = False
ctx_invoices = self.get_invoice_list(request)
for i in ctx_invoices:
if i['id'] == invoice['id']:
invoice['download_url'] = reverse('invoice-download',
args=(self.slug, invoice_id, invoice_hash))
break
return invoice
class Option(models.Model):
regie = models.ForeignKey(Regie)
name = models.CharField(max_length=32)
value = models.CharField(max_length=256)
class Meta:
abstract = True
def __unicode__(self):
return _('%s: %s') % (self.name, self.value)
class ServiceOption(Option):
pass
class RequestOption(Option):
pass
class TransactionEvent(models.Model):
regie = models.ForeignKey(Regie)
transaction_id = models.CharField(max_length=128, db_index=True)
invoice_id= models.CharField(max_length=128, db_index=True)
date = models.DateTimeField(auto_now_add=True)
address = models.GenericIPAddressField(null=True, blank=True)
nameid = models.CharField(max_length=256, null=True, blank=True)
status = models.CharField(max_length=16, choices=TRANSACTION_STATUS,
default='CREATED')
response = models.BooleanField(default=False)
details = JSONField(blank=True, null=True)
class Meta:
get_latest_by = 'date'
ordering = ['date']
verbose_name = _('Transaction event')
verbose_name_plural = _('Transaction events')

View File

@ -1,2 +0,0 @@
DATETIME;TRANSACTION_ID;INVOICE;STATUS;TIPI_NUMCLI;TIPI_REFDET;TIPI_MONTANT;TIPI_RESULTRANS;TIPI_DATTRANS;TIPI_HEURTRANS;TIPI_SAISIE;TIPI_MEL;TIPI_NUMAUTO{% for e in transactionevent_list %}
{{ e.date|date:'c' }};{{ e.transaction_id }};{{ e.invoice_id }};{{ e.status }};{% with bd=e.details.bank_data %}{{ bd.numcli }};{{ bd.refdet }};{{ bd.montant }};{{ bd.resultrans }};{{ bd.dattrans }};{{ bd.heurtrans }};{{ bd.saisie}};{{ bd.mel }};{{ bd.numauto }}{% endwith %}{% endfor %}
1 DATETIME TRANSACTION_ID INVOICE STATUS TIPI_NUMCLI TIPI_REFDET TIPI_MONTANT TIPI_RESULTRANS TIPI_DATTRANS TIPI_HEURTRANS TIPI_SAISIE TIPI_MEL TIPI_NUMAUTO{% for e in transactionevent_list %}
2 {{ e.date|date:'c' }} {{ e.transaction_id }} {{ e.invoice_id }} {{ e.status }} {% with bd=e.details.bank_data %}{{ bd.numcli }} {{ bd.refdet }} {{ bd.montant }} {{ bd.resultrans }} {{ bd.dattrans }} {{ bd.heurtrans }} {{ bd.saisie}} {{ bd.mel }} {{ bd.numauto }}{% endwith %}{% endfor %}

View File

@ -1,228 +0,0 @@
{% extends 'base-cms.html' %}
{% load i18n %}
{% load orleans_tags %}
{% load facturier_tags %}
{% block breadcrumbs %}
<li><a href="/factures/">Mes factures</a></li>
<li class="separ">&nbsp;/&nbsp;</li>
<li class="last">Détails de la facture n°{{ invoice.id }}</li>
{% endblock %}
{% block sidebar %}
{% if perms.facturier %}
<p>
<em>Les informations ci-dessous sont visibles car vous avec
les droits "staff" sur l'application. Un utilisateur habituel
ne verra rien.</em>
</p>
<div class="blocProgram">
<h2 class="title">Mode test</h2>
<div class="rteContent">
<p>
En tant qu'utilisateur {{ request.user }} vous pouvez lancer un faux paiement (test)
en cochant cette case :<br /><label><input type="checkbox" name="test" id="test" />
<strong>appeler TIPI en mode test</strong></label>
</p>
</div>
{% if user.is_superuser %}
<h2 class="title">Infos techniques</h2>
<div class="rteContent">
<p>
{% for k,v in invoice.items %}
<strong>{{ k }}</strong>:&nbsp;{{ v }}<br />
{% endfor %}
</p>
</div>
{% endif %}
</div>
{% endif %}
{% endblock sidebar %}
{% block content %}
<h1>Facture {{ invoice.id }}</h1>
<div class="wrapSpecial"><div class="rteContent">
<h2>Montant : {{ invoice.amount }} €</h2>
<p>Facture émise le
{{ invoice.creation_date|iso8601|date:"l j F Y" }}
{% if invoice.prelevement_automatique %}
<br />
Prélèvement automatique effectué le {{ invoice.expiration_date|iso8601|date:"l j F Y" }}
{% endif %}
</p>
<h2>Détails de la facture</h2>
<p id="download">
{% if invoice.download_url %}
<a href="{{ invoice.download_url }}#{{invoice.id}}.pdf"
title="facture_{{ invoice.id }}.pdf"
download="facture_{{ invoice.id }}.pdf"
class="download">Télécharger la version PDF complète de la facture</a>
{% else %}
{% if user.is_authenticated %}
Cette facture ne vous est pas destinée, vous ne pouvez pas en
voir les détails, uniquement la payer en ligne.
{% else %}
Pour voir les détails de cette facture, vous devez vous
connecter à votre compte citoyen. Sans être connecté,
vous pouvez uniquement la payer en ligne.
{% endif %}
{% endif %}
</p>
<h2>Paiement en ligne</h2>
{% if invoice.prelevement_automatique %}
<p>Facture en prélévement automatique, vous ne pouvez pas la payer en ligne.</p>
{% elif invoice.paid %}
<p>
Cette facture a déjà été payée
{% if invoice.paid_date %}le {{ invoice.paid_date }}{% endif %}
</p>
{% elif invoice.expired %}
<p>
Cette facture est expirée depuis le
{{ invoice.expiration_date|iso8601|date:"l j F Y" }}&nbsp;:
vous ne pouvez plus la payer en ligne.
</p>
{% elif invoice.amount|decimal < 1.0 %}
<p>
Le montant de cette facture est inférieur à 1 € (un euro),
vous ne pouvez pas la payer en ligne.
</p>
<p>
Il s'agit d'une contrainte imposée par le système de paiement
«TIPI» de la Direction Générale des Finances Publiques.
</p>
{% else %}
<p>
Si vous désirez payer cette facture en ligne, indiquez d'abord votre
adresse mail ci-dessous, puis cliquez sur le bouton «payer en ligne».
</p>
<p>
<label>Votre adresse mail :</label>
<input type="email" name="email" id="email" placeholder="nom@domaine.fr"
{% if request.user.email %}
value="{{ request.user.email }}"
{% else %}
placeholder="nom@domaine.fr"
{% endif %}
/>
<span id="error" style="display: none; color: red;">
Adresse mail invalide ! Vous devez indiquer votre adresse mail correcte
pour payer.
</span>
</p>
<div id="pay">
<p>
<button style="font-size: 1.2em;" onclick="tipi()">Payer cette facture en ligne</button>
</p>
<p>
En cliquant sur ce bouton, vous allez être redirigé vers le site TIPI
de la Direction générale des Finances publiques (DGFiP), qui vous permettra de
payer cette facture.
</p>
<p>
<strong>Attention : le système de paiement va s'ouvrir dans une fenêtre «popup»&nbsp;:
avant de cliquer, veillez à désactiver tout bloqueur de fenêtre publicitaire
(système «anti-pop-up»).</strong>
</p>
</div>
<div id="pay-open" style="display: none;">
<p>
Vous avez cliqué sur le bouton de paiement. Si la fenêtre de paiement
n'apparait pas, vérifiez qu'elle n'est pas bloquée par un système
«anti-publicité» ou tout autre système «anti-pop-up».
</p>
</div>
<div id="pay-close" style="display: none;">
<p>
Vous venez de fermer la fenêtre du paiement.
La ville est désormais en attente de
validation du paiement de la part de la DGFiP.
</p>
<p>
Note : si vous n'avez pas réussi à effectuer le paiement ou si vous avez
fermé la fenêtre avant de le terminer, vous pouvez
<a href="javascript:tipi()">relancer le paiement</a>.
</p>
</div>
</div>
</div>
<script>
var popup;
var timer;
var error = document.getElementById('error');
var pay = document.getElementById('pay');
var pay_open = document.getElementById('pay-open');
var pay_close = document.getElementById('pay-close');
function validateEmail(email) {
var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
}
function tipi() {
var email = document.getElementById('email');
var test = document.getElementById('test');
pay_close.style.display='none';
var url = '{{ invoice.url|safe }}';
if (url.indexOf('?') == -1) {
url = url + '?';
} else {
url = url + '&';
}
if (validateEmail(email.value)) {
url +='email=' + email.value;
error.style.display='none';
} else {
error.style.display='block';
return false;
}
if (test)
if (test.checked)
url += '&saisie=T';
pay.innerHTML = '<p><strong>Paiement en cours.</strong></p>';
pay_open.style.display='block';
popup = window.open(url, 'tipi', 'height=800, width=900, toolbar=no, menubar=no, scrollbars=no, resizable=yes, location=no, directories=no, status=no');
timer = setInterval(checkChild, 500);
return false;
}
function checkChild() {
if (popup.closed) {
pay_open.style.display='none';
pay_close.style.display='block';
document.getElementById('pay').innerHTML = '<p><strong>Fenêtre de paiement fermée.</strong></p>';
clearInterval(timer);
}
}
</script>
{% endif %}
{% endblock %}

View File

@ -1,59 +0,0 @@
{% extends "base.html" %}
{% block breadcrumbs %}
<li>Paiement de la facture {{ invoice_id }}</li>
{% endblock %}
{% block content %}
{% if paid %}
<h1>Cette facture a déjà été payée !</h1>
{% if paid_date %}
le {{ paid_date.date|date:"d/m/Y" }} &agrave; {{ paid_date.date|date:"H:i" }}
{% endif %}
{% else %}
<h1>Attention ! Le paiement de cette facture est peut-être déjà en cours.</h1>
<div class="wrapSpecial"><div class="rteContent">
<p>
Attention ! Une transaction de paiement pour cette facture {{ invoice_id }}
est en cours depuis le {{ last_transaction_date|date:"d/m/Y" }}
à {{ last_transaction_date|date:'H:i' }}.
</p>
<script>
function force_new() {
c = confirm("Êtes-vous vraiment certain-e que cette facture {{invoice_id}} n'a pas déjà été payée, même par une autre personne ?\nSi vous avez un doute, nous vous conseillons d'annuler et d'attendre deux jours : après ce délai la ville aura été informée d'un paiement. Vous pourrez alors voir si la facture a vraiment été payée ou non.\n");
if (c == false) {
window.close();
};
return c;
}
</script>
<p>
{% if force_new_transaction_allowed %}
Si vous aviez abandonné un paiement précédent,
si vous êtes sûr-e que cette facture n'a pas été payée,
vous pouvez relancer le paiement en cliquant ici :
<a href="{% url "transaction" slug invoice_id invoice_hash %}?force&{{ request.GET.urlencode }}"
onclick="return force_new();">
lancer une nouvelle demande de paiement
</a>.
<br/>
<strong>Attention, ne cliquez que si vous êtes sûr-e que
la transaction précédente n'a pas fonctionné et a bien été
abandonnée, et si vous êtes certain-e que le paiement de
la facture {{invoice_id}} n'a pas été fait par quelqu'un
d'autre.</strong>
{% endif %}
</p>
</div></div>
{% endif %}
{% endblock content %}

View File

@ -1,9 +0,0 @@
from django import template
from decimal import Decimal
register = template.Library()
@register.filter
def decimal(value):
return Decimal(value)

View File

@ -1,7 +0,0 @@
from django import template
register = template.Library()
def payment_url(invoice_id, invoice_hash):
return reverse('transaction', args=('tipi', invoice_id, invoice_hash))

View File

@ -1,17 +0,0 @@
from django.conf.urls import patterns, include, url
from .views import InvoiceView, InvoiceDownloadView, TransactionView, TransactionResponseListView
urlpatterns = patterns('',
url(r'^simple/(?P<slug>\w+)/(?P<id>\w+)/(?P<hash>\w+)$',
InvoiceView.as_view(),
name='invoice'),
url(r'^details/(?P<slug>\w+)/(?P<id>\w+)/(?P<hash>\w+)$',
InvoiceDownloadView.as_view(),
name='invoice-download'),
url(r'^transaction/(?P<slug>\w+)/(?P<id>\w+)/(?P<hash>\w+)$',
TransactionView.as_view(),
name='transaction'),
url(r'^responses/(?P<regie>\w+).(?P<days>\d+).csv$',
TransactionResponseListView.as_view(),
name='responses'),
)

View File

@ -1,278 +0,0 @@
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.decorators import login_required
from django.views.generic import DetailView, ListView
from django.http import HttpResponse, HttpResponseForbidden
from django.template import RequestContext
from django.core.urlresolvers import reverse
from django.shortcuts import redirect
from django.core.exceptions import ObjectDoesNotExist
from . import app_settings
import datetime
import eopayment
from .models import Regie, TransactionEvent
from portail_citoyen.apps.data_source_plugin.cms_plugins import Data
import logging
logger = logging.getLogger(__name__)
class LoginRequiredMixin(object):
@classmethod
def as_view(cls, **initkwargs):
view = super(LoginRequiredMixin, cls).as_view(**initkwargs)
return login_required(view)
class InvoiceView(DetailView):
model = Regie
http_method_names = [u'get']
def get_template_names(self):
return ('facturier/%s.html' % self.object.slug,
'facturier/%s.html' % self.object.service)
def get_object_and_invoice(self, **kwargs):
self.object = self.get_object()
self.invoice = self.object.get_invoice(kwargs['id'],
kwargs['hash'], self.request)
def get_context_data(self):
context = super(InvoiceView, self).get_context_data()
context['invoice'] = self.invoice
return context
def get(self, request, *args, **kwargs):
self.get_object_and_invoice(**kwargs)
context = self.get_context_data()
return self.render_to_response(context)
class InvoiceDownloadView(LoginRequiredMixin, InvoiceView):
def get(self, request, *args, **kwargs):
self.get_object_and_invoice(**kwargs)
# if invoice can't be downloaded, stop here
if not self.invoice.get('download_url'):
return HttpResponseForbidden()
context = self.get_context_data()
filename = app_settings.download_filename.format(**context)
mimetype = app_settings.download_filename_mimetype
return HttpResponse(open(filename, 'rb'), mimetype=mimetype)
class TransactionView(DetailView):
model = Regie
template_name = 'facturier/transaction.html'
http_method_names = [u'get', u'post']
def create_event(self, transaction_id, invoice_id, status,
response=False, message=None, details={}):
address=self.request.META.get('HTTP_X_REAL_IP') or \
self.request.META.get('HTTP_X_FORWARDED_FOR') or \
self.request.META.get('REMOTE_ADDR')
details['message'] = message
TransactionEvent.objects.create(invoice_id=invoice_id,
regie=self.object,
transaction_id=transaction_id,
address=address,
response=response,
status=status,
details=details)
def create_transaction(self, options, invoice, context, message=None):
p = eopayment.Payment(kind=self.object.service,
options=options)
transaction_id, kind, redirect_url = p.request(**invoice)
assert kind == eopayment.URL
self.create_event(transaction_id, context['invoice_id'], 'CREATED',
message=message)
return transaction_id, redirect_url
def handle_transaction(self, invoice, context):
"""
checks if a transaction exists, otherwise creates a new transaction.
"""
service_options = dict([(option.name, option.value) \
for option in self.object.serviceoption_set.all()])
try:
event = TransactionEvent.objects.filter(regie=self.object,
invoice_id=context['invoice_id']).latest()
except ObjectDoesNotExist:
# this is a new invoice : create a new transaction
transaction_id, redirect_url = self.create_transaction(service_options,
invoice, context, message='new')
context.update({'redirect_url': redirect_url})
else:
if event.status == 'PAID':
# a online payment took place = the user can't pay again
context['paid'] = True
context['paid_date'] = event.date
elif event.status == 'CREATED' and 'force' in self.request.GET:
# the user want to force a new transaction : cancel the current
# one and create a new one
self.create_event(event.transaction_id, context['invoice_id'],
status='CANCELED',
message='forced by user')
transaction_id, redirect_url = self.create_transaction(service_options,
invoice, context,
message='forced by user, replace %s' % event.transaction_id)
context.update({'redirect_url': redirect_url})
elif event.status == 'CREATED':
# there is a current transaction: propose to "force" a new transaction
context['force_new_transaction_allowed'] = True
context['last_transaction_date'] = event.date
else:
# the last transaction is closed (cancel, error, test, etc.):
# create a new one
transaction_id, redirect_url = self.create_transaction(service_options,
invoice, context,
message='recreated after %s of %s' % (event.status, event.transaction_id))
context.update({'redirect_url': redirect_url})
return context
def invoice_rest_request(self, data_source_url, context):
data = Data(data_source_url, RequestContext(self.request, context),
limit=None, refresh=None)
return data.update_content().get('data').get('invoice')
def get_context_data(self, **kwargs):
context = super(TransactionView, self).get_context_data(**kwargs)
invoice_id = self.kwargs['id']
invoice_hash = self.kwargs['hash']
slug = self.object.slug # (self.object is a "Regie")
# create an invoice :
# 1. create a base from request and regie options
invoice = {}
if hasattr(self.request.user, 'email'):
invoice['email'] = self.request.user.email
request_options = dict([(option.name, option.value) \
for option in self.object.requestoption_set.all()])
invoice.update(request_options)
# get invoice from the regie (webservice)
context.update({'invoice_id': invoice_id,
'invoice_hash': invoice_hash,
'slug': slug,
'paid': False,})
invoice_data = self.invoice_rest_request(self.object.get_url, context)
invoice.update(invoice_data)
# invoice can be overriden by request.GET parameters
if self.request.GET:
for k, v in self.request.GET.iteritems():
if k in invoice:
invoice[k] = v
# invoice is paid : stop now
if invoice.get('paid'):
context['paid'] = True
return context
next_url = reverse('transaction', args=(slug, invoice_id, invoice_hash))
if request_options.get('next_url_base'):
invoice['next_url'] = str('%s%s' % (request_options['next_url_base'] ,next_url))
else:
invoice['next_url'] = self.request.build_absolute_uri(next_url)
context.update({'details': invoice})
self.handle_transaction(invoice, context)
logger.debug('payment request: context %s' % context)
return context
def get(self, request, *args, **kwargs):
self.object = self.get_object()
context = self.get_context_data(object=self.object)
if context.get('redirect_url'):
return redirect(context['redirect_url'], permanent=False)
return self.render_to_response(context)
# don't use CSRF protection (for post)
@csrf_exempt
def dispatch(self, *args, **kwargs):
return super(TransactionView, self).dispatch(*args, **kwargs)
def post(self, request, *args, **kwargs):
logger.debug('payment response: path %s' % request.path)
query_string = str(request.META['QUERY_STRING'])
if not query_string:
if request.META['CONTENT_TYPE'] == 'application/x-www-form-urlencoded':
query_string = str(request.body)
logger.debug('payment response: query_string %s', query_string)
self.object = self.get_object()
service_options = dict([(option.name, option.value) \
for option in self.object.serviceoption_set.all()])
invoice_id = self.kwargs['id']
invoice_hash = self.kwargs['hash']
logger.debug('payment response: invoice %s', invoice_id)
try:
event = TransactionEvent.objects.filter(regie=self.object,
invoice_id=invoice_id).latest()
logger.debug('payment response: found transaction %s', event.transaction_id)
except ObjectDoesNotExist:
logger.warn('payment response: no transaction for invoice %s', invoice_id)
return HttpResponse(status=404) # HTTP Not Found
if event.status != 'CREATED':
logger.warn('payment response: transaction status != CREATED')
return HttpResponse(status=410) # HTTP Gone
backend = eopayment.Payment(kind=self.object.service, options=service_options)
response = backend.response(query_string)
logger.debug('payment response: response %s', response)
if response.result == eopayment.common.PAID:
status = 'PAID'
else:
status = 'ERROR'
if response.test:
status = 'TEST_%s' % status
context = {
'invoice_id': invoice_id,
'invoice_hash': invoice_hash,
'status': status
}
logger.debug('payment response: close transaction %s' % event.transaction_id)
self.create_event(event.transaction_id, invoice_id, status,
response=True, message='response', details=response.__dict__)
logger.debug('payment response: update invoice PAID %s -- context %s' %
(self.object.update_url, context))
self.invoice_rest_request(self.object.update_url, context)
# ok !
logger.debug('payment response: OK invoice %s', invoice_id)
return HttpResponse(status=200)
class TransactionResponseListView(ListView):
content_type = 'text/csv'
def get_regie(self):
self.regie = Regie.objects.filter(slug=self.kwargs['regie']).get()
def get_template_names(self):
return ('facturier/response-%s.csv' % self.regie.slug,
'facturier/response-%s.csv' % self.regie.service)
def get_queryset(self):
days = int(self.kwargs.get('days', 5))
day_start = datetime.datetime.now() - datetime.timedelta(days)
return TransactionEvent.objects.filter(regie=self.regie,
response=True,
date__gte=day_start)
def get(self, request, *args, **kwargs):
if request.GET.get('key') != app_settings.responses_csv_key:
return HttpResponseForbidden('forbidden')
self.get_regie()
return super(TransactionResponseListView, self).\
get(request, *args, **kwargs)