Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion django_ledger/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
default_app_config = 'django_ledger.apps.DjangoLedgerConfig'

"""Django Ledger"""
__version__ = '0.7.9'
__version__ = '0.7.10'
__license__ = 'GPLv3 License'

__author__ = 'Miguel Sanda'
Expand Down
4 changes: 1 addition & 3 deletions django_ledger/forms/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from treebeard.forms import MoveNodeForm

from django_ledger.io import ACCOUNT_CHOICES_NO_ROOT
from django_ledger.models import ChartOfAccountModel, EntityModel
from django_ledger.models import ChartOfAccountModel
from django_ledger.models.accounts import AccountModel
from django_ledger.settings import DJANGO_LEDGER_FORM_INPUT_CLASSES

Expand All @@ -24,8 +24,6 @@ class AccountModelCreateForm(ModelForm):

Attributes
----------
ENTITY_MODEL : Model
The entity model being used in the form.
COA_MODEL : Model
The Chart of Account Model being used in the form.
"""
Expand Down
5 changes: 5 additions & 0 deletions django_ledger/forms/customer.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class Meta:
model = CustomerModel
fields = [
'customer_name',
'customer_code',
'address_1',
'address_2',
'city',
Expand All @@ -43,6 +44,10 @@ class Meta:
'customer_name': TextInput(attrs={
'class': DJANGO_LEDGER_FORM_INPUT_CLASSES
}),
'customer_code': TextInput(attrs={
'class': DJANGO_LEDGER_FORM_INPUT_CLASSES,
'placeholder': 'Ex: CDR-78987-2025...'
}),
'address_1': TextInput(attrs={
'class': DJANGO_LEDGER_FORM_INPUT_CLASSES
}),
Expand Down
5 changes: 5 additions & 0 deletions django_ledger/forms/vendor.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class Meta:
model = VendorModel
fields = [
'vendor_name',
'vendor_code',
'address_1',
'address_2',
'city',
Expand All @@ -39,6 +40,10 @@ class Meta:
'vendor_name': TextInput(attrs={
'class': DJANGO_LEDGER_FORM_INPUT_CLASSES
}),
'vendor_code': TextInput(attrs={
'class': DJANGO_LEDGER_FORM_INPUT_CLASSES,
'placeholder': 'Ex: GRB-67987-2025...'
}),
'address_1': TextInput(attrs={
'class': DJANGO_LEDGER_FORM_INPUT_CLASSES
}),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Generated by Django 5.2.1 on 2025-08-22 19:05

import django.db.models.deletion
import django_ledger.models.customer
import django_ledger.models.vendor
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('django_ledger', '0022_bankaccountmodel_financial_institution_and_more'),
]

operations = [
migrations.AddField(
model_name='customermodel',
name='customer_code',
field=models.SlugField(blank=True, null=True, unique=True, verbose_name='User defined customer code'),
),
migrations.AddField(
model_name='customermodel',
name='picture',
field=models.ImageField(blank=True, null=True, upload_to=django_ledger.models.customer.customer_picture_upload_to),
),
migrations.AddField(
model_name='vendormodel',
name='picture',
field=models.ImageField(blank=True, null=True, upload_to=django_ledger.models.vendor.vendor_picture_upload_to),
),
migrations.AddField(
model_name='vendormodel',
name='vendor_code',
field=models.SlugField(blank=True, null=True, verbose_name='User defined vendor code.'),
),
migrations.AlterField(
model_name='customermodel',
name='customer_number',
field=models.CharField(editable=False, help_text='System generated customer number.', max_length=30, verbose_name='Customer Number'),
),
migrations.AlterField(
model_name='vendormodel',
name='entity_model',
field=models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to='django_ledger.entitymodel', verbose_name='Vendor Entity'),
),
migrations.AlterField(
model_name='vendormodel',
name='vendor_number',
field=models.CharField(blank=True, editable=False, help_text='System generated vendor number.', max_length=30, null=True, verbose_name='Vendor Number'),
),
]
25 changes: 24 additions & 1 deletion django_ledger/models/customer.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,32 @@
created before it can be assigned to the InvoiceModel. Only customers who are active can be assigned to new Invoices.
"""

import os
from uuid import uuid4

from django.core.exceptions import ObjectDoesNotExist
from django.db import models, transaction, IntegrityError
from django.db.models import Q, F, QuerySet, Manager
from django.utils.text import slugify
from django.utils.translation import gettext_lazy as _

from django_ledger.models.mixins import ContactInfoMixIn, CreateUpdateMixIn, TaxCollectionMixIn
from django_ledger.models.utils import lazy_loader
from django_ledger.settings import DJANGO_LEDGER_DOCUMENT_NUMBER_PADDING, DJANGO_LEDGER_CUSTOMER_NUMBER_PREFIX


def customer_picture_upload_to(instance, filename):
"""
Stores pictures under: customer_pictures/<customer_number>/<sanitized-filename>.<ext>
"""
if not instance.customer_number:
instance.generate_customer_number(commit=False)
customer_number = instance.customer_number
name, ext = os.path.splitext(filename)
safe_name = slugify(name)
return f'customer_pictures/{customer_number}/{safe_name}{ext.lower()}'


class CustomerModelQueryset(QuerySet):
"""
A custom defined QuerySet for the CustomerModel. This implements multiple methods or queries needed to get a
Expand Down Expand Up @@ -170,15 +184,24 @@ class CustomerModelAbstract(ContactInfoMixIn, TaxCollectionMixIn, CreateUpdateMi
"""

uuid = models.UUIDField(default=uuid4, editable=False, primary_key=True)
customer_code = models.SlugField(
max_length=50,
unique=True,
null=True,
blank=True,
verbose_name='User defined customer code'
)
customer_name = models.CharField(max_length=100)
customer_number = models.CharField(max_length=30, editable=False, verbose_name=_('Customer Number'))
customer_number = models.CharField(max_length=30, editable=False, verbose_name=_('Customer Number'),
help_text='System generated customer number.')
entity_model = models.ForeignKey('django_ledger.EntityModel',
editable=False,
on_delete=models.CASCADE,
verbose_name=_('Customer Entity'))
description = models.TextField()
active = models.BooleanField(default=True)
hidden = models.BooleanField(default=False)
picture = models.ImageField(upload_to=customer_picture_upload_to, null=True, blank=True)

additional_info = models.JSONField(null=True, blank=True, default=dict)

Expand Down
34 changes: 28 additions & 6 deletions django_ledger/models/vendor.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,29 @@
whether temporarily or indefinitely may be flagged as inactive (i.e. active is False). Hidden Vendors will not show up
as an option in the UI, but can still be used programmatically (via API).
"""

import os
from uuid import uuid4

from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.db import models, transaction, IntegrityError
from django.db.models import Q, F, QuerySet
from django.db.models import Q, F, QuerySet, Manager
from django.utils.text import slugify
from django.utils.translation import gettext_lazy as _

from django_ledger.models.mixins import ContactInfoMixIn, CreateUpdateMixIn, FinancialAccountInfoMixin, TaxInfoMixIn
from django_ledger.models.utils import lazy_loader
from django_ledger.settings import DJANGO_LEDGER_DOCUMENT_NUMBER_PADDING, DJANGO_LEDGER_VENDOR_NUMBER_PREFIX


def vendor_picture_upload_to(instance, filename):
if not instance.customer_number:
instance.generate_customer_number(commit=False)
vendor_number = instance.customer_number
name, ext = os.path.splitext(filename)
safe_name = slugify(name)
return f'vendor_pictures/{vendor_number}/{safe_name}{ext.lower()}'


class VendorModelValidationError(ValidationError):
pass

Expand Down Expand Up @@ -83,7 +93,7 @@ def visible(self) -> QuerySet:
)


class VendorModelManager(models.Manager):
class VendorModelManager(Manager):
"""
Custom defined VendorModel Manager, which defines many methods for initial query of the Database.
"""
Expand Down Expand Up @@ -173,15 +183,27 @@ class VendorModelAbstract(ContactInfoMixIn,

"""
uuid = models.UUIDField(default=uuid4, editable=False, primary_key=True)
vendor_number = models.CharField(max_length=30, null=True, blank=True)
vendor_code = models.SlugField(
max_length=50,
null=True,
blank=True,
verbose_name='User defined vendor code.'
)
vendor_number = models.CharField(max_length=30,
null=True,
blank=True,
editable=False,
verbose_name=_('Vendor Number'), help_text='System generated vendor number.')
vendor_name = models.CharField(max_length=100)

entity_model = models.ForeignKey('django_ledger.EntityModel',
on_delete=models.CASCADE,
verbose_name=_('Vendor Entity'))
verbose_name=_('Vendor Entity'),
editable=False)
description = models.TextField()
active = models.BooleanField(default=True)
hidden = models.BooleanField(default=False)
picture = models.ImageField(upload_to=vendor_picture_upload_to, null=True, blank=True)

additional_info = models.JSONField(null=True, blank=True, default=dict)

Expand Down Expand Up @@ -215,7 +237,7 @@ def can_generate_vendor_number(self) -> bool:
Returns
-------
bool
True if vendor number can be generated, else False.
True if the vendor number can be generated, else False.
"""
return all([
self.entity_model_id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<th class="has-text-centered">{% trans 'Customer Number' %}</th>
<th class="has-text-centered">{% trans 'Customer' %}</th>
<th class="has-text-centered">{% trans 'Address' %}</th>
<th class="has-text-centered">{% trans 'Customer Code' %}</th>
<th class="has-text-centered">{% trans 'Active' %}</th>
<th class="has-text-centered">{% trans 'Hidden' %}</th>
<th class="has-text-centered">{% trans 'Actions' %}</th>
Expand All @@ -19,6 +20,7 @@
<td>{{ customer.customer_number }}</td>
<td>{{ customer.customer_name }}</td>
<td>{{ customer.address_1 }}</td>
<td>{% if customer.customer_code %}{{ customer.customer_code }}{% endif %}</td>
<td>
{% if customer.active %}
<span class="icon has-text-success-dark">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@
<section class="hero is-light is-bold is-small">
<div class="hero-body">
<div class="container">
<h1 class="title">{% trans 'Receivables' %}</h1>
<h2 class="subtitle">
<h1 class="is-size-2 is-bold">{% trans 'Receivables' %}</h1>
<h2 class="is-size-5 has-text-weight-light">
<span class="icon">{% icon "ic:baseline-business" 16 %}</span>{{ entity.name }}</h2>
</div>
</div>
Expand Down Expand Up @@ -80,8 +80,8 @@ <h2 class="subtitle">
<section class="hero is-light is-bold is-small">
<div class="hero-body">
<div class="container">
<h1 class="title">{% trans 'Payables' %}</h1>
<h2 class="subtitle">
<h1 class="is-size-2 is-bold">{% trans 'Payables' %}</h1>
<h2 class="is-size-5 has-text-weight-light">
<span class="icon">{% icon "ic:baseline-business" 16 %}</span>{{ entity.name }}</h2>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
</div>
{% endif %}
<div class="column is-9">
<h1 class="title has-text-weight-light">{{ header_title }}</h1>
<h1 class="is-size-2 is-bold">{{ header_title }}</h1>
{% if header_subtitle %}
<h2 class="subtitle">{{ header_subtitle }}</h2>
<h2 class="is-size-5 has-text-weight-light">{{ header_subtitle }}</h2>
{% endif %}
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<th class="has-text-centered">{% trans 'Vendor Number' %}</th>
<th class="has-text-centered">{% trans 'Vendor' %}</th>
<th class="has-text-centered">{% trans 'Address' %}</th>
<th class="has-text-centered">{% trans 'Code' %}</th>
<th class="has-text-centered">{% trans 'Active' %}</th>
<th class="has-text-centered">{% trans 'Hidden' %}</th>
<th class="has-text-centered">{% trans 'Actions' %}</th>
Expand All @@ -20,6 +21,7 @@
<td>{{ vendor.vendor_number }}</td>
<td>{{ vendor.vendor_name }}</td>
<td>{{ vendor.address_1 }}</td>
<td>{% if vendor.vendor_code %}{{ vendor.vendor_code }}{% endif %}</td>
<td>
{% if vendor.active %}
<span class="icon has-text-success-dark">
Expand All @@ -31,6 +33,7 @@
</span>
{% endif %}
</td>

<td>
{% if vendor.hidden %}
<span class="icon has-text-success-dark">
Expand Down
Loading