finance-sdk 1.0.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2 @@
1
+ default_app_config = 'finance_sdk.apps.FinanceSdkConfig'
2
+ __version__ = '1.0.2'
finance_sdk/admin.py ADDED
@@ -0,0 +1,3 @@
1
+ from django.contrib import admin
2
+
3
+ # Register your models here.
finance_sdk/apps.py ADDED
@@ -0,0 +1,6 @@
1
+ from django.apps import AppConfig
2
+
3
+
4
+ class FinanceSdkConfig(AppConfig):
5
+ default_auto_field = 'django.db.models.BigAutoField'
6
+ name = 'finance_sdk'
finance_sdk/enums.py ADDED
@@ -0,0 +1,52 @@
1
+
2
+ class Type:
3
+ ENTRY = "E"
4
+ OUT = "O"
5
+ AUTOMATIC_PAYMENT = "AP"
6
+ PAID_ENTRY = 'PE'
7
+
8
+ CHOICES = (
9
+ (ENTRY , "Entry"),
10
+ (OUT , "Out"),
11
+ (AUTOMATIC_PAYMENT, "Automatic Payment"),
12
+ (PAID_ENTRY , "Paid entry")
13
+ )
14
+
15
+
16
+
17
+ class RegistryClassification:
18
+ VARIABLE = "variable"
19
+ FIX = "fix"
20
+ INVESTIMENT = "investiment"
21
+
22
+ CHOICES = (
23
+ (VARIABLE, "variable"),
24
+ (FIX , "fix"),
25
+ (INVESTIMENT, "investiment"),
26
+ )
27
+
28
+
29
+ class Frequency:
30
+ NONE = 0
31
+ WEEK = 7
32
+ BIWEEK = 15
33
+ MONTH = 30
34
+ YEAR = 365
35
+
36
+ CHOICES = (
37
+ (NONE, "None"),
38
+ (WEEK , "Week"),
39
+ (BIWEEK, "Biweek"),
40
+ (BIWEEK, "Biweek"),
41
+ )
42
+
43
+ @staticmethod
44
+ def get_frequency(frequency: int):
45
+ mapping = {
46
+ Frequency.WEEK : 2,
47
+ Frequency.BIWEEK : 3,
48
+ Frequency.MONTH : 4,
49
+ Frequency.YEAR : 5,
50
+
51
+ }
52
+ return mapping.get(frequency, 1)
File without changes
File without changes
@@ -0,0 +1,41 @@
1
+ from django.db import models
2
+
3
+ from models import bank
4
+
5
+ class Account(models.Model):
6
+ name = models.CharField(max_length=200, blank=False, null=False)
7
+ bank = models.ForeignKey(bank, on_delete=models.PROTECT)
8
+ deactivate = models.BooleanField(default=False, blank=False, null=False)
9
+ created_at = models.DateTimeField(auto_now_add=True)
10
+ updated_at = models.DateTimeField(auto_now=True)
11
+ client_app = models.JSONField()
12
+
13
+ def __str__(self):
14
+ return self.name + " - " + self.bank.name
15
+
16
+
17
+ class AccountPermission(models.Model):
18
+ account = models.ForeignKey(Account, on_delete=models.CASCADE)
19
+ employee = models.JSONField()
20
+ deactivate = models.BooleanField(default=False, blank=False, null=False)
21
+ created_at = models.DateTimeField(auto_now_add=True)
22
+ updated_at = models.DateTimeField(auto_now=True)
23
+ client_app = models.JSONField()
24
+
25
+ def __str__(self):
26
+ return "Account: %s | %s" % (self.account, self.employee)
27
+
28
+ @staticmethod
29
+ def get_account(user_id, client_app):
30
+ accounts = Account.objects.filter(
31
+ id__in=[
32
+ AccountPermission.objects.filter(
33
+ employee__user_id=user_id,
34
+ client_app_id=client_app,
35
+ deactivate=False,
36
+ account__bank__deactivate=False,
37
+ ).values_list("account_id")
38
+ ]
39
+ )
40
+
41
+ return accounts
@@ -0,0 +1,11 @@
1
+ from django.db import models
2
+
3
+ class Bank(models.Model):
4
+ name = models.CharField(max_length=200, blank=False, null=False)
5
+ deactivate = models.BooleanField(default=False, blank=False, null=False)
6
+ created_at = models.DateTimeField(auto_now_add=True)
7
+ updated_at = models.DateTimeField(auto_now=True)
8
+ client_app = models.JSONField()
9
+
10
+ def __str__(self):
11
+ return self.name
@@ -0,0 +1,17 @@
1
+ from django.db import models
2
+
3
+ class Category(models.Model):
4
+ name = models.CharField("Nome", max_length=200, blank=False, null=False)
5
+ principal_category = models.ForeignKey(
6
+ "self", on_delete=models.PROTECT, blank=True, null=True
7
+ )
8
+ is_entry = models.BooleanField(default=True, blank=False, null=False)
9
+ is_out = models.BooleanField(default=True, blank=False, null=False)
10
+ deactivate = models.BooleanField(default=False, blank=False, null=False)
11
+ created_at = models.DateTimeField(auto_now_add=True)
12
+ updated_at = models.DateTimeField(auto_now=True)
13
+ client_app = models.JSONField()
14
+
15
+
16
+ def __str__(self):
17
+ return self.name
@@ -0,0 +1,53 @@
1
+ from django.db import models
2
+
3
+ from category import Category
4
+ from payment import PaymentMethod
5
+ from accounts import Account
6
+
7
+ from enums import Frequency, Type, RegistryClassification
8
+
9
+ class Entry(models.Model):
10
+ due_date = models.DateField(blank=False)
11
+ payment_date = models.DateField(blank=True, null=True)
12
+ description = models.TextField("Description", blank=False)
13
+ category = models.ForeignKey(
14
+ Category,
15
+ verbose_name="Category",
16
+ on_delete=models.PROTECT,
17
+ blank=True,
18
+ null=True,
19
+ )
20
+ value = models.DecimalField(max_digits=9, decimal_places=2, blank=False, null=False)
21
+ received_value = models.DecimalField(
22
+ max_digits=9, decimal_places=2, blank=True, null=True
23
+ )
24
+ liquid_value = models.DecimalField(
25
+ max_digits=9, decimal_places=2, blank=True, null=True
26
+ )
27
+ payment_method = models.ForeignKey(
28
+ PaymentMethod, on_delete=models.PROTECT, null=True
29
+ )
30
+ registry_classification = models.CharField(
31
+ max_length=30,
32
+ blank=True,
33
+ null=False,
34
+ default=RegistryClassification.VARIABLE,
35
+ choices=RegistryClassification.CHOICES,
36
+ )
37
+ number_of_payments = models.PositiveIntegerField(default=1, null=False, blank=False)
38
+ current_payment = models.PositiveIntegerField(default=1, null=False, blank=False)
39
+ frequency = models.IntegerField(
40
+ choices=Frequency, default=Frequency.NONE, null=True, blank=True
41
+ )
42
+ reference_record = models.ForeignKey(
43
+ "self", on_delete=models.PROTECT, null=True, blank=False, related_name="payments"
44
+ )
45
+ observation = models.TextField(blank=True, null=True)
46
+ cost_center = models.JSONField(default=dict)
47
+ account = models.ForeignKey(Account, on_delete=models.PROTECT, blank=True, null=True)
48
+ entry_type = models.CharField(max_length=1, choices=Type.CHOICES, blank=False)
49
+ person = models.JSONField(default=dict)
50
+ tag = models.TextField(blank=True, null=True)
51
+ created_at = models.DateTimeField(auto_now_add=True)
52
+ updated_at = models.DateTimeField(auto_now=True)
53
+ client_app = models.JSONField(default=dict, null=False, blank=False)
@@ -0,0 +1,29 @@
1
+ from django.db import models
2
+
3
+ class PaymentMethod(models.Model):
4
+ name = models.CharField("Nome", max_length=200, blank=False, null=False)
5
+ tax = models.DecimalField(
6
+ decimal_places=2, max_digits=9, blank=True, null=True, default=0
7
+ )
8
+ deactivate = models.BooleanField(default=False, blank=False, null=False)
9
+ created_at = models.DateTimeField(auto_now_add=True)
10
+ updated_at = models.DateTimeField(auto_now=True)
11
+ client_app = models.JSONField()
12
+
13
+
14
+ def __str__(self):
15
+ return self.nome
16
+
17
+ def save(self, *args, **kwargs):
18
+ if self.taxa == "":
19
+ self.taxa = 0
20
+
21
+ super(PaymentMethod, self).save(*args, **kwargs)
22
+
23
+
24
+ class PaymentMethodTaxs(models.Model):
25
+ initial_payment = models.PositiveIntegerField()
26
+ final_payment = models.PositiveIntegerField()
27
+ tax = models.DecimalField(decimal_places=2, max_digits=5)
28
+ PaymentMethod = models.ForeignKey(PaymentMethod, on_delete=models.PROTECT)
29
+ client_app = models.JSONField()
File without changes
@@ -0,0 +1,45 @@
1
+ from rest_framework import serializers
2
+ from models.accounts import Account, AccountPermission
3
+
4
+
5
+ class AccountSerializer(serializers.ModelSerializer):
6
+ class Meta:
7
+ model = Account
8
+ fields = ["id", "name", "bank"]
9
+
10
+ def validate_name(self, value):
11
+ if not (self.instance and value == self.instance.name):
12
+ if Account.objects.filter(
13
+ name=value, deactivate=False, client_app=self.initial_data.get('client_app')).exists():
14
+ raise serializers.ValidationError(
15
+ "Already exists an account with this name."
16
+ )
17
+
18
+ return value
19
+
20
+
21
+
22
+ class AccountPermissionSerializer(serializers.ModelSerializer):
23
+
24
+ class Meta:
25
+ model = AccountPermission
26
+ fields = ["id", "account", "employee"]
27
+ validators = []
28
+
29
+ def validate(self, attrs):
30
+ if (
31
+ AccountPermission.objects.filter(
32
+ employee__id=attrs["employee"],
33
+ account=attrs["account"],
34
+ deactivate=False,
35
+ account__deactivate=False,
36
+ account__bank__deactivate=False,
37
+ ).exists()
38
+ ):
39
+ raise serializers.ValidationError(
40
+ {"employee": "This employee already has permission"}
41
+ )
42
+
43
+ return attrs
44
+
45
+
@@ -0,0 +1,20 @@
1
+ from rest_framework import serializers
2
+ from models.bank import Bank
3
+
4
+
5
+ class BankSerializer(serializers.ModelSerializer):
6
+
7
+ class Meta:
8
+ model = Bank
9
+ fields = ["id", "name"]
10
+
11
+ def validate_name(self, value):
12
+ if not (self.instance and value == self.instance.name):
13
+ if Bank.objects.filter(
14
+ name=value, deactivate =False, client_app=self.initial_data.get('client_app')
15
+ ).exists():
16
+ raise serializers.ValidationError(
17
+ "Already exists a bank with this name"
18
+ )
19
+
20
+ return value
@@ -0,0 +1,31 @@
1
+ from rest_framework import serializers
2
+ from models.category import Category
3
+
4
+ class CategorySerializer(serializers.ModelSerializer):
5
+
6
+ class Meta:
7
+ model = Category
8
+ fields = [
9
+ "id",
10
+ "name",
11
+ "principal_category",
12
+ "is_entry",
13
+ "is_out",
14
+ "deactivate",
15
+ ]
16
+
17
+ def validate_name(self, value):
18
+ if not (self.instance and value == self.instance.name):
19
+ if Category.objects.filter(
20
+ name=value, deactivate=False, client_app=self.initial_data.get('client_app')).exists():
21
+ raise serializers.ValidationError(
22
+ "Already exists a category with this name."
23
+ )
24
+
25
+ if Category.objects.filter(
26
+ name=value, deactivate=True, client_app=self.initial_data.get('client_app')).exists():
27
+ raise serializers.ValidationError(
28
+ "Already exists a category with this name."
29
+ )
30
+
31
+ return value
@@ -0,0 +1,144 @@
1
+ from django.db import transaction
2
+ from datetime import date, timedelta
3
+
4
+ from rest_framework import serializers
5
+ from finance_sdk.models.entry import Entry
6
+ from finance_sdk.models.accounts import AccountPermission
7
+
8
+ from enums import Frequency, Type, RegistryClassification
9
+ from services.entriesService import generate_entries
10
+
11
+ class EntrySerializer(serializers.ModelSerializer):
12
+
13
+ class Meta:
14
+ model = Entry
15
+ fields = [
16
+ "id",
17
+ "description",
18
+ "value",
19
+ "received_value",
20
+ "liquid_value",
21
+ "category",
22
+ "account",
23
+ "cost_center",
24
+ "payment_date",
25
+ "due_date",
26
+ "payment_method",
27
+ "person",
28
+ "entry_type",
29
+ "registry_classification",
30
+ "tag",
31
+ "number_of_payments",
32
+ "current_payment",
33
+ "frequency",
34
+ "reference_record",
35
+
36
+ ]
37
+
38
+ read_only_fields = [
39
+ "current_payment",
40
+ "reference_record",
41
+ "frequency",
42
+ "liquid_value",
43
+ ]
44
+
45
+ @transaction.atomic
46
+ def create(self, validated_data):
47
+ return generate_entries(self.initial_data, validated_data)
48
+
49
+ def update(self, instance, validated_data):
50
+ validated_data["number_of_payments"] = instance.number_of_payments
51
+ validated_data["frequency"] = instance.frequency
52
+ validated_data["reference_record"] = instance.reference_record
53
+ value = validated_data.get("value")
54
+ entry_type = (
55
+ validated_data.get("entry_type")
56
+ if validated_data.get("entry_type") is not None
57
+ else instance.entry_type
58
+ )
59
+ if value is not None and entry_type == Entry.entry_type.ENTRY:
60
+ payment_method = (
61
+ validated_data.get("payment_method")
62
+ if validated_data.get("payment_method") is not None
63
+ else instance.payment_method
64
+ )
65
+ if payment_method is not None:
66
+ validated_data["liquid_value"] = value * (payment_method.tax / 100)
67
+
68
+ if self.context.get("recalcular") and instance.forma_pagamento is not None:
69
+ validated_data["valor_liquido"] = instance.valor * (
70
+ instance.forma_pagamento.taxa / 100
71
+ )
72
+
73
+ return super().update(instance, validated_data)
74
+
75
+ def validate_payment_date(self, value):
76
+ DATE_LIMIT = date(2000, 1, 1)
77
+
78
+ if DATE_LIMIT > value:
79
+ raise serializers.ValidationError(
80
+ "Date can't be lower then 2000-01-01"
81
+ )
82
+
83
+ return value
84
+
85
+ def validate_due_date(self, value):
86
+ DATE_LIMIT = date(2000, 1, 1)
87
+
88
+ if DATE_LIMIT > value:
89
+ raise serializers.ValidationError(
90
+ "Date can't be lower then 2000-01-01"
91
+ )
92
+ return value
93
+
94
+ def validate_value(self, value):
95
+ if not value > 0:
96
+ raise serializers.ValidationError("The value must be greater than 0")
97
+
98
+ return value
99
+
100
+ def validate_account(self, value):
101
+ if not AccountPermission.objects.filter(
102
+ account=value, employee_id=self.initial_data.get('employee')
103
+ ).exists():
104
+ raise serializers.ValidationError("Invalid Account")
105
+
106
+ return value
107
+
108
+ def validate_number_of_payments(self, value):
109
+ if not value > 0:
110
+ raise serializers.ValidationError(
111
+ "Number of payments must be greater then 0"
112
+ )
113
+
114
+ return value
115
+
116
+
117
+ def validate(self, attrs):
118
+ frequency = attrs.get("frequency", Frequency.NONE)
119
+
120
+ if (frequency == Frequency.NONE) and (attrs.get("number_of_payments", 1) > 1):
121
+ raise serializers.ValidationError(
122
+ {
123
+ "message": "An accounts payable/receivable entry without any recurrence cannot have more than one payment."
124
+ }
125
+ )
126
+
127
+ if (attrs.get("number_of_payments", 1) == 1) and (
128
+ frequency != Frequency.NONE
129
+ ):
130
+ raise serializers.ValidationError(
131
+ {
132
+ "message": "The number of payments must be greater than 1 in order to have a frequency."
133
+ } )
134
+
135
+ value = attrs.get("value")
136
+ entry_type = attrs.get("entry_type")
137
+ if value and entry_type == Type.ENTRY:
138
+ paid_value = attrs.get("paid_value", 0)
139
+ if value < paid_value:
140
+ raise serializers.ValidationError(
141
+ {"message": "The Paid value can't be greater than the value."}
142
+ )
143
+
144
+ return attrs
@@ -0,0 +1,73 @@
1
+ from rest_framework import serializers
2
+ from models.payment import PaymentMethod, PaymentMethodTaxs
3
+
4
+
5
+ class PaymentMethodSerializer(serializers.ModelSerializer):
6
+ class Meta:
7
+ model = PaymentMethod
8
+ fields = ["id", "name", "tax"]
9
+
10
+ def validate_name(self, value):
11
+ if not (self.instance and value == self.instance.name):
12
+ if PaymentMethod.objects.filter(
13
+ name=value, deactivate=False, client_app=self.initial_data.get('client_app')).exists():
14
+ raise serializers.ValidationError(
15
+ "Already exists a payment method with this name."
16
+ )
17
+
18
+ return value
19
+
20
+ def validate_tax(self, value):
21
+ if value is not None and value < 0:
22
+ raise serializers.ValidationError("the tax can't be negative")
23
+
24
+ return value
25
+
26
+
27
+ class PaymentMethodTaxsSerializer(serializers.ModelSerializer):
28
+ class Meta:
29
+ model = PaymentMethodTaxs
30
+ fields = ["id", "initial_payment", "final_payment", "tax"]
31
+
32
+ def validate(self, attrs):
33
+ if attrs["initial_payment"] > attrs["final_payment"]:
34
+ raise serializers.ValidationError(
35
+ {"menssage": " The initial payment can't be bigger then the final_payment"}
36
+ )
37
+
38
+ taxs = PaymentMethodTaxs.objects.filter(
39
+ payment_method_id=self.context.get("payment_method_id"),
40
+ client_app=self.initial_data.get('client_app'),
41
+ )
42
+
43
+ if self.instance:
44
+ taxs = taxs.exclude(id=self.instance.id)
45
+
46
+ for tax in taxs:
47
+ if attrs["initial_payment"] in range(
48
+ tax.initial_payment, tax.final_payment + 1
49
+ ):
50
+ raise serializers.ValidationError(
51
+ {
52
+ "initial_payment": "Already exists a tax for this payment in this payment method."
53
+ }
54
+ )
55
+ elif attrs["final_payment"] in range(
56
+ tax.initial_payment, tax.final_payment + 1
57
+ ):
58
+ raise serializers.ValidationError(
59
+ {
60
+ "final_payment": "Already exists a tax for this payment in this payment method."
61
+ }
62
+ )
63
+ elif (
64
+ tax.initial_payment >= attrs["initial_payment"]
65
+ and tax.final_payment <= attrs["final_payment"]
66
+ ):
67
+ raise serializers.ValidationError(
68
+ {
69
+ "menssage": "Already exists a tax for this payments in this payment method."
70
+ }
71
+ )
72
+
73
+ return attrs
File without changes
@@ -0,0 +1,77 @@
1
+ from datetime import date, timedelta
2
+ from finance_sdk.models.entry import Entry
3
+
4
+
5
+ from enums import Frequency
6
+
7
+ def generate_entries(validated_data, initial_data):
8
+ number_of_payments = validated_data.get("number_of_payments", 1)
9
+ payment_value = validated_data.get("value") / number_of_payments
10
+ frequency = validated_data.get("frequency")
11
+ validated_data["frequency"] = Frequency.get_frequency(frequency=frequency)
12
+ primary_payment = Entry.objects.create(**validated_data)
13
+ payment_method = primary_payment.payment_method
14
+ tax = payment_method.tax / 100 if payment_method else 0
15
+ liquid_value = (
16
+ payment_value - payment_value * tax
17
+ if validated_data.get("type") == Entry.entry_type.ENTRY
18
+ else None
19
+ )
20
+ primary_payment.value = payment_value
21
+ primary_payment.liquid_value = liquid_value
22
+ primary_payment.client_app = initial_data.get('client_app')
23
+ primary_payment.reference_record_id = primary_payment.id
24
+ primary_payment.save()
25
+
26
+ if number_of_payments > 1:
27
+ entry_payments = []
28
+ for payment in range(2, number_of_payments + 1):
29
+ entry_payments.append(
30
+ Entry(
31
+ description=validated_data.get("description"),
32
+ value=payment_value,
33
+ liquid_value=liquid_value,
34
+ category=validated_data.get("category"),
35
+ account=validated_data.get("account"),
36
+ cost_center=validated_data.get("cost_center"),
37
+ due_date=validated_data.get("due_date")
38
+ + timedelta(days=frequency * (payment - 1)),
39
+ payment_method=validated_data.get("payment_method"),
40
+ person=validated_data.get("person"),
41
+ entry_type=validated_data.get("entry_type"),
42
+ registry_classification=validated_data.get(
43
+ "registry_classification"
44
+ ),
45
+ number_of_payments=validated_data.get("number_of_payments"),
46
+ current_payment=payment,
47
+ frequency=primary_payment.frequency,
48
+ reference_record_id=primary_payment.pk,
49
+ client_app=initial_data.get('client_app'),
50
+ )
51
+ )
52
+
53
+ Entry.objects.bulk_create(entry_payments)
54
+ else:
55
+ received_value = validated_data.get("received_value", 0)
56
+ total_value = validated_data.get("value", 0)
57
+
58
+
59
+ if received_value < total_value and received_value > 0:
60
+ Entry.objects.create(
61
+ description=validated_data.get("description"),
62
+ value=total_value - received_value,
63
+ category=validated_data.get("category"),
64
+ account=validated_data.get("account"),
65
+ cost_center=validated_data.get("cost_center"),
66
+ due_date=validated_data.get("due_date"),
67
+ person=validated_data.get("person"),
68
+ entry_type=validated_data.get("entry_type"),
69
+ registry_classification=validated_data.get("registry_classification"),
70
+ number_of_payments=validated_data.get("numero_parcelas", 1),
71
+ cliente_app_id=initial_data.get('client_app'),
72
+ )
73
+
74
+ return primary_payment
75
+
76
+
77
+
finance_sdk/tests.py ADDED
@@ -0,0 +1,3 @@
1
+ from django.test import TestCase
2
+
3
+ # Create your tests here.
finance_sdk/utils.py ADDED
@@ -0,0 +1,63 @@
1
+ from django.forms import ValidationError
2
+
3
+
4
+
5
+ def raise_error(message):
6
+ raise ValidationError(
7
+ {
8
+ "message": message,
9
+ })
10
+
11
+
12
+ def validate_item_in_list(
13
+ item, list, message, message_if_empty="", required=False
14
+ ):
15
+ if required and not item:
16
+ raise_error(message_if_empty)
17
+
18
+ if item:
19
+ if isinstance(item, list):
20
+ itens = item
21
+
22
+ return (
23
+ itens
24
+ if all(item in list for item in itens)
25
+ else raise_error(message)
26
+ )
27
+
28
+ return item if item in list else raise_error(message)
29
+
30
+ return False
31
+
32
+
33
+
34
+ def validate_natural_number(
35
+ number, message, message_if_empty="", required=False
36
+ ):
37
+ if isinstance(number, list):
38
+ number = list(filter(lambda x: x.strip() != "", number))
39
+
40
+ elif isinstance(number, str) and number.strip() == "":
41
+ number = None
42
+
43
+ if required and not number:
44
+ raise_error(message_if_empty)
45
+
46
+ if number:
47
+ if isinstance(number, list):
48
+ numbers = number
49
+ to_int = lambda x: int(x)
50
+
51
+ return (
52
+ list(map(to_int, numbers))
53
+ if all(number.isnumeric() and number != "0" for number in numbers)
54
+ else raise_error(message)
55
+ )
56
+
57
+ return (
58
+ number
59
+ if number.isnumeric() and number != "0"
60
+ else raise_error(message)
61
+ )
62
+
63
+ return False
File without changes
@@ -0,0 +1,50 @@
1
+ import operator
2
+ from functools import reduce
3
+ from rest_framework import viewsets
4
+ from rest_framework.views import APIView
5
+
6
+ from django.db.models.query_utils import Q
7
+
8
+ from models.accounts import Account, AccountPermission
9
+ from serializers.accounts import AccountSerializer, AccountPermissionSerializer
10
+
11
+
12
+
13
+ class AccountViewSet(viewsets.ModelViewSet):
14
+
15
+ serializer_class = AccountSerializer
16
+ queryset = Account.objects.all()
17
+
18
+ def get_queryset(self):
19
+ queryset = super().get_queryset()
20
+
21
+ query = Q(deactivate=False)
22
+
23
+ if self.action == "list":
24
+ LIST = "list"
25
+ INDICATORS = "indicators"
26
+
27
+ name = str(self.request.query_params.get("name", ""))
28
+
29
+ use = self.validate_item_in_list(
30
+ item=self.request.query_params.get("use", "list"),
31
+ list=[LIST, INDICATORS],
32
+ message="Invalid",
33
+ required=True,
34
+ )
35
+
36
+ if use == INDICATORS:
37
+ queryset = AccountPermission.get_conta(
38
+ self.request.user.id, self.request.META["HTTP_CLIENTE_APP_ID"]
39
+ )
40
+
41
+ if name != "":
42
+ query &= reduce(
43
+ operator.__and__,
44
+ (
45
+ Q(name__unaccent__icontains=word)
46
+ for word in name.split(" ")
47
+ ),
48
+ )
49
+
50
+ return queryset.filter(query).order_by("name")
@@ -0,0 +1,30 @@
1
+ import operator
2
+ from functools import reduce
3
+ from rest_framework import viewsets
4
+ from rest_framework.views import APIView
5
+
6
+ from django.db.models.query_utils import Q
7
+
8
+ from models.bank import Bank
9
+ from serializers.bank import BankSerializer
10
+
11
+ class BankViewSet(viewsets.ModelViewSet):
12
+
13
+ serializer_class = BankSerializer
14
+ queryset = Bank.objects.all()
15
+
16
+ def get_queryset(self):
17
+ queryset = super().get_queryset()
18
+
19
+ query = Q(deactivate=False)
20
+
21
+ if self.action == "list":
22
+ name = str(self.request.query_params.get("name", "")).split(" ")
23
+
24
+ if name != "":
25
+ query &= reduce(
26
+ operator.__and__,
27
+ (Q(name__unaccent__icontains=word) for word in name),
28
+ )
29
+
30
+ return queryset.filter(query).order_by("-name")
@@ -0,0 +1,36 @@
1
+ import operator
2
+ from functools import reduce
3
+ from rest_framework import viewsets
4
+ from rest_framework.views import APIView
5
+
6
+ from django.db.models.query_utils import Q
7
+
8
+ from models.category import Category
9
+ from serializers.category import CategorySerializer
10
+
11
+
12
+ class CategoryViewSet(viewsets.ModelViewSet):
13
+ serializer_class = CategorySerializer
14
+ queryset = Category.objects.all()
15
+
16
+ def get_queryset(self):
17
+ queryset = super().get_queryset()
18
+
19
+ query = Q()
20
+
21
+ if self.action == "list":
22
+ query_params = self.request.query_params
23
+
24
+ name = str(query_params.get("name", "")).split(" ")
25
+
26
+ if name != "":
27
+ query &= reduce(
28
+ operator.__and__,
29
+ (Q(name__unaccent__icontains=word) for word in name),
30
+ )
31
+
32
+ deactivates = query_params.get("deactivate", "").lower() == "true"
33
+
34
+ query &= Q(deactivate=deactivates)
35
+
36
+ return queryset.filter(query).order_by("name")
@@ -0,0 +1,206 @@
1
+ from argparse import Action
2
+ import operator
3
+ from functools import reduce
4
+ from rest_framework.response import Response
5
+ from rest_framework import viewsets
6
+ from rest_framework.views import APIView
7
+
8
+ from django.db.models.query_utils import Q
9
+ from finance_sdk_wlc.finance_sdk.utils import validate_item_in_list, validate_natural_number
10
+
11
+ from enums import Frequency, Type
12
+
13
+ from models.entry import Entry
14
+ from serializers.entry import EntrySerializer
15
+
16
+ from models.accounts import Account, AccountPermission
17
+
18
+
19
+ class EntryViewSet( viewsets.ModelViewSet):
20
+
21
+ serializer_class = EntrySerializer
22
+ queryset = Entry.objects.all()
23
+
24
+
25
+ def get_queryset(self):
26
+ client_app_id = self.request.query_params.get("client_app")
27
+ employee_id = self.request.query_params.get("employee")
28
+
29
+ queryset = self.queryset
30
+
31
+ query = (
32
+ (
33
+ Q(
34
+ account_id__in=AccountPermission.get_conta(
35
+ self.request.user.id, client_app_id
36
+ ),
37
+ account__deactivate=False,
38
+ account__bank__deactivate=False,
39
+ )
40
+ | Q(account__isnull=True) )
41
+ &
42
+
43
+ (
44
+ Q(payment_method__isnull=False, payment_method__desativada=False)
45
+ | Q(payment_method__isnull=True)
46
+ )
47
+ & (
48
+ Q(category__isnull=False, category__deactivate=False)
49
+ | Q(category__isnull=True)
50
+ )
51
+
52
+ (
53
+ Q(person_isnull=False) | Q(person_isnull=True)
54
+ )
55
+ )
56
+
57
+ person_id = self.request.query_params.getlist("person_ids", [])
58
+
59
+ if person_id:
60
+ query &= Q(person__id__in=person_id)
61
+
62
+ if client_app_id:
63
+ query &= Q(client_app__id=client_app_id)
64
+
65
+ cost_center_id = self.request.query_params.getlist("cost_center", [])
66
+
67
+ if cost_center_id:
68
+ query &= Q(cost_center__id__in=cost_center_id)
69
+
70
+
71
+ if self.action == "list":
72
+ query_params = self.request.query_params
73
+
74
+ entry_type = self.validate_item_in_list(
75
+ item=query_params.get("tipo", False),
76
+ lista=dict(Entry.Type.TYPE).keys(),
77
+ message="Entry type invalid",
78
+ message_if_empty="Entry type required",
79
+ required=True,
80
+ )
81
+
82
+ initial_date, final_date = self.validar_periodo_datas(
83
+ initial_date=query_params.get("initial_date", False),
84
+ final_date=query_params.get("final_date", False),
85
+ )
86
+
87
+ query &= Q(
88
+ entry_type=entry_type, due_date__gte=initial_date, due_date__lte=final_date
89
+ )
90
+
91
+ cost_center = validate_natural_number(
92
+ numero=query_params.get("cost_center", False),
93
+ mensagem="Invalid Cost Center",
94
+ )
95
+
96
+ if cost_center:
97
+ query &= Q(cost_center_id=cost_center)
98
+
99
+ person = query_params.get("person", False)
100
+
101
+ if person:
102
+ person = person.split(" ")
103
+ query &= reduce(
104
+ operator.__and__,
105
+ (Q(person__name__unaccent__icontains=param) for param in person),
106
+ )
107
+
108
+ category = validate_natural_number(
109
+ number=query_params.get("category", False),
110
+ message="Inválid Category",
111
+ )
112
+
113
+ if category:
114
+ query &= Q(categoria_id=category)
115
+
116
+ account = validate_natural_number(
117
+ number=query_params.get("account", False), message="Invalid Account"
118
+ )
119
+
120
+ if account:
121
+ query &= Q(account_id=account)
122
+
123
+ return queryset.filter(query).order_by(
124
+ "due_date", "category", "description", "created_at", "id"
125
+ )
126
+
127
+ def list(self, request, *args, **kwargs):
128
+ if "values" not in request.query_params:
129
+ return super().list(request, *args, **kwargs)
130
+
131
+ serializer_data = EntrySerializer(
132
+ {"Entry": self.get_queryset()}, context={"request": request}
133
+ ).data
134
+
135
+ return Response(data=serializer_data["valores"])
136
+
137
+ def update(self, request, *args, **kwargs):
138
+ partial = kwargs.pop("partial", False)
139
+ instance = self.get_object()
140
+ recalculate_liquid_value = request.data.get("recalculate", False)
141
+ serializer = EntrySerializer(
142
+ instance,
143
+ data=request.data,
144
+ partial=partial,
145
+ context={"request": request, "recalculate": recalculate_liquid_value},
146
+ )
147
+ serializer.is_valid(raise_exception=True)
148
+ self.perform_update(serializer)
149
+
150
+ if getattr(instance, "_prefetched_objects_cache", None):
151
+ instance._prefetched_objects_cache = {}
152
+
153
+ return Response(serializer.data)
154
+
155
+ def destroy(self, request, *args, **kwargs):
156
+ instance = self.get_object()
157
+
158
+ if Entry.objects.filter(reference_record=instance).count() > 1:
159
+ return Response(
160
+ {"message": "Payment deletion requires confirmation."},
161
+ ),
162
+
163
+
164
+ instance.reference_record = None
165
+ instance.save()
166
+
167
+ self.perform_destroy(instance)
168
+
169
+ return Response(status=status.HTTP_204_NO_CONTENT)
170
+
171
+ @Action(methods=["GET"], detail=True, url_path="payments")
172
+ def list_payments(self, request, pk=None):
173
+ entry = self.get_object()
174
+
175
+ if entry.reference_record:
176
+ payments = Entry.objects.filter(
177
+ reference_record=entry.reference_record
178
+ ).order_by("id")
179
+ else:
180
+ payments = Entry.objects.filter(id=entry.id)
181
+
182
+
183
+ page = self.paginate_queryset(payments)
184
+ serializer = self.get_serializer(page, many=True)
185
+
186
+ return self.get_paginated_response(serializer.data)
187
+
188
+
189
+
190
+ @Action(methods=["DELETE"], detail=True, url_path="confirm_payment")
191
+ def confirm_payment_deletion(self, request, pk=None):
192
+ entry = self.get_object()
193
+
194
+ payments = Entry.objects.filter(reference_record=entry).exclude(
195
+ pk=entry.pk
196
+ )
197
+
198
+ for payment in payments:
199
+ self.perform_destroy(payment)
200
+
201
+ entry.reference_record = None
202
+ entry.save()
203
+
204
+ self.perform_destroy(entry)
205
+
206
+ return Response()
@@ -0,0 +1,56 @@
1
+ import operator
2
+ from functools import reduce
3
+ from rest_framework import viewsets
4
+ from rest_framework.views import APIView
5
+ from django.http.response import Http404, HttpResponse
6
+ from rest_framework.response import Response
7
+
8
+ from django.db.models.query_utils import Q
9
+
10
+ from models.payment import PaymentMethod, PaymentMethodTaxs
11
+ from serializers.payments import PaymentMethodSerializer, PaymentMethodTaxsSerializer
12
+
13
+
14
+ class PaymentMethodViewSet(viewsets.ModelViewSet):
15
+
16
+ serializer_class = PaymentMethodSerializer
17
+ queryset = PaymentMethod.objects.all()
18
+
19
+ def get_queryset(self):
20
+ queryset = super().get_queryset()
21
+
22
+ query = Q(deactivate=False)
23
+
24
+ if self.action == "list":
25
+ name = str(self.request.query_params.get("name", "")).split(" ")
26
+
27
+ if name != "":
28
+ query &= reduce(
29
+ operator.__and__,
30
+ (Q(name__unaccent__icontains=word) for word in name),
31
+ )
32
+
33
+ return queryset.filter(query).order_by("name")
34
+
35
+
36
+ class ListPaymentMethodTaxs(viewsets.ModelViewSet):
37
+
38
+ serializer_class = PaymentMethodTaxsSerializer
39
+ queryset = PaymentMethodTaxs.objects.all()
40
+
41
+ def get_queryset(self):
42
+ queryset = super().get_queryset()
43
+
44
+ query = Q(deactivate=False)
45
+
46
+ if self.action == "list":
47
+ tax = str(self.request.query_params.get("tax", "")).split(" ")
48
+
49
+ if tax != "":
50
+ query &= reduce(
51
+ operator.__and__,
52
+ (Q(tax__icontains=word) for word in tax),
53
+ )
54
+
55
+ return queryset.filter(query).order_by("initial_date")
56
+
@@ -0,0 +1,23 @@
1
+ Metadata-Version: 2.4
2
+ Name: finance_sdk
3
+ Version: 1.0.3
4
+ Summary: SDK for Finance Module
5
+ Home-page: https://github.com/wlc-solucoes/wlc-sdk-financeiro.git
6
+ Author: WLC Soluções
7
+ Author-email: analiciasouza.11@gmail.com
8
+ Classifier: Environment :: Web Environment
9
+ Classifier: Framework :: Django
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python
12
+ Requires-Dist: django
13
+ Requires-Dist: djangorestframework
14
+ Dynamic: author
15
+ Dynamic: author-email
16
+ Dynamic: classifier
17
+ Dynamic: home-page
18
+ Dynamic: requires-dist
19
+ Dynamic: summary
20
+
21
+ # SDK Financeiro - WLC Soluções
22
+
23
+
@@ -0,0 +1,31 @@
1
+ finance_sdk/__init__.py,sha256=Gzuvw8Ow_dRgrZIJptCgRtdYkXj-2sqilDbIlIxdHK8,78
2
+ finance_sdk/admin.py,sha256=suMo4x8I3JBxAFBVIdE-5qnqZ6JAZV0FESABHOSc-vg,63
3
+ finance_sdk/apps.py,sha256=UA4iSvwSqXkM9Dwlr3O8vO6AX8z3hwAQ9W5TnBGPMvE,153
4
+ finance_sdk/enums.py,sha256=V-Cn2r4KGoqxW35iK-_T_ve5KSxg2fJromIhcW-G2Dw,1176
5
+ finance_sdk/tests.py,sha256=mrbGGRNg5jwbTJtWWa7zSKdDyeB4vmgZCRc2nk6VY-g,60
6
+ finance_sdk/utils.py,sha256=zgZPMmxXeN9dAYPYvL4a3LECTeR7WFfVz1T0RZF3m44,1594
7
+ finance_sdk/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ finance_sdk/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ finance_sdk/models/accounts.py,sha256=E41hh6yjrRpwfPtIwqGUZpC-q6ZxxS0MdwPrEyjGidI,1417
10
+ finance_sdk/models/bank.py,sha256=NHI1Dxd6VcxbKC2WeaLA5qG4BRlOY5oU7oqGzHArYyY,397
11
+ finance_sdk/models/category.py,sha256=FwUBQ2aDedyytfX6GOFKynM4N_u45qcwCm4_oAoBfu0,669
12
+ finance_sdk/models/entry.py,sha256=hDGeXDgyuJNhrgY3jUN4hPs5txhSxGqE-2NmzucKpKA,2153
13
+ finance_sdk/models/payment.py,sha256=4-5cHpYvor3mzSORfJ1SIyv_yeaK5LJYLtQb_vi9EuA,995
14
+ finance_sdk/serializers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
+ finance_sdk/serializers/accounts.py,sha256=JpWDwOQ4Ii08iYHd8TTPZjyFkS8PguIRfnT6KGL3oZw,1325
16
+ finance_sdk/serializers/bank.py,sha256=toIYBVwwoGv8BXbcTHI5DhVrsHtrRoIgGjcSQ14FJ7o,596
17
+ finance_sdk/serializers/category.py,sha256=ahx5wpHqvtYdVtFUDgUK_CrPyGEWDm_guP_7lH4VlvE,1023
18
+ finance_sdk/serializers/entry.py,sha256=lheWYdzhAa4WyZByGMxuvCKZMYP5y9vWZDwJEWngtq0,4665
19
+ finance_sdk/serializers/payments.py,sha256=ODmxwTzsmjsZ7ZFqCkS5MFniLDJRumXdI7mAf7CCUg4,2643
20
+ finance_sdk/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
+ finance_sdk/services/entriesService.py,sha256=esQ7F-wJ1SLRzoooIJKadX_gQvvlOpiTaD7oz3Wy2KY,3504
22
+ finance_sdk/views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
+ finance_sdk/views/account.py,sha256=ptpnONCxRtCGMS2hGfo9WOQTqzSSY2ybHcAsVZKSkfg,1461
24
+ finance_sdk/views/bank.py,sha256=lrYVFSatTBEztW3HFbkMSYwMW5sJVwOqIyk_R6gxF64,824
25
+ finance_sdk/views/category.py,sha256=GGVZaRsxGz3y4urbCizIcmvZXVedndrF9rbsiyI6bpk,1003
26
+ finance_sdk/views/entry.py,sha256=pIuCiLiW0Kz_-9qDVn4XmeSAQlSoa0K4oxGUa9Jwer0,6420
27
+ finance_sdk/views/payment.py,sha256=lECY1E0tGguDZqjJ6xrGvCY-osGy3FR9RAgzz6QdupM,1646
28
+ finance_sdk-1.0.3.dist-info/METADATA,sha256=ae5-wb_vHXpL37nW8wY_ZVxNdbh6UG4_rqNTuLT8aq8,590
29
+ finance_sdk-1.0.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
30
+ finance_sdk-1.0.3.dist-info/top_level.txt,sha256=VghHbEzVbFaLJhFhyllLz1gaRt6DXhz_oBMN204-cNY,12
31
+ finance_sdk-1.0.3.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ finance_sdk