misc: apply double-quote-string-fixer (#79788)
This commit is contained in:
parent
5b36982e20
commit
f1941a3ad8
|
@ -14,7 +14,7 @@ STATIC_ROOT = os.path.join(VAR_DIR, 'collected-static')
|
|||
MEDIA_ROOT = os.path.join(VAR_DIR, 'media')
|
||||
ETC_DIR = '/etc/barbacompta/'
|
||||
|
||||
with open("/etc/barbacompta/secret") as fd:
|
||||
with open('/etc/barbacompta/secret') as fd:
|
||||
SECRET_KEY = fd.read()
|
||||
|
||||
DEBUG = False
|
||||
|
@ -29,8 +29,8 @@ if os.path.exists('/etc/barbacompta/idp-metadata.xml'):
|
|||
'first_name': '{attributes[first_name][0]}',
|
||||
'last_name': '{attributes[last_name][0]}',
|
||||
}
|
||||
MELLON_SUPERUSER_MAPPING = {"is_superuser": ("true",)}
|
||||
MELLON_USERNAME_TEMPLATE = "{attributes[username][0]}"
|
||||
MELLON_SUPERUSER_MAPPING = {'is_superuser': ('true',)}
|
||||
MELLON_USERNAME_TEMPLATE = '{attributes[username][0]}'
|
||||
MELLON_PUBLIC_KEYS = ['/etc/barbacompta/saml.crt']
|
||||
MELLON_PRIVATE_KEY = '/etc/barbacompta/saml.key'
|
||||
MELLON_IDENTITY_PROVIDERS = [{'METADATA': '/etc/barbacompta/idp-metadata.xml'}]
|
||||
|
|
|
@ -32,8 +32,8 @@ def export_as_csv(modeladmin, request, queryset):
|
|||
if not request.user.is_staff:
|
||||
raise PermissionDenied
|
||||
opts = modeladmin.model._meta
|
||||
response = HttpResponse(content_type="text/csv")
|
||||
response["Content-Disposition"] = "attachment; filename=%s.csv" % str(opts).replace(".", "_")
|
||||
response = HttpResponse(content_type='text/csv')
|
||||
response['Content-Disposition'] = 'attachment; filename=%s.csv' % str(opts).replace('.', '_')
|
||||
writer = csv.writer(response)
|
||||
field_names = [field.name for field in opts.fields]
|
||||
m2m_field_names = [m2m_field.name for m2m_field in opts.many_to_many]
|
||||
|
@ -44,13 +44,13 @@ def export_as_csv(modeladmin, request, queryset):
|
|||
values = [str(getattr(obj, field)) for field in field_names]
|
||||
for m2m_field in m2m_field_names:
|
||||
value = getattr(obj, m2m_field)
|
||||
value = ",".join(map(str, value.all()))
|
||||
value = ','.join(map(str, value.all()))
|
||||
values.append(str(value))
|
||||
writer.writerow(map(lambda x: str.encode(x, "utf8"), values))
|
||||
writer.writerow(map(lambda x: str.encode(x, 'utf8'), values))
|
||||
return response
|
||||
|
||||
|
||||
export_as_csv.short_description = "Export selected objects as csv file"
|
||||
export_as_csv.short_description = 'Export selected objects as csv file'
|
||||
|
||||
|
||||
def export_references_as_fodt(modeladmin, request, queryset):
|
||||
|
@ -73,7 +73,7 @@ def export_references_as_fodt(modeladmin, request, queryset):
|
|||
return response
|
||||
|
||||
|
||||
export_references_as_fodt.short_description = _("Export selected contracts as fodt file")
|
||||
export_references_as_fodt.short_description = _('Export selected contracts as fodt file')
|
||||
|
||||
|
||||
def export_invoices_as_zip(modeladmin, request, queryset):
|
||||
|
@ -88,4 +88,4 @@ def export_invoices_as_zip(modeladmin, request, queryset):
|
|||
return response
|
||||
|
||||
|
||||
export_invoices_as_zip.short_description = _("Export selected invoices")
|
||||
export_invoices_as_zip.short_description = _('Export selected invoices')
|
||||
|
|
|
@ -33,19 +33,19 @@ User = get_user_model()
|
|||
class EOGestionAdminSite(admin.AdminSite):
|
||||
@never_cache
|
||||
def login(self, request, extra_context=None):
|
||||
if "mellon" in settings.INSTALLED_APPS:
|
||||
next_url = request.GET.get(REDIRECT_FIELD_NAME, settings.LOGIN_REDIRECT_URL or "/")
|
||||
if 'mellon' in settings.INSTALLED_APPS:
|
||||
next_url = request.GET.get(REDIRECT_FIELD_NAME, settings.LOGIN_REDIRECT_URL or '/')
|
||||
query = urlencode({REDIRECT_FIELD_NAME: next_url})
|
||||
url = f"/accounts/mellon/login/?{query}"
|
||||
url = f'/accounts/mellon/login/?{query}'
|
||||
return HttpResponseRedirect(url)
|
||||
return super().login(request, extra_context=extra_context)
|
||||
|
||||
@never_cache
|
||||
def logout(self, request, extra_context=None):
|
||||
if "mellon" in settings.INSTALLED_APPS:
|
||||
next_url = request.GET.get(REDIRECT_FIELD_NAME, settings.LOGIN_REDIRECT_URL or "/")
|
||||
if 'mellon' in settings.INSTALLED_APPS:
|
||||
next_url = request.GET.get(REDIRECT_FIELD_NAME, settings.LOGIN_REDIRECT_URL or '/')
|
||||
query = urlencode({REDIRECT_FIELD_NAME: next_url})
|
||||
url = f"/accounts/mellon/logout/?{query}"
|
||||
url = f'/accounts/mellon/logout/?{query}'
|
||||
return HttpResponseRedirect(url)
|
||||
return super().logout(request, extra_context=extra_context)
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ class LigneBanquePopAdmin(admin.ModelAdmin):
|
|||
|
||||
def get_queryset(self, request):
|
||||
qs = super().get_queryset(request)
|
||||
qs = qs.prefetch_related("payments")
|
||||
qs = qs.prefetch_related('payments')
|
||||
return qs
|
||||
|
||||
def has_add_permission(self, request):
|
||||
|
|
|
@ -29,7 +29,7 @@ class Command(BaseCommand):
|
|||
]
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument("args", nargs="+")
|
||||
parser.add_argument('args', nargs='+')
|
||||
|
||||
def to_date(self, str):
|
||||
try:
|
||||
|
@ -38,13 +38,13 @@ class Command(BaseCommand):
|
|||
return datetime.strptime(str, '%d/%m/%Y').date()
|
||||
|
||||
def make_csv_reader(self, csv_file):
|
||||
for delimiter in [";", "\t"]:
|
||||
for delimiter in [';', '\t']:
|
||||
csv_file.seek(0)
|
||||
csv_lines = csv.reader(csv_file, delimiter=delimiter)
|
||||
first_line = next(csv_lines)
|
||||
if first_line == self.HEADER:
|
||||
return csv_lines
|
||||
raise CommandError("Invalid CSV file header")
|
||||
raise CommandError('Invalid CSV file header')
|
||||
|
||||
def load_one_file(self, csv_file_path, csv_lines):
|
||||
counter = 0
|
||||
|
|
|
@ -14,8 +14,8 @@ class Command(BaseCommand):
|
|||
can_import_django_settings = True
|
||||
output_transaction = True
|
||||
requires_system_checks = True
|
||||
args = "<csv_file> <csv_file>..."
|
||||
help = "Charge le solde courant"
|
||||
args = '<csv_file> <csv_file>...'
|
||||
help = 'Charge le solde courant'
|
||||
|
||||
@transaction.atomic
|
||||
def handle(self, compte, montant, **options):
|
||||
|
|
|
@ -26,7 +26,7 @@ def solde(t=None):
|
|||
if t is None:
|
||||
t = date.today()
|
||||
try:
|
||||
s = SoldeBanquePop.objects.latest("date")
|
||||
s = SoldeBanquePop.objects.latest('date')
|
||||
except SoldeBanquePop.DoesNotExist:
|
||||
return 0
|
||||
m = s.montant
|
||||
|
@ -50,10 +50,10 @@ class Commentaire(models.Model):
|
|||
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
|
||||
object_id = models.PositiveIntegerField()
|
||||
creation = models.DateTimeField(auto_now_add=True)
|
||||
content_object = GenericForeignKey("content_type", "object_id")
|
||||
content_object = GenericForeignKey('content_type', 'object_id')
|
||||
|
||||
def __str__(self):
|
||||
return "Commentaire créé le %s" % self.creation
|
||||
return 'Commentaire créé le %s' % self.creation
|
||||
|
||||
|
||||
class LigneBanquePop(models.Model):
|
||||
|
@ -78,7 +78,7 @@ class LigneBanquePop(models.Model):
|
|||
]
|
||||
|
||||
def __str__(self):
|
||||
return "%(date_valeur)s %(libelle)s %(montant)s" % self.__dict__
|
||||
return '%(date_valeur)s %(libelle)s %(montant)s' % self.__dict__
|
||||
|
||||
def montant_non_affecte(self):
|
||||
return self.montant - sum(x.montant_affecte for x in self.payments.all())
|
||||
|
|
|
@ -34,7 +34,7 @@ def month_before(date):
|
|||
return date.replace(month=date.month - 1)
|
||||
|
||||
|
||||
@register.inclusion_tag("eo_banque/finances.html")
|
||||
@register.inclusion_tag('eo_banque/finances.html')
|
||||
@cache
|
||||
def finances(month=3):
|
||||
dates = [date.today().replace(day=1)]
|
||||
|
@ -82,8 +82,8 @@ def finances(month=3):
|
|||
|
||||
@register.inclusion_tag('eo_banque/total.html', takes_context=True)
|
||||
def total(context):
|
||||
qs = context["cl"].get_queryset(context["request"])
|
||||
ls = [ligne[0] for ligne in qs.values_list("montant")]
|
||||
qs = context['cl'].get_queryset(context['request'])
|
||||
ls = [ligne[0] for ligne in qs.values_list('montant')]
|
||||
credit = sum(montant for montant in ls if montant > 0)
|
||||
debit = sum(montant for montant in ls if montant < 0)
|
||||
total = sum(ls)
|
||||
|
@ -91,14 +91,14 @@ def total(context):
|
|||
|
||||
|
||||
def iso_year_start(iso_year):
|
||||
"The gregorian calendar date of the first day of the given ISO year"
|
||||
'The gregorian calendar date of the first day of the given ISO year'
|
||||
fourth_jan = date(iso_year, 1, 4)
|
||||
delta = timedelta(fourth_jan.isoweekday() - 1)
|
||||
return fourth_jan - delta
|
||||
|
||||
|
||||
def iso_to_gregorian(iso_year, iso_week, iso_day):
|
||||
"Gregorian calendar date for the given ISO year, week and day"
|
||||
'Gregorian calendar date for the given ISO year, week and day'
|
||||
year_start = iso_year_start(iso_year)
|
||||
return year_start + timedelta(iso_day - 1, 0, 0, 0, 0, 0, iso_week - 1)
|
||||
|
||||
|
@ -123,16 +123,16 @@ def week_start_and_end(year, month):
|
|||
]
|
||||
|
||||
|
||||
@register.inclusion_tag("admin/date_hierarchy.html")
|
||||
@register.inclusion_tag('admin/date_hierarchy.html')
|
||||
def eo_banque_date_hierarchy(cl):
|
||||
if cl.date_hierarchy:
|
||||
field_name = cl.date_hierarchy
|
||||
year_field = "%s__year" % field_name
|
||||
month_field = "%s__month" % field_name
|
||||
day_field = "%s__day" % field_name
|
||||
field_generic = "%s__" % field_name
|
||||
field_gte = "%s__gte" % field_name
|
||||
field_lte = "%s__lte" % field_name
|
||||
year_field = '%s__year' % field_name
|
||||
month_field = '%s__month' % field_name
|
||||
day_field = '%s__day' % field_name
|
||||
field_generic = '%s__' % field_name
|
||||
field_gte = '%s__gte' % field_name
|
||||
field_lte = '%s__lte' % field_name
|
||||
year_lookup = cl.params.get(year_field)
|
||||
month_lookup = cl.params.get(month_field)
|
||||
day_lookup = cl.params.get(day_field)
|
||||
|
|
|
@ -75,11 +75,11 @@ class PaymentInlineFormset(BaseInlineFormSet):
|
|||
super().__init__(*args, **kwargs)
|
||||
for form in self.forms:
|
||||
if form.instance.id is None:
|
||||
field = form.fields["ligne_banque_pop"]
|
||||
if not hasattr(field, "parent_instance"):
|
||||
field = form.fields['ligne_banque_pop']
|
||||
if not hasattr(field, 'parent_instance'):
|
||||
field.queryset = models.encaissements_avec_solde_non_affecte()
|
||||
field = form.fields["facture"]
|
||||
if not hasattr(field, "parent_instance"):
|
||||
field = form.fields['facture']
|
||||
if not hasattr(field, 'parent_instance'):
|
||||
field.queryset = models.Facture.objects.avec_solde()
|
||||
|
||||
|
||||
|
@ -96,7 +96,7 @@ class LigneInline(SelectRelatedMixin, SortableInlineAdminMixin, admin.TabularInl
|
|||
form = forms.LigneForm
|
||||
model = models.Ligne
|
||||
original = False
|
||||
verbose_name_plural = "Lignes de facture (vous pouvez les réordonner par drag&drop)"
|
||||
verbose_name_plural = 'Lignes de facture (vous pouvez les réordonner par drag&drop)'
|
||||
formfield_overrides = {
|
||||
TextField: {
|
||||
'widget': Textarea(attrs={'cols': 30, 'rows': 1}),
|
||||
|
@ -156,7 +156,7 @@ def show_client(obj):
|
|||
url = reverse('admin:eo_facture_client_change', args=[obj.client.id])
|
||||
return format_html('<a href="{0}">{1}</a>', url, obj.client)
|
||||
else:
|
||||
return ""
|
||||
return ''
|
||||
|
||||
|
||||
show_client.short_description = 'Client'
|
||||
|
@ -169,7 +169,7 @@ class ContratAdmin(LookupAllowed, admin.ModelAdmin):
|
|||
PrestationInline,
|
||||
]
|
||||
list_display = [
|
||||
"__str__",
|
||||
'__str__',
|
||||
show_client,
|
||||
'column_montant',
|
||||
'pourcentage_facture',
|
||||
|
@ -226,7 +226,7 @@ class ContratAdmin(LookupAllowed, admin.ModelAdmin):
|
|||
'opts': self.model._meta,
|
||||
}
|
||||
|
||||
return render(request, "admin/eo_facture/contrat/duplicate.html", context=context)
|
||||
return render(request, 'admin/eo_facture/contrat/duplicate.html', context=context)
|
||||
|
||||
def facturer_echeance(self, request, object_id):
|
||||
if request.method != 'POST':
|
||||
|
@ -284,7 +284,7 @@ def index(facture):
|
|||
return format_html('{0}', ordinal(facture.index()))
|
||||
|
||||
|
||||
index.short_description = "Ordre"
|
||||
index.short_description = 'Ordre'
|
||||
|
||||
|
||||
class FactureAdmin(LookupAllowed, admin.ModelAdmin):
|
||||
|
@ -333,7 +333,7 @@ class FactureAdmin(LookupAllowed, admin.ModelAdmin):
|
|||
|
||||
def column_code(self, obj):
|
||||
if obj.montant < 0:
|
||||
return "Avoir %s" % obj.code()
|
||||
return 'Avoir %s' % obj.code()
|
||||
else:
|
||||
return obj.code()
|
||||
|
||||
|
@ -364,16 +364,16 @@ class FactureAdmin(LookupAllowed, admin.ModelAdmin):
|
|||
from django.db import connection
|
||||
|
||||
qs = super().get_queryset(request)
|
||||
qs = qs.prefetch_related("lignes__facture__client")
|
||||
qs = qs.prefetch_related("payments__ligne_banque_pop")
|
||||
qs = qs.prefetch_related("contrat__factures")
|
||||
if connection.vendor == "postgresql":
|
||||
qs = qs.extra({"year": "EXTRACT(year FROM emission)"})
|
||||
elif connection.vendor == "sqlite":
|
||||
qs = qs.extra({"year": "strftime('%Y', emission)"})
|
||||
qs = qs.prefetch_related('lignes__facture__client')
|
||||
qs = qs.prefetch_related('payments__ligne_banque_pop')
|
||||
qs = qs.prefetch_related('contrat__factures')
|
||||
if connection.vendor == 'postgresql':
|
||||
qs = qs.extra({'year': 'EXTRACT(year FROM emission)'})
|
||||
elif connection.vendor == 'sqlite':
|
||||
qs = qs.extra({'year': "strftime('%Y', emission)"})
|
||||
else:
|
||||
qs = qs.extra({"year": "YEAR(emission)"})
|
||||
qs = qs.order_by("-year", "-proforma", "-ordre")
|
||||
qs = qs.extra({'year': 'YEAR(emission)'})
|
||||
qs = qs.order_by('-year', '-proforma', '-ordre')
|
||||
return qs
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
|
@ -383,7 +383,7 @@ class FactureAdmin(LookupAllowed, admin.ModelAdmin):
|
|||
|
||||
def add_simple(self, request):
|
||||
context = {}
|
||||
if request.method == "POST":
|
||||
if request.method == 'POST':
|
||||
form = forms.RapidFactureForm(request=request, data=request.POST)
|
||||
if form.is_valid():
|
||||
return http.HttpResponseRedirect(
|
||||
|
@ -398,11 +398,11 @@ class FactureAdmin(LookupAllowed, admin.ModelAdmin):
|
|||
'opts': self.model._meta,
|
||||
}
|
||||
|
||||
return render(request, "admin/eo_facture/facture/add_simple.html", context=context)
|
||||
return render(request, 'admin/eo_facture/facture/add_simple.html', context=context)
|
||||
|
||||
def sheet(self, request):
|
||||
workbook = ods.Workbook()
|
||||
ws = workbook.add_sheet("Factures")
|
||||
ws = workbook.add_sheet('Factures')
|
||||
for i, header_name in enumerate(
|
||||
['Référence', 'Nom client', 'Date', 'Montant HT', 'Montant TTC', 'TVA']
|
||||
):
|
||||
|
@ -447,9 +447,9 @@ class FactureAdmin(LookupAllowed, admin.ModelAdmin):
|
|||
name='eo_facture_facture_send_to_chorus',
|
||||
),
|
||||
url(
|
||||
r"^sheet/$",
|
||||
r'^sheet/$',
|
||||
self.admin_site.admin_view(self.sheet),
|
||||
name="eo_facture_facture_sheet",
|
||||
name='eo_facture_facture_sheet',
|
||||
),
|
||||
url(
|
||||
r'^(.+)/cancel/',
|
||||
|
|
|
@ -31,8 +31,8 @@ class PercentagePerYear(list):
|
|||
|
||||
class EuroField(models.DecimalField):
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs["max_digits"] = 8
|
||||
kwargs["decimal_places"] = 2
|
||||
kwargs['max_digits'] = 8
|
||||
kwargs['decimal_places'] = 2
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
|
@ -51,22 +51,22 @@ def check_percentage_per_year(value):
|
|||
years = [a for a, b in value]
|
||||
percentages = [b for a, b in value]
|
||||
# ordered
|
||||
assert years == sorted(years), "years are not ordered"
|
||||
assert years == sorted(years), 'years are not ordered'
|
||||
# sum equals 100
|
||||
assert sum(percentages) == 1, "percentage does not sum to 100"
|
||||
assert sum(percentages) == 1, 'percentage does not sum to 100'
|
||||
# no duplicate year
|
||||
assert len(years) == len(set(years)), "years are not unique"
|
||||
assert len(years) == len(set(years)), 'years are not unique'
|
||||
# consecutive
|
||||
assert years == list(range(years[0], years[0] + len(years))), 'years are not consecutive'
|
||||
|
||||
|
||||
def parse_percentage_per_year(value):
|
||||
msg = _("field must be numeric values separated by commas")
|
||||
values = value.split(",")
|
||||
msg = _('field must be numeric values separated by commas')
|
||||
values = value.split(',')
|
||||
decimals = []
|
||||
for value in values:
|
||||
try:
|
||||
year, decimal = value.split(":")
|
||||
year, decimal = value.split(':')
|
||||
except ValueError:
|
||||
raise ValidationError(msg)
|
||||
try:
|
||||
|
@ -92,7 +92,7 @@ class PercentagePerYearFormField(forms.Field):
|
|||
if isinstance(PercentagePerYear, value):
|
||||
return value
|
||||
if not isinstance(str, value):
|
||||
raise ValidationError(self.default_error_messages["invalid"])
|
||||
raise ValidationError(self.default_error_messages['invalid'])
|
||||
return parse_percentage_per_year(value)
|
||||
|
||||
|
||||
|
@ -114,7 +114,7 @@ class PercentagePerYearField(models.Field):
|
|||
default_validators = [check_percentage_per_year]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs["max_length"] = 64
|
||||
kwargs['max_length'] = 64
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def from_db_value(self, value, expression, connection):
|
||||
|
@ -125,12 +125,12 @@ class PercentagePerYearField(models.Field):
|
|||
return value
|
||||
if value is not None:
|
||||
percentage_per_year = []
|
||||
pairs = value.split(",")
|
||||
pairs = value.split(',')
|
||||
for pair in pairs:
|
||||
try:
|
||||
year, percentage = map(value.__class__.strip, pair.split(":"))
|
||||
year, percentage = map(value.__class__.strip, pair.split(':'))
|
||||
except ValueError:
|
||||
raise ValidationError(PercentagePerYearFormField.default_error_messages["invalid"])
|
||||
raise ValidationError(PercentagePerYearFormField.default_error_messages['invalid'])
|
||||
year = int(year)
|
||||
percentage = Decimal(percentage) / Decimal(100)
|
||||
percentage_per_year.append((year, percentage))
|
||||
|
@ -150,10 +150,10 @@ class PercentagePerYearField(models.Field):
|
|||
return super().get_prep_value(value)
|
||||
|
||||
def get_internal_type(self):
|
||||
return "CharField"
|
||||
return 'CharField'
|
||||
|
||||
def formfield(self, **kwargs):
|
||||
defaults = {"form_class": PercentagePerYearFormField}
|
||||
defaults = {'form_class': PercentagePerYearFormField}
|
||||
defaults.update(kwargs)
|
||||
return super().formfield(**kwargs)
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ from django.db.transaction import atomic
|
|||
|
||||
from . import models
|
||||
|
||||
pourcentages = [(Decimal(i) / 100, "%s %%" % i) for i in range(0, 101, 5)]
|
||||
pourcentages = [(Decimal(i) / 100, '%s %%' % i) for i in range(0, 101, 5)]
|
||||
|
||||
|
||||
class RapidFactureForm(forms.Form):
|
||||
|
@ -51,7 +51,7 @@ class RapidFactureForm(forms.Form):
|
|||
except ValidationError as e:
|
||||
raise forms.ValidationError('clean facture %s' % facture.code(), *e.args)
|
||||
facture.save()
|
||||
self.cleaned_data["facture"] = facture
|
||||
self.cleaned_data['facture'] = facture
|
||||
lignes = []
|
||||
errors = []
|
||||
if solde:
|
||||
|
@ -73,8 +73,8 @@ class RapidFactureForm(forms.Form):
|
|||
try:
|
||||
ligne.clean()
|
||||
except ValidationError as e:
|
||||
error = "Il y a un problème avec la ligne « %s »: " % prestation.intitule
|
||||
error += "; ".join(map(lambda x: x.rstrip("."), e.messages))
|
||||
error = 'Il y a un problème avec la ligne « %s »: ' % prestation.intitule
|
||||
error += '; '.join(map(lambda x: x.rstrip('.'), e.messages))
|
||||
errors.append(error)
|
||||
if errors:
|
||||
raise forms.ValidationError(errors)
|
||||
|
@ -87,7 +87,7 @@ class RapidFactureForm(forms.Form):
|
|||
|
||||
class DuplicateContractForm(forms.Form):
|
||||
contrat = forms.ModelChoiceField(queryset=models.Contrat.objects.all())
|
||||
new_intitule = forms.CharField(max_length=150, label="Nouvel intitulé")
|
||||
new_intitule = forms.CharField(max_length=150, label='Nouvel intitulé')
|
||||
|
||||
def __init__(self, request=None, *args, **kwargs):
|
||||
self.request = request
|
||||
|
@ -109,7 +109,7 @@ class DuplicateContractForm(forms.Form):
|
|||
except ValidationError as e:
|
||||
raise forms.ValidationError('clean contrat %s' % contrat.intitule, *e.args)
|
||||
new_contrat.save()
|
||||
self.cleaned_data["new_contrat"] = new_contrat
|
||||
self.cleaned_data['new_contrat'] = new_contrat
|
||||
for prestation in contrat.prestations.all():
|
||||
new_prestation = prestation.duplicate()
|
||||
new_prestation.contrat = new_contrat
|
||||
|
@ -121,14 +121,14 @@ class LigneForm(forms.ModelForm):
|
|||
class Meta:
|
||||
fields = '__all__'
|
||||
model = models.Ligne
|
||||
localized_fields = ("quantite", "prix_unitaire_ht", "taux_tva")
|
||||
localized_fields = ('quantite', 'prix_unitaire_ht', 'taux_tva')
|
||||
|
||||
|
||||
class PrestationForm(forms.ModelForm):
|
||||
class Meta:
|
||||
fields = '__all__'
|
||||
model = models.Prestation
|
||||
localized_fields = ("quantite", "prix_unitaire_ht")
|
||||
localized_fields = ('quantite', 'prix_unitaire_ht')
|
||||
|
||||
|
||||
class FactureForm(forms.ModelForm):
|
||||
|
@ -189,17 +189,17 @@ class FactureForm(forms.ModelForm):
|
|||
class Meta:
|
||||
fields = '__all__'
|
||||
model = models.Facture
|
||||
localized_fields = ("taux_tva",)
|
||||
localized_fields = ('taux_tva',)
|
||||
|
||||
|
||||
class ClientForm(forms.ModelForm):
|
||||
class Meta:
|
||||
fields = '__all__'
|
||||
model = models.Client
|
||||
localized_fields = ("tva",)
|
||||
localized_fields = ('tva',)
|
||||
widgets = {
|
||||
"adresse": widgets.AdminTextareaWidget(attrs={"rows": 4}),
|
||||
"contacts": widgets.AdminTextareaWidget(attrs={"rows": 4}),
|
||||
'adresse': widgets.AdminTextareaWidget(attrs={'rows': 4}),
|
||||
'contacts': widgets.AdminTextareaWidget(attrs={'rows': 4}),
|
||||
}
|
||||
|
||||
|
||||
|
@ -215,7 +215,7 @@ class ContratForm(forms.ModelForm):
|
|||
class Meta:
|
||||
fields = '__all__'
|
||||
model = models.Contrat
|
||||
localized_fields = ("tva", "montant_sous_traite")
|
||||
localized_fields = ('tva', 'montant_sous_traite')
|
||||
|
||||
class Media:
|
||||
js = ['facture.js']
|
||||
|
@ -225,4 +225,4 @@ class PaymentForm(forms.ModelForm):
|
|||
class Meta:
|
||||
fields = '__all__'
|
||||
model = models.Payment
|
||||
localized_fields = ("montant_affecte",)
|
||||
localized_fields = ('montant_affecte',)
|
||||
|
|
|
@ -42,13 +42,13 @@ from . import facturx, fields, taggit, validators
|
|||
|
||||
User = get_user_model()
|
||||
|
||||
validate_telephone = RegexValidator(r"[. 0-9]*")
|
||||
validate_telephone = RegexValidator(r'[. 0-9]*')
|
||||
|
||||
DEFAULT_TVA = getattr(settings, "TVA", "20")
|
||||
DEFAULT_TVA = getattr(settings, 'TVA', '20')
|
||||
|
||||
|
||||
def accounting_rounding(amount):
|
||||
return amount.quantize(Decimal("0.01"), ROUND_HALF_UP)
|
||||
return amount.quantize(Decimal('0.01'), ROUND_HALF_UP)
|
||||
|
||||
|
||||
def today():
|
||||
|
@ -122,11 +122,11 @@ class Client(models.Model):
|
|||
|
||||
|
||||
def one_hundred_percent_this_year():
|
||||
return "%s:100" % now().date().year
|
||||
return '%s:100' % now().date().year
|
||||
|
||||
|
||||
class Contrat(models.Model):
|
||||
client = models.ForeignKey(Client, related_name="contrats", on_delete=models.CASCADE, null=True)
|
||||
client = models.ForeignKey(Client, related_name='contrats', on_delete=models.CASCADE, null=True)
|
||||
intitule = models.CharField(max_length=150)
|
||||
description = models.TextField(blank=True)
|
||||
public_description = models.TextField(
|
||||
|
@ -372,7 +372,7 @@ class Prestation(models.Model):
|
|||
ordering = ('contrat', 'id')
|
||||
|
||||
|
||||
DELAI_PAIEMENT = getattr(settings, "DELAI_PAIEMENT", 45)
|
||||
DELAI_PAIEMENT = getattr(settings, 'DELAI_PAIEMENT', 45)
|
||||
|
||||
|
||||
def today_plus_delai():
|
||||
|
@ -416,7 +416,7 @@ class Facture(models.Model):
|
|||
)
|
||||
intitule = models.CharField(max_length=150, verbose_name='Intitulé', blank=True)
|
||||
notes = models.TextField(blank=True)
|
||||
emission = models.DateField(verbose_name="Émission", default=today, db_index=True)
|
||||
emission = models.DateField(verbose_name='Émission', default=today, db_index=True)
|
||||
echeance = models.DateField(verbose_name=echeance_verbose_name, default=today_plus_delai)
|
||||
taux_tva = models.DecimalField(
|
||||
max_digits=4, decimal_places=2, default=Decimal(DEFAULT_TVA), blank=True, null=True
|
||||
|
@ -426,7 +426,7 @@ class Facture(models.Model):
|
|||
verbose_name='Montant sous-traité',
|
||||
help_text='indiquer une somme pas un pourcentage, hors-taxe',
|
||||
)
|
||||
paid = models.BooleanField(blank=True, verbose_name="Soldée", default=False, db_index=True)
|
||||
paid = models.BooleanField(blank=True, verbose_name='Soldée', default=False, db_index=True)
|
||||
creator = models.ForeignKey(User, verbose_name='Créateur', on_delete=models.CASCADE)
|
||||
account_on_previous_period = models.BooleanField(
|
||||
verbose_name='Mettre cette facture sur l\'exercice précédent', default=False
|
||||
|
@ -459,9 +459,9 @@ class Facture(models.Model):
|
|||
ctx = {}
|
||||
ctx.update(self.__dict__)
|
||||
ctx.update({'year': self.emission.year})
|
||||
if ctx["ordre"] is None:
|
||||
return "Ordre is missing"
|
||||
format = getattr(settings, "FACTURE_CODE_FORMAT", "F%(year)s%(ordre)04d")
|
||||
if ctx['ordre'] is None:
|
||||
return 'Ordre is missing'
|
||||
format = getattr(settings, 'FACTURE_CODE_FORMAT', 'F%(year)s%(ordre)04d')
|
||||
return format % ctx
|
||||
|
||||
@property
|
||||
|
@ -478,13 +478,13 @@ class Facture(models.Model):
|
|||
|
||||
def clean(self):
|
||||
if not (self.contrat or self.client):
|
||||
raise ValidationError("La facture doit avoir un client ou un contrat")
|
||||
raise ValidationError('La facture doit avoir un client ou un contrat')
|
||||
if self.contrat:
|
||||
if not self.intitule:
|
||||
self.intitule = self.contrat.intitule
|
||||
if self.client:
|
||||
if self.client != self.contrat.client and self.contrat.client is not None:
|
||||
raise ValidationError("Le client de la facture et du contrat doivent être identiques.")
|
||||
raise ValidationError('Le client de la facture et du contrat doivent être identiques.')
|
||||
else:
|
||||
self.client = self.contrat.client
|
||||
if self.contrat.periodicite and not self.annulation:
|
||||
|
@ -506,7 +506,7 @@ class Facture(models.Model):
|
|||
)
|
||||
else:
|
||||
if not self.intitule:
|
||||
raise ValidationError("La facture doit avoir un intitulé")
|
||||
raise ValidationError('La facture doit avoir un intitulé')
|
||||
if self.numero_d_echeance is not None:
|
||||
raise ValidationError(
|
||||
'Un numéro d\'échéance ne peut être défini que pour un contrat récurrent.'
|
||||
|
@ -516,7 +516,7 @@ class Facture(models.Model):
|
|||
for ligne in self.lignes.all():
|
||||
ligne.clean()
|
||||
except ValidationError:
|
||||
raise ValidationError("Il y a un problème avec les lignes de cette facture")
|
||||
raise ValidationError('Il y a un problème avec les lignes de cette facture')
|
||||
self.update_paid(save=False)
|
||||
self.numero_engagement = self.numero_engagement.strip()
|
||||
if (
|
||||
|
@ -544,7 +544,7 @@ class Facture(models.Model):
|
|||
amount_by_vat[ligne.tva] += ligne.montant
|
||||
vat = Decimal(0)
|
||||
for vat_percentage, amount in amount_by_vat.items():
|
||||
var_ratio = vat_percentage / Decimal("100")
|
||||
var_ratio = vat_percentage / Decimal('100')
|
||||
vat += accounting_rounding(var_ratio * amount)
|
||||
return vat
|
||||
|
||||
|
@ -627,7 +627,7 @@ class Facture(models.Model):
|
|||
facture_avoir.ordre = None
|
||||
facture_avoir.annulation = self
|
||||
facture_avoir.proforma = True
|
||||
facture_avoir.intitule = "AVOIR POUR LA FACTURE " + self.intitule
|
||||
facture_avoir.intitule = 'AVOIR POUR LA FACTURE ' + self.intitule
|
||||
facture_avoir.paid = False
|
||||
facture_avoir.creator = creator
|
||||
facture_avoir.account_on_previous_period = False
|
||||
|
@ -679,14 +679,14 @@ class Facture(models.Model):
|
|||
periode = property(periode)
|
||||
|
||||
class Meta:
|
||||
ordering = ("-id",)
|
||||
ordering = ('-id',)
|
||||
unique_together = [
|
||||
('contrat', 'numero_d_echeance'),
|
||||
]
|
||||
|
||||
|
||||
class Ligne(models.Model):
|
||||
facture = models.ForeignKey(Facture, related_name="lignes", on_delete=models.CASCADE)
|
||||
facture = models.ForeignKey(Facture, related_name='lignes', on_delete=models.CASCADE)
|
||||
intitule = models.TextField(blank=True)
|
||||
prix_unitaire_ht = models.DecimalField(max_digits=8, decimal_places=2, default=Decimal('0'))
|
||||
quantite = models.DecimalField(max_digits=8, decimal_places=3, default=Decimal('1.0'))
|
||||
|
@ -711,9 +711,9 @@ class Ligne(models.Model):
|
|||
def clean(self):
|
||||
errors = []
|
||||
if self.taux_tva and self.taux_tva < 0:
|
||||
errors.append("Le taux de tva doit être une valeur positive ou nulle.")
|
||||
errors.append('Le taux de tva doit être une valeur positive ou nulle.')
|
||||
if self.prix_unitaire_ht < 0:
|
||||
errors.append("Le prix unitaire hors taxe doit être une valeur positive ou nulle.")
|
||||
errors.append('Le prix unitaire hors taxe doit être une valeur positive ou nulle.')
|
||||
if self.facture.contrat and not self.facture.proforma:
|
||||
facture = self.facture
|
||||
contrat = facture.contrat
|
||||
|
@ -728,17 +728,17 @@ class Ligne(models.Model):
|
|||
raise ValidationError(errors)
|
||||
|
||||
class Meta:
|
||||
ordering = ("order",)
|
||||
ordering = ('order',)
|
||||
|
||||
def __str__(self):
|
||||
if self.facture.client:
|
||||
return "%s pour %s %s" % (
|
||||
return '%s pour %s %s' % (
|
||||
self.intitule,
|
||||
self.montant,
|
||||
self.facture.client.monnaie,
|
||||
)
|
||||
else:
|
||||
return "%s pour %s €" % (self.intitule, self.montant)
|
||||
return '%s pour %s €' % (self.intitule, self.montant)
|
||||
|
||||
|
||||
def encaissements_avec_solde_non_affecte():
|
||||
|
@ -775,7 +775,7 @@ class Payment(models.Model):
|
|||
self.montant_affecte = min(self.ligne_banque_pop.montant, self.facture.montant_ttc)
|
||||
except (banque_models.LigneBanquePop.DoesNotExist, Facture.DoesNotExist):
|
||||
pass
|
||||
aggregate = models.Sum("montant_affecte")
|
||||
aggregate = models.Sum('montant_affecte')
|
||||
# from the ligne de banque pov
|
||||
try:
|
||||
other_payments = self.ligne_banque_pop.payments
|
||||
|
@ -784,7 +784,7 @@ class Payment(models.Model):
|
|||
except banque_models.LigneBanquePop.DoesNotExist:
|
||||
pass
|
||||
else:
|
||||
deja_affecte = other_payments.aggregate(aggregate).get("montant_affecte", 0)
|
||||
deja_affecte = other_payments.aggregate(aggregate).get('montant_affecte', 0)
|
||||
if deja_affecte + self.montant_affecte > self.ligne_banque_pop.montant:
|
||||
raise ValidationError(
|
||||
'Le montant affecté aux différentes factures '
|
||||
|
@ -796,7 +796,7 @@ class Payment(models.Model):
|
|||
except Facture.DoesNotExist:
|
||||
pass
|
||||
else:
|
||||
deja_affecte = other_payments.aggregate(aggregate).get("montant_affecte") or 0
|
||||
deja_affecte = other_payments.aggregate(aggregate).get('montant_affecte') or 0
|
||||
if (
|
||||
self.montant_affecte is not None
|
||||
and deja_affecte + self.montant_affecte > self.facture.montant_ttc
|
||||
|
|
|
@ -156,17 +156,17 @@ class StringWithHref(str):
|
|||
def client_and_link(c):
|
||||
if c is not None:
|
||||
s = str(c)
|
||||
url = reverse("admin:eo_facture_client_change", args=(c.id,))
|
||||
url = reverse('admin:eo_facture_client_change', args=(c.id,))
|
||||
return StringWithHref(s, url)
|
||||
else:
|
||||
return ""
|
||||
return ''
|
||||
|
||||
|
||||
def dict_of_list():
|
||||
return defaultdict(lambda: [])
|
||||
|
||||
|
||||
@register.inclusion_tag("eo_facture/table.html")
|
||||
@register.inclusion_tag('eo_facture/table.html')
|
||||
@cache
|
||||
def income_by_clients(year=None):
|
||||
if not year:
|
||||
|
@ -218,7 +218,7 @@ def income_by_clients(year=None):
|
|||
pareto[client] = running_total
|
||||
return dict(
|
||||
title="Chiffre d'affaire prévisionnel par client pour %s" % year,
|
||||
name="previsional-income-by-client-%s" % year,
|
||||
name='previsional-income-by-client-%s' % year,
|
||||
headers=[
|
||||
('client', 'Client'),
|
||||
('income', 'Chiffre d\'affaire'),
|
||||
|
@ -291,12 +291,12 @@ def a_facturer():
|
|||
def ago(date):
|
||||
ago = timesince(date)
|
||||
# selects only the first part of the returned string
|
||||
return ago.split(",")[0]
|
||||
return ago.split(',')[0]
|
||||
|
||||
|
||||
@register.filter(is_safe=True)
|
||||
def amountformat(value, use_l10n=True):
|
||||
return number_format(Decimal(value).quantize(Decimal("0.01")), force_grouping=True)
|
||||
return number_format(Decimal(value).quantize(Decimal('0.01')), force_grouping=True)
|
||||
|
||||
|
||||
# invalidate impayees() cache when Payment set changes
|
||||
|
|
|
@ -22,13 +22,13 @@ from datetime import date, datetime
|
|||
from django.utils.encoding import force_text
|
||||
|
||||
NS = {
|
||||
"fo": "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",
|
||||
"office": "urn:oasis:names:tc:opendocument:xmlns:office:1.0",
|
||||
"style": "urn:oasis:names:tc:opendocument:xmlns:style:1.0",
|
||||
"number": "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0",
|
||||
"table": "urn:oasis:names:tc:opendocument:xmlns:table:1.0",
|
||||
"text": "urn:oasis:names:tc:opendocument:xmlns:text:1.0",
|
||||
"xlink": "http://www.w3.org/1999/xlink",
|
||||
'fo': 'urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0',
|
||||
'office': 'urn:oasis:names:tc:opendocument:xmlns:office:1.0',
|
||||
'style': 'urn:oasis:names:tc:opendocument:xmlns:style:1.0',
|
||||
'number': 'urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0',
|
||||
'table': 'urn:oasis:names:tc:opendocument:xmlns:table:1.0',
|
||||
'text': 'urn:oasis:names:tc:opendocument:xmlns:text:1.0',
|
||||
'xlink': 'http://www.w3.org/1999/xlink',
|
||||
}
|
||||
|
||||
for prefix, uri in NS.items():
|
||||
|
@ -36,7 +36,7 @@ for prefix, uri in NS.items():
|
|||
|
||||
|
||||
def is_number(value):
|
||||
if isinstance(value, str) and (value.startswith("0") or value.startswith("+")):
|
||||
if isinstance(value, str) and (value.startswith('0') or value.startswith('+')):
|
||||
return False
|
||||
try:
|
||||
float(value)
|
||||
|
@ -55,96 +55,96 @@ class Workbook:
|
|||
return sheet
|
||||
|
||||
def get_content_node(self):
|
||||
root = ET.Element("{%s}document-content" % NS["office"])
|
||||
ET.SubElement(root, "{%s}scripts" % NS["office"])
|
||||
ET.SubElement(root, "{%s}font-face-decls" % NS["office"])
|
||||
root = ET.Element('{%s}document-content' % NS['office'])
|
||||
ET.SubElement(root, '{%s}scripts' % NS['office'])
|
||||
ET.SubElement(root, '{%s}font-face-decls' % NS['office'])
|
||||
|
||||
body = ET.SubElement(root, "{%s}body" % NS["office"])
|
||||
spreadsheet = ET.SubElement(body, "{%s}spreadsheet" % NS["office"])
|
||||
body = ET.SubElement(root, '{%s}body' % NS['office'])
|
||||
spreadsheet = ET.SubElement(body, '{%s}spreadsheet' % NS['office'])
|
||||
for sheet in self.sheets:
|
||||
spreadsheet.append(sheet.get_node())
|
||||
return root
|
||||
|
||||
def get_styles_node(self):
|
||||
root = ET.Element("{%s}document-styles" % NS["office"])
|
||||
ET.SubElement(root, "{%s}font-face-decls" % NS["office"])
|
||||
automatic_styles = ET.SubElement(root, "{%s}styles" % NS["office"])
|
||||
style = ET.SubElement(automatic_styles, "{%s}style" % NS["style"])
|
||||
style.attrib["{%s}name" % NS["style"]] = "Default"
|
||||
root = ET.Element('{%s}document-styles' % NS['office'])
|
||||
ET.SubElement(root, '{%s}font-face-decls' % NS['office'])
|
||||
automatic_styles = ET.SubElement(root, '{%s}styles' % NS['office'])
|
||||
style = ET.SubElement(automatic_styles, '{%s}style' % NS['style'])
|
||||
style.attrib['{%s}name' % NS['style']] = 'Default'
|
||||
|
||||
def define_number_style():
|
||||
node = ET.SubElement(automatic_styles, '{%s}number-style' % NS['number'])
|
||||
node.attrib["{%s}name" % NS["style"]] = "NumberFormat"
|
||||
node.attrib['{%s}name' % NS['style']] = 'NumberFormat'
|
||||
sub_node = ET.SubElement(node, '{%s}number' % NS['number'])
|
||||
sub_node.attrib['{%s}decimal-places' % NS['number']] = '2'
|
||||
sub_node.attrib['{%s}min-decimal-places' % NS['number']] = '2'
|
||||
sub_node.attrib['{%s}min-integer-digits' % NS['number']] = '1'
|
||||
sub_node.attrib['{%s}grouping' % NS['number']] = 'true'
|
||||
style = ET.SubElement(automatic_styles, "{%s}style" % NS["style"])
|
||||
style.attrib["{%s}name" % NS["style"]] = 'Number'
|
||||
style.attrib["{%s}family" % NS["style"]] = "table-cell"
|
||||
style.attrib["{%s}data-style-name" % NS["style"]] = "NumberFormat"
|
||||
style.attrib["{%s}parent-style" % NS["style"]] = "Default"
|
||||
style = ET.SubElement(automatic_styles, '{%s}style' % NS['style'])
|
||||
style.attrib['{%s}name' % NS['style']] = 'Number'
|
||||
style.attrib['{%s}family' % NS['style']] = 'table-cell'
|
||||
style.attrib['{%s}data-style-name' % NS['style']] = 'NumberFormat'
|
||||
style.attrib['{%s}parent-style' % NS['style']] = 'Default'
|
||||
|
||||
define_number_style()
|
||||
|
||||
def define_date_style(name, strftime_string):
|
||||
node = ET.SubElement(automatic_styles, "{%s}date-style" % NS["number"])
|
||||
node.attrib["{%s}name" % NS["style"]] = name + "NumberFormat"
|
||||
for part in re.findall(r"%?.", strftime_string):
|
||||
if part == "%Y":
|
||||
ET.SubElement(node, "{%s}year" % NS["number"]).attrib["{%s}style" % NS["number"]] = "long"
|
||||
elif part == "%m":
|
||||
ET.SubElement(node, "{%s}month" % NS["number"]).attrib[
|
||||
"{%s}style" % NS["number"]
|
||||
] = "long"
|
||||
elif part == "%d":
|
||||
ET.SubElement(node, "{%s}day" % NS["number"]).attrib["{%s}style" % NS["number"]] = "long"
|
||||
elif part == "%H":
|
||||
ET.SubElement(node, "{%s}hours" % NS["number"]).attrib[
|
||||
"{%s}style" % NS["number"]
|
||||
] = "long"
|
||||
elif part == "%M":
|
||||
ET.SubElement(node, "{%s}minutes" % NS["number"]).attrib[
|
||||
"{%s}style" % NS["number"]
|
||||
] = "long"
|
||||
elif part == "%S":
|
||||
ET.SubElement(node, "{%s}seconds" % NS["number"]).attrib[
|
||||
"{%s}style" % NS["number"]
|
||||
] = "long"
|
||||
node = ET.SubElement(automatic_styles, '{%s}date-style' % NS['number'])
|
||||
node.attrib['{%s}name' % NS['style']] = name + 'NumberFormat'
|
||||
for part in re.findall(r'%?.', strftime_string):
|
||||
if part == '%Y':
|
||||
ET.SubElement(node, '{%s}year' % NS['number']).attrib['{%s}style' % NS['number']] = 'long'
|
||||
elif part == '%m':
|
||||
ET.SubElement(node, '{%s}month' % NS['number']).attrib[
|
||||
'{%s}style' % NS['number']
|
||||
] = 'long'
|
||||
elif part == '%d':
|
||||
ET.SubElement(node, '{%s}day' % NS['number']).attrib['{%s}style' % NS['number']] = 'long'
|
||||
elif part == '%H':
|
||||
ET.SubElement(node, '{%s}hours' % NS['number']).attrib[
|
||||
'{%s}style' % NS['number']
|
||||
] = 'long'
|
||||
elif part == '%M':
|
||||
ET.SubElement(node, '{%s}minutes' % NS['number']).attrib[
|
||||
'{%s}style' % NS['number']
|
||||
] = 'long'
|
||||
elif part == '%S':
|
||||
ET.SubElement(node, '{%s}seconds' % NS['number']).attrib[
|
||||
'{%s}style' % NS['number']
|
||||
] = 'long'
|
||||
else:
|
||||
ET.SubElement(node, "{%s}text" % NS["number"]).text = part
|
||||
style = ET.SubElement(automatic_styles, "{%s}style" % NS["style"])
|
||||
style.attrib["{%s}name" % NS["style"]] = name
|
||||
style.attrib["{%s}family" % NS["style"]] = "table-cell"
|
||||
style.attrib["{%s}data-style-name" % NS["style"]] = name + "NumberFormat"
|
||||
style.attrib["{%s}parent-style" % NS["style"]] = "Default"
|
||||
ET.SubElement(node, '{%s}text' % NS['number']).text = part
|
||||
style = ET.SubElement(automatic_styles, '{%s}style' % NS['style'])
|
||||
style.attrib['{%s}name' % NS['style']] = name
|
||||
style.attrib['{%s}family' % NS['style']] = 'table-cell'
|
||||
style.attrib['{%s}data-style-name' % NS['style']] = name + 'NumberFormat'
|
||||
style.attrib['{%s}parent-style' % NS['style']] = 'Default'
|
||||
|
||||
style = ET.SubElement(automatic_styles, "{%s}style" % NS["style"])
|
||||
style.attrib["{%s}name" % NS["style"]] = name + "Column"
|
||||
style.attrib["{%s}family" % NS["style"]] = "table-column"
|
||||
ET.SubElement(style, "{%s}table-column-properties" % NS["style"]).attrib[
|
||||
"{%s}column-width" % NS["style"]
|
||||
] = "80mm"
|
||||
style = ET.SubElement(automatic_styles, '{%s}style' % NS['style'])
|
||||
style.attrib['{%s}name' % NS['style']] = name + 'Column'
|
||||
style.attrib['{%s}family' % NS['style']] = 'table-column'
|
||||
ET.SubElement(style, '{%s}table-column-properties' % NS['style']).attrib[
|
||||
'{%s}column-width' % NS['style']
|
||||
] = '80mm'
|
||||
|
||||
define_date_style("Date", '%d/%m/%Y')
|
||||
define_date_style("DateTime", '%d/%m/%Y %H:%M')
|
||||
define_date_style('Date', '%d/%m/%Y')
|
||||
define_date_style('DateTime', '%d/%m/%Y %H:%M')
|
||||
|
||||
return root
|
||||
|
||||
def get_styles(self):
|
||||
return ET.tostring(self.get_styles_node(), "utf-8")
|
||||
return ET.tostring(self.get_styles_node(), 'utf-8')
|
||||
|
||||
def get_content(self):
|
||||
return ET.tostring(self.get_content_node(), "utf-8")
|
||||
return ET.tostring(self.get_content_node(), 'utf-8')
|
||||
|
||||
def save(self, output):
|
||||
with zipfile.ZipFile(output, "w") as z:
|
||||
z.writestr("content.xml", self.get_content())
|
||||
z.writestr("styles.xml", self.get_styles())
|
||||
z.writestr("mimetype", "application/vnd.oasis.opendocument.spreadsheet")
|
||||
with zipfile.ZipFile(output, 'w') as z:
|
||||
z.writestr('content.xml', self.get_content())
|
||||
z.writestr('styles.xml', self.get_styles())
|
||||
z.writestr('mimetype', 'application/vnd.oasis.opendocument.spreadsheet')
|
||||
z.writestr(
|
||||
"META-INF/manifest.xml",
|
||||
'META-INF/manifest.xml',
|
||||
"""<?xml version="1.0" encoding="UTF-8"?>
|
||||
<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0">
|
||||
<manifest:file-entry manifest:full-path="/" manifest:media-type="application/vnd.oasis.opendocument.spreadsheet"/>
|
||||
|
@ -168,15 +168,15 @@ class WorkSheet:
|
|||
self.cells[row][column] = WorkCell(self, value, **kwargs)
|
||||
|
||||
def get_node(self):
|
||||
root = ET.Element("{%s}table" % NS["table"])
|
||||
root.attrib["{%s}name" % NS["table"]] = self.name
|
||||
ET.SubElement(root, "{%s}table-column" % NS["table"])
|
||||
root = ET.Element('{%s}table' % NS['table'])
|
||||
root.attrib['{%s}name' % NS['table']] = self.name
|
||||
ET.SubElement(root, '{%s}table-column' % NS['table'])
|
||||
for i in range(0, max(self.cells.keys()) + 1):
|
||||
row = ET.SubElement(root, "{%s}table-row" % NS["table"])
|
||||
row = ET.SubElement(root, '{%s}table-row' % NS['table'])
|
||||
for j in range(0, max(self.cells.get(i).keys()) + 1):
|
||||
cell = self.cells.get(i, {}).get(j, None)
|
||||
if not cell:
|
||||
ET.SubElement(row, "{%s}table-cell" % NS["table"])
|
||||
ET.SubElement(row, '{%s}table-cell' % NS['table'])
|
||||
else:
|
||||
row.append(cell.get_node())
|
||||
return root
|
||||
|
@ -185,39 +185,39 @@ class WorkSheet:
|
|||
class WorkCell:
|
||||
def __init__(self, worksheet, value):
|
||||
if value is None:
|
||||
value = ""
|
||||
value = ''
|
||||
self.worksheet = worksheet
|
||||
self.native_value = value
|
||||
value = force_text(value)
|
||||
for i in range(0x20): # remove control characters
|
||||
char = chr(i)
|
||||
if char in ("\t", "\r", "\n"):
|
||||
if char in ('\t', '\r', '\n'):
|
||||
# only allow tab, carriage return and line feed.
|
||||
continue
|
||||
value = value.replace(char, "")
|
||||
value = value.replace(char, '')
|
||||
# fffe and ffff are also invalid characters
|
||||
value = value.replace("\ufffe", "").replace("\uffff", "")
|
||||
value = value.replace('\ufffe', '').replace('\uffff', '')
|
||||
self.value = value
|
||||
|
||||
def get_node(self):
|
||||
root = ET.Element("{%s}table-cell" % NS["table"])
|
||||
p = ET.SubElement(root, "{%s}p" % NS["text"])
|
||||
root = ET.Element('{%s}table-cell' % NS['table'])
|
||||
p = ET.SubElement(root, '{%s}p' % NS['text'])
|
||||
p.text = self.value
|
||||
value = self.native_value
|
||||
if is_number(value):
|
||||
root.attrib["{%s}value-type" % NS["office"]] = "float"
|
||||
root.attrib["{%s}value" % NS["office"]] = self.value
|
||||
root.attrib["{%s}style-name" % NS["table"]] = "Number"
|
||||
root.attrib['{%s}value-type' % NS['office']] = 'float'
|
||||
root.attrib['{%s}value' % NS['office']] = self.value
|
||||
root.attrib['{%s}style-name' % NS['table']] = 'Number'
|
||||
elif isinstance(value, datetime):
|
||||
root.attrib["{%s}style-name" % NS["table"]] = "DateTime"
|
||||
root.attrib["{%s}value-type" % NS["office"]] = "date"
|
||||
root.attrib["{%s}date-value" % NS["office"]] = value.strftime("%Y-%m-%dT%H:%M:%S")
|
||||
p.text = value.strftime("%d/%m/%Y %H:%M:%S")
|
||||
root.attrib['{%s}style-name' % NS['table']] = 'DateTime'
|
||||
root.attrib['{%s}value-type' % NS['office']] = 'date'
|
||||
root.attrib['{%s}date-value' % NS['office']] = value.strftime('%Y-%m-%dT%H:%M:%S')
|
||||
p.text = value.strftime('%d/%m/%Y %H:%M:%S')
|
||||
elif isinstance(value, date):
|
||||
root.attrib["{%s}style-name" % NS["table"]] = "Date"
|
||||
root.attrib["{%s}value-type" % NS["office"]] = "date"
|
||||
root.attrib["{%s}date-value" % NS["office"]] = value.strftime("%Y-%m-%d")
|
||||
p.text = value.strftime("%d/%m/%Y")
|
||||
root.attrib['{%s}style-name' % NS['table']] = 'Date'
|
||||
root.attrib['{%s}value-type' % NS['office']] = 'date'
|
||||
root.attrib['{%s}date-value' % NS['office']] = value.strftime('%Y-%m-%d')
|
||||
p.text = value.strftime('%d/%m/%Y')
|
||||
else:
|
||||
root.attrib["{%s}value-type" % NS["office"]] = "string"
|
||||
root.attrib['{%s}value-type' % NS['office']] = 'string'
|
||||
return root
|
||||
|
|
|
@ -86,11 +86,11 @@ LOGGING = {
|
|||
# timezone as the operating system.
|
||||
# If running in a Windows environment this must be set to the same as your
|
||||
# system time zone.
|
||||
TIME_ZONE = "Europe/Paris"
|
||||
TIME_ZONE = 'Europe/Paris'
|
||||
|
||||
# Language code for this installation. All choices can be found here:
|
||||
# http://www.i18nguy.com/unicode/language-identifiers.html
|
||||
LANGUAGE_CODE = "fr-fr"
|
||||
LANGUAGE_CODE = 'fr-fr'
|
||||
|
||||
SITE_ID = 1
|
||||
|
||||
|
@ -110,28 +110,28 @@ LOCALE_PATHS = (os.path.join(BASE_DIR, 'eo_gestion', 'locale'),)
|
|||
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
|
||||
# trailing slash if there is a path component (optional in other cases).
|
||||
# Examples: "http://media.lawrence.com", "http://example.com/media/"
|
||||
MEDIA_URL = "/media/"
|
||||
MEDIA_URL = '/media/'
|
||||
|
||||
# URL prefix for static files.
|
||||
# Example: "http://media.lawrence.com/static/"
|
||||
STATIC_URL = "/static/"
|
||||
STATIC_URL = '/static/'
|
||||
STATICFILES_FINDERS = list(global_settings.STATICFILES_FINDERS) + ['gadjo.finders.XStaticFinder']
|
||||
|
||||
|
||||
# Make this unique, and don't share it with anybody.
|
||||
SECRET_KEY = "5w+ifr2ho!#x06q7dshr08wd#gt0wwp@wvbvw33kmtb+x$(9ts"
|
||||
SECRET_KEY = '5w+ifr2ho!#x06q7dshr08wd#gt0wwp@wvbvw33kmtb+x$(9ts'
|
||||
|
||||
MIDDLEWARE = (
|
||||
"django.middleware.common.CommonMiddleware",
|
||||
"django.middleware.http.ConditionalGetMiddleware",
|
||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||
"django.middleware.csrf.CsrfViewMiddleware",
|
||||
"django.middleware.locale.LocaleMiddleware",
|
||||
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||
"django.contrib.messages.middleware.MessageMiddleware",
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.http.ConditionalGetMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.middleware.locale.LocaleMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
)
|
||||
|
||||
ROOT_URLCONF = "eo_gestion.urls"
|
||||
ROOT_URLCONF = 'eo_gestion.urls'
|
||||
|
||||
# Templates
|
||||
TEMPLATES = [
|
||||
|
@ -157,17 +157,17 @@ TEMPLATES = [
|
|||
]
|
||||
|
||||
INSTALLED_APPS = (
|
||||
"django.contrib.auth",
|
||||
"django.contrib.contenttypes",
|
||||
"django.contrib.sessions",
|
||||
"django.contrib.sites",
|
||||
"django.contrib.messages",
|
||||
"django.contrib.staticfiles",
|
||||
"django.contrib.humanize",
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.sites',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'django.contrib.humanize',
|
||||
# Uncomment the next line to enable the admin:
|
||||
"django.contrib.admin",
|
||||
"eo_gestion.eo_facture",
|
||||
"eo_gestion.eo_banque",
|
||||
'django.contrib.admin',
|
||||
'eo_gestion.eo_facture',
|
||||
'eo_gestion.eo_banque',
|
||||
'eo_gestion.eo_conges',
|
||||
'eo_gestion.chorus',
|
||||
'taggit',
|
||||
|
@ -180,7 +180,7 @@ AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend',)
|
|||
|
||||
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
|
||||
|
||||
LOGIN_REDIRECT_URL = "/"
|
||||
LOGIN_REDIRECT_URL = '/'
|
||||
|
||||
# timeout used in python-requests call, in seconds
|
||||
# timeout just after web server, which is usually 30s,
|
||||
|
@ -207,7 +207,7 @@ WORKERS_CALENDAR_CONFIG = {
|
|||
],
|
||||
}
|
||||
|
||||
local_settings_file = os.environ.get("BARBACOMPTA_SETTINGS_FILE", "local_settings.py")
|
||||
local_settings_file = os.environ.get('BARBACOMPTA_SETTINGS_FILE', 'local_settings.py')
|
||||
if os.path.exists(local_settings_file):
|
||||
with open(local_settings_file) as fd:
|
||||
exec(fd.read())
|
||||
|
|
|
@ -162,7 +162,7 @@ class SortableAdminMixin(SortableAdminBase):
|
|||
first_order_direction, first_order_field_index = self._get_first_ordering(request)
|
||||
if first_order_field_index == self.default_order_field_index:
|
||||
self.enable_sorting = True
|
||||
self.order_by = f"{first_order_direction}{self.default_order_field}"
|
||||
self.order_by = f'{first_order_direction}{self.default_order_field}'
|
||||
else:
|
||||
self.enable_sorting = False
|
||||
return super().get_changelist(request, **kwargs)
|
||||
|
@ -178,9 +178,9 @@ class SortableAdminMixin(SortableAdminBase):
|
|||
first_order_direction = self.default_order_direction
|
||||
else:
|
||||
first_order_field_index = None
|
||||
first_order_direction = ""
|
||||
for p in order_var.split("."):
|
||||
none, prefix, index = p.rpartition("-")
|
||||
first_order_direction = ''
|
||||
for p in order_var.split('.'):
|
||||
none, prefix, index = p.rpartition('-')
|
||||
try:
|
||||
index = int(index)
|
||||
except ValueError:
|
||||
|
@ -316,8 +316,8 @@ class SortableAdminMixin(SortableAdminBase):
|
|||
# noinspection PyProtectedMember
|
||||
raise model.MultipleObjectsReturned(
|
||||
"Detected non-unique values in field '{rank_field}' used for sorting this model.\n"
|
||||
"Consider to run \n python manage.py reorder {model._meta.label}\n"
|
||||
"to adjust this inconsistency."
|
||||
'Consider to run \n python manage.py reorder {model._meta.label}\n'
|
||||
'to adjust this inconsistency.'
|
||||
)
|
||||
|
||||
move_qs = model.objects.filter(**move_filter).order_by(order_by)
|
||||
|
@ -398,7 +398,7 @@ class SortableAdminMixin(SortableAdminBase):
|
|||
queryset_size = queryset.count()
|
||||
page_size = page.end_index() - page.start_index() + 1
|
||||
if queryset_size > page_size:
|
||||
msg = _(f"The target page size is {page_size}. It is too small for {queryset_size} items.")
|
||||
msg = _(f'The target page size is {page_size}. It is too small for {queryset_size} items.')
|
||||
self.message_user(request, msg, level=messages.ERROR)
|
||||
return
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
import os
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "eo_gestion.settings")
|
||||
if __name__ == '__main__':
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'eo_gestion.settings')
|
||||
|
||||
from django.core.management import execute_from_command_line
|
||||
|
||||
|
|
|
@ -29,11 +29,11 @@ def test_references(app):
|
|||
if i % 3 == 1:
|
||||
contract.tags.add(gi)
|
||||
|
||||
response = app.get("/api/references/")
|
||||
response = app.get('/api/references/')
|
||||
assert any(row['tags'] for row in response.json['data'])
|
||||
response_gru = app.get("/api/references/", params={'tags': 'GRU'})
|
||||
response_gru = app.get('/api/references/', params={'tags': 'GRU'})
|
||||
assert len(response_gru.json['data']) == 12
|
||||
response_gi = app.get("/api/references/", params={'tags': 'Gestion d\'identité'})
|
||||
response_gi = app.get('/api/references/', params={'tags': 'Gestion d\'identité'})
|
||||
assert len(response_gi.json['data']) == 18
|
||||
response_gru_and_gi = app.get("/api/references/", params={'tags': ['GRU', 'Gestion d\'identité']})
|
||||
response_gru_and_gi = app.get('/api/references/', params={'tags': ['GRU', 'Gestion d\'identité']})
|
||||
assert len(response_gru_and_gi.json['data']) == 30
|
||||
|
|
|
@ -19,27 +19,27 @@ import pytest
|
|||
|
||||
@pytest.fixture
|
||||
def homepage(app):
|
||||
response = app.get("/").follow()
|
||||
response = app.get('/').follow()
|
||||
|
||||
response.form.set("username", "admin")
|
||||
response.form.set("password", "admin")
|
||||
response.form.set('username', 'admin')
|
||||
response.form.set('password', 'admin')
|
||||
|
||||
return response.form.submit().follow()
|
||||
|
||||
|
||||
def test_misc(homepage):
|
||||
clients = homepage.click("Clients")
|
||||
clients = homepage.click('Clients')
|
||||
str(clients)
|
||||
ajouter_un_client = homepage.click("Ajouter un client")
|
||||
ajouter_un_client = homepage.click('Ajouter un client')
|
||||
str(ajouter_un_client)
|
||||
contrats = homepage.click("Contrats")
|
||||
contrats = homepage.click('Contrats')
|
||||
contrat_2c210afd24c11596eeaf94bfb = contrats.click('2c210afd24c11596eeaf94bfb', href='change')
|
||||
str(contrat_2c210afd24c11596eeaf94bfb)
|
||||
ajouter_un_contrat = homepage.click("Ajouter un contrat")
|
||||
ajouter_un_contrat = homepage.click('Ajouter un contrat')
|
||||
str(ajouter_un_contrat)
|
||||
compte_en_banque = homepage.click("Compte en banque")
|
||||
compte_en_banque = homepage.click('Compte en banque')
|
||||
str(compte_en_banque)
|
||||
factures = homepage.click("Factures")
|
||||
factures = homepage.click('Factures')
|
||||
factures_00137 = factures.click('F20190137')
|
||||
str(factures_00137)
|
||||
rapid = factures.click('Rapid')
|
||||
|
@ -47,10 +47,10 @@ def test_misc(homepage):
|
|||
|
||||
|
||||
def test_ods_export(app):
|
||||
response = app.get("/eo_facture/facture/").follow()
|
||||
response = app.get('/eo_facture/facture/').follow()
|
||||
|
||||
response.form.set("username", "admin")
|
||||
response.form.set("password", "admin")
|
||||
response.form.set('username', 'admin')
|
||||
response.form.set('password', 'admin')
|
||||
|
||||
factures = response.form.submit().follow()
|
||||
|
||||
|
@ -59,9 +59,9 @@ def test_ods_export(app):
|
|||
|
||||
|
||||
def test_odt_export(app):
|
||||
response = app.get("/eo_facture/contrat/").follow()
|
||||
response.form.set("username", "admin")
|
||||
response.form.set("password", "admin")
|
||||
response = app.get('/eo_facture/contrat/').follow()
|
||||
response.form.set('username', 'admin')
|
||||
response.form.set('password', 'admin')
|
||||
|
||||
contracts = response.form.submit().follow()
|
||||
form = contracts.forms['changelist-form']
|
||||
|
@ -74,9 +74,9 @@ def test_odt_export(app):
|
|||
|
||||
|
||||
def test_zip_export(app):
|
||||
response = app.get("/eo_facture/facture/").follow()
|
||||
response.form.set("username", "admin")
|
||||
response.form.set("password", "admin")
|
||||
response = app.get('/eo_facture/facture/').follow()
|
||||
response.form.set('username', 'admin')
|
||||
response.form.set('password', 'admin')
|
||||
|
||||
factures = response.form.submit().follow()
|
||||
form = factures.forms['changelist-form']
|
||||
|
|
|
@ -21,30 +21,30 @@ from django.core.management import call_command
|
|||
|
||||
User = get_user_model()
|
||||
|
||||
DATA = ["tests/fixture.json"]
|
||||
DATA = ['tests/fixture.json']
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
@pytest.fixture(scope='session')
|
||||
def django_db_setup(django_db_setup, django_db_blocker, django_db_keepdb, django_db_createdb):
|
||||
with django_db_blocker.unblock():
|
||||
if not django_db_keepdb or django_db_createdb or User.objects.count() == 0:
|
||||
for data in DATA:
|
||||
call_command("loaddata", data)
|
||||
call_command('loaddata', data)
|
||||
admin, _ = User.objects.update_or_create(
|
||||
username="admin",
|
||||
defaults=dict(email="admin@example.com", is_superuser=True, is_staff=True),
|
||||
username='admin',
|
||||
defaults=dict(email='admin@example.com', is_superuser=True, is_staff=True),
|
||||
)
|
||||
admin.set_password("admin")
|
||||
admin.set_password('admin')
|
||||
admin.save()
|
||||
yield
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def app(db, freezer):
|
||||
freezer.move_to("2019-01-01")
|
||||
freezer.move_to('2019-01-01')
|
||||
wtm = django_webtest.WebTestMixin()
|
||||
wtm._patch_settings()
|
||||
try:
|
||||
return django_webtest.DjangoTestApp(extra_environ={"HTTP_HOST": "localhost"})
|
||||
return django_webtest.DjangoTestApp(extra_environ={'HTTP_HOST': 'localhost'})
|
||||
finally:
|
||||
wtm._unpatch_settings()
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
import os
|
||||
|
||||
ALLOWED_HOSTS = ["localhost"]
|
||||
ALLOWED_HOSTS = ['localhost']
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
|
|
|
@ -44,8 +44,8 @@ class TestLoggedIn:
|
|||
response.form['periodicite'] = 'annuelle'
|
||||
response.form['periodicite_debut'] = '2018-12-01'
|
||||
response = response.form.submit('_continue').follow()
|
||||
response.forms["contrat_form"]['periodicite_debut'] = '2018-12-02'
|
||||
response = response.forms["contrat_form"].submit('_continue').follow()
|
||||
response.forms['contrat_form']['periodicite_debut'] = '2018-12-02'
|
||||
response = response.forms['contrat_form'].submit('_continue').follow()
|
||||
|
||||
# Créer la facture de première échéance
|
||||
response = app.get('/')
|
||||
|
|
|
@ -135,7 +135,7 @@ def test_conges_no_match_error(mocked_get_events, app, settings):
|
|||
|
||||
login(app)
|
||||
resp = app.get('/conges/2023/01/')
|
||||
assert escape("Aucun·e coopérateurice trouvé·e pour les évènements : xxx, yyy") in resp.text
|
||||
assert escape('Aucun·e coopérateurice trouvé·e pour les évènements : xxx, yyy') in resp.text
|
||||
assert 'le 06/01' in resp.text
|
||||
|
||||
|
||||
|
|
|
@ -42,13 +42,13 @@ def test_limitations(db):
|
|||
|
||||
|
||||
def test_facture_avoir(app):
|
||||
response = app.get("/eo_facture/facture/").follow()
|
||||
response = app.get('/eo_facture/facture/').follow()
|
||||
|
||||
response.form.set("username", "admin")
|
||||
response.form.set("password", "admin")
|
||||
response.form.set('username', 'admin')
|
||||
response.form.set('password', 'admin')
|
||||
|
||||
homepage = response.form.submit().follow()
|
||||
factures_page = homepage.click("Factures")
|
||||
factures_page = homepage.click('Factures')
|
||||
|
||||
facture_0137_page = factures_page.click('F20190137')
|
||||
assert 'F20190137' in facture_0137_page.html.find('div', {'class': 'breadcrumbs'}).text
|
||||
|
@ -57,7 +57,7 @@ def test_facture_avoir(app):
|
|||
facture = [x for x in Facture.objects.all() if x.code() == 'F20190137'][0]
|
||||
assert facture.factures_avoir.count() == 0
|
||||
assert 'Annuler' in [li.a.text for li in facture_0137_page.html.find_all('li')]
|
||||
facture_avoir_page = facture_0137_page.click("Annuler")
|
||||
facture_avoir_page = facture_0137_page.click('Annuler')
|
||||
facture_avoir_page = facture_avoir_page.follow()
|
||||
assert facture.factures_avoir.count() == 1
|
||||
facture_avoir = facture.factures_avoir.first()
|
||||
|
@ -96,7 +96,7 @@ def test_facture_avoir(app):
|
|||
assert facture_avoir.code() == 'F20190237'
|
||||
|
||||
assert 'Imprimer' in [li.a.text for li in facture_avoir_page.html.find_all('li')]
|
||||
factur_x_page = app.get("/eo_facture/facture/%s/view_pdf/F20190137.pdf?facturx" % facture_avoir.id)
|
||||
factur_x_page = app.get('/eo_facture/facture/%s/view_pdf/F20190137.pdf?facturx' % facture_avoir.id)
|
||||
factur_x_pdf = factur_x_page.body
|
||||
_, factur_x_xml = facturx.get_facturx_xml_from_pdf(io.BytesIO(factur_x_pdf))
|
||||
root = ET.fromstring(factur_x_xml)
|
||||
|
@ -174,32 +174,32 @@ def test_facture_filename(app, settings):
|
|||
settings.FACTURE_DIR = tmpdir
|
||||
facture = [x for x in Facture.objects.all() if x.code() == 'F20190137'][0]
|
||||
|
||||
response = app.get("/eo_facture/facture/").follow()
|
||||
response.form.set("username", "admin")
|
||||
response.form.set("password", "admin")
|
||||
response = app.get('/eo_facture/facture/').follow()
|
||||
response.form.set('username', 'admin')
|
||||
response.form.set('password', 'admin')
|
||||
homepage = response.form.submit().follow()
|
||||
|
||||
# facture F20190137
|
||||
factures_page = homepage.click("Factures")
|
||||
factures_page = homepage.click('Factures')
|
||||
facture_0137_page = factures_page.click(facture.code())
|
||||
assert (
|
||||
'/view_pdf/F20190137.pdf'
|
||||
in [li.a['href'] for li in facture_0137_page.html.find_all('li') if li.text == 'Imprimer'][0]
|
||||
)
|
||||
app.get("/eo_facture/facture/%s/view_pdf/" % facture.id)
|
||||
assert os.path.exists(os.path.join(tmpdir, "F20190137-c3f42bb0d75d379.pdf"))
|
||||
app.get('/eo_facture/facture/%s/view_pdf/' % facture.id)
|
||||
assert os.path.exists(os.path.join(tmpdir, 'F20190137-c3f42bb0d75d379.pdf'))
|
||||
|
||||
# facture avoir proforma
|
||||
facture_avoir_page = facture_0137_page.click("Annuler")
|
||||
facture_avoir_page = facture_0137_page.click('Annuler')
|
||||
facture_avoir_page = facture_avoir_page.follow()
|
||||
facture_avoir = facture.factures_avoir.first()
|
||||
assert (
|
||||
'/view_pdf/Devis n°%s du 2019-10-09-AVOIR.pdf' % facture_avoir.id
|
||||
in [li.a['href'] for li in facture_avoir_page.html.find_all('li') if li.text == 'Imprimer'][0]
|
||||
)
|
||||
app.get("/eo_facture/facture/%s/view_pdf/" % facture_avoir.id)
|
||||
app.get('/eo_facture/facture/%s/view_pdf/' % facture_avoir.id)
|
||||
assert os.path.exists(
|
||||
os.path.join(tmpdir, "Devis n°%s du 2019-10-09-c3f42bb0d75d379-AVOIR.pdf" % facture_avoir.id)
|
||||
os.path.join(tmpdir, 'Devis n°%s du 2019-10-09-c3f42bb0d75d379-AVOIR.pdf' % facture_avoir.id)
|
||||
)
|
||||
|
||||
# facture avoir
|
||||
|
@ -211,8 +211,8 @@ def test_facture_filename(app, settings):
|
|||
'/view_pdf/F20190237-AVOIR.pdf'
|
||||
in [li.a['href'] for li in facture_avoir_page.html.find_all('li') if li.text == 'Imprimer'][0]
|
||||
)
|
||||
app.get("/eo_facture/facture/%s/view_pdf/" % facture_avoir.id)
|
||||
assert os.path.exists(os.path.join(tmpdir, "F20190237-c3f42bb0d75d379-AVOIR.pdf"))
|
||||
app.get('/eo_facture/facture/%s/view_pdf/' % facture_avoir.id)
|
||||
assert os.path.exists(os.path.join(tmpdir, 'F20190237-c3f42bb0d75d379-AVOIR.pdf'))
|
||||
|
||||
|
||||
def test_facture_pdf(app):
|
||||
|
|
Loading…
Reference in New Issue