refactoring

This commit is contained in:
Paul J Stevens 2024-01-13 21:36:20 +01:00
parent 2a27949cfd
commit c992fed3e6
7 changed files with 239 additions and 32 deletions

14
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,14 @@
# File format: https://pre-commit.com/#plugins
# Supported hooks: https://pre-commit.com/hooks.html
# Running "make format" fixes most issues for you
repos:
- repo: https://github.com/ambv/black
rev: 23.12.1
hooks:
- id: black
exclude: ^.*\b(migrations)\b.*$
- repo: https://github.com/charliermarsh/ruff-pre-commit
# Ruff version.
rev: "v0.1.13"
hooks:
- id: ruff

View File

@ -6,6 +6,7 @@ DBNAME=bij1
install:
pdm install -d
pre-commit install
setup:
TRYTOND_DATABASE_URI=postgresql://localhost/$(DBNAME) trytond-admin -d $(DBNAME) --all --verbose
@ -13,8 +14,11 @@ setup:
run:
supervisord
configure:
bin/bij1_setup
sync:
bin/airtable -c etc/dev.ini -d $(DBNAME)
bin/bij1_airtable
frontend: frontend/package.json
make -C frontend

View File

@ -24,7 +24,7 @@ stopasgroup=true
redirect_stderr=true
[program:api]
command=uvicorn bij1.api.main:app --reload --port 5000
command=uvicorn bij1.api.main:app --reload-dir=%(ENV_PWD)s/src/ --port 5000
stopasgroup=true
redirect_stderr=true

128
pdm.lock
View File

@ -5,7 +5,7 @@
groups = ["default", "dev"]
strategy = ["cross_platform", "inherit_metadata"]
lock_version = "4.4.1"
content_hash = "sha256:7505f6c4957e308846e2f5aa7d93c6569ae440f1e934f4e370578ead99fce95a"
content_hash = "sha256:0a53b25a34df010604c4713ea2e930d7689fdf1959140aeefd5550c0a9511c4e"
[[package]]
name = "annotated-types"
@ -44,6 +44,17 @@ files = [
{file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"},
]
[[package]]
name = "cfgv"
version = "3.4.0"
requires_python = ">=3.8"
summary = "Validate configuration and produce human readable error messages."
groups = ["default"]
files = [
{file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"},
{file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"},
]
[[package]]
name = "charset-normalizer"
version = "3.3.2"
@ -122,6 +133,16 @@ files = [
{file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"},
]
[[package]]
name = "distlib"
version = "0.3.8"
summary = "Distribution utilities"
groups = ["default"]
files = [
{file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"},
{file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"},
]
[[package]]
name = "factory-boy"
version = "3.3.0"
@ -181,6 +202,17 @@ files = [
{file = "fastapi-0.108.0.tar.gz", hash = "sha256:5056e504ac6395bf68493d71fcfc5352fdbd5fda6f88c21f6420d80d81163296"},
]
[[package]]
name = "filelock"
version = "3.13.1"
requires_python = ">=3.8"
summary = "A platform independent file lock."
groups = ["default"]
files = [
{file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"},
{file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"},
]
[[package]]
name = "genshi"
version = "0.7.7"
@ -219,6 +251,17 @@ files = [
{file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
]
[[package]]
name = "identify"
version = "2.5.33"
requires_python = ">=3.8"
summary = "File identification library for Python"
groups = ["default"]
files = [
{file = "identify-2.5.33-py2.py3-none-any.whl", hash = "sha256:d40ce5fcd762817627670da8a7d8d8e65f24342d14539c59488dc603bf662e34"},
{file = "identify-2.5.33.tar.gz", hash = "sha256:161558f9fe4559e1557e1bff323e8631f6a0e4837f7497767c1782832f16b62d"},
]
[[package]]
name = "idna"
version = "3.6"
@ -347,6 +390,20 @@ files = [
{file = "marshmallow-3.20.1.tar.gz", hash = "sha256:5d2371bbe42000f2b3fb5eaa065224df7d8f8597bc19a1bbfa5bfe7fba8da889"},
]
[[package]]
name = "nodeenv"
version = "1.8.0"
requires_python = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*"
summary = "Node.js virtual environment builder"
groups = ["default"]
dependencies = [
"setuptools",
]
files = [
{file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"},
{file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"},
]
[[package]]
name = "packaging"
version = "23.2"
@ -368,6 +425,17 @@ files = [
{file = "passlib-1.7.4.tar.gz", hash = "sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04"},
]
[[package]]
name = "platformdirs"
version = "4.1.0"
requires_python = ">=3.8"
summary = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
groups = ["default"]
files = [
{file = "platformdirs-4.1.0-py3-none-any.whl", hash = "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380"},
{file = "platformdirs-4.1.0.tar.gz", hash = "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420"},
]
[[package]]
name = "pluggy"
version = "1.3.0"
@ -389,6 +457,24 @@ files = [
{file = "polib-1.2.0.tar.gz", hash = "sha256:f3ef94aefed6e183e342a8a269ae1fc4742ba193186ad76f175938621dbfc26b"},
]
[[package]]
name = "pre-commit"
version = "3.6.0"
requires_python = ">=3.9"
summary = "A framework for managing and maintaining multi-language pre-commit hooks."
groups = ["default"]
dependencies = [
"cfgv>=2.0.0",
"identify>=1.0.0",
"nodeenv>=0.11.1",
"pyyaml>=5.1",
"virtualenv>=20.10.0",
]
files = [
{file = "pre_commit-3.6.0-py2.py3-none-any.whl", hash = "sha256:c255039ef399049a5544b6ce13d135caba8f2c28c3b4033277a788f434308376"},
{file = "pre_commit-3.6.0.tar.gz", hash = "sha256:d30bad9abf165f7785c15a21a1f46da7d0677cb00ee7ff4c579fd38922efe15d"},
]
[[package]]
name = "proteus"
version = "6.8.1"
@ -609,6 +695,30 @@ files = [
{file = "python_stdnum-1.19-py2.py3-none-any.whl", hash = "sha256:1b5b401ad3f45b798b0317313b781a433f5d7a5ff2c9feb8054664f76f78644e"},
]
[[package]]
name = "pyyaml"
version = "6.0.1"
requires_python = ">=3.6"
summary = "YAML parser and emitter for Python"
groups = ["default"]
files = [
{file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
{file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"},
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
{file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"},
{file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
{file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
{file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
{file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
{file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
{file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"},
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
]
[[package]]
name = "relatorio"
version = "0.10.1"
@ -1180,6 +1290,22 @@ files = [
{file = "uvicorn-0.25.0.tar.gz", hash = "sha256:6dddbad1d7ee0f5140aba5ec138ddc9612c5109399903828b4874c9937f009c2"},
]
[[package]]
name = "virtualenv"
version = "20.25.0"
requires_python = ">=3.7"
summary = "Virtual Python Environment builder"
groups = ["default"]
dependencies = [
"distlib<1,>=0.3.7",
"filelock<4,>=3.12.2",
"platformdirs<5,>=3.9.1",
]
files = [
{file = "virtualenv-20.25.0-py3-none-any.whl", hash = "sha256:4238949c5ffe6876362d9c0180fc6c3a824a7b12b80604eeb8085f2ed7460de3"},
{file = "virtualenv-20.25.0.tar.gz", hash = "sha256:bf51c0d9c7dd63ea8e44086fa1e4fb1093a31e963b86959257378aef020e1f1b"},
]
[[package]]
name = "werkzeug"
version = "3.0.1"

View File

@ -24,13 +24,15 @@ dependencies = [
"uvicorn>=0.25.0",
"gunicorn>=21.2.0",
"supervisor>=4.2.5",
"pre-commit>=3.6.0",
]
requires-python = ">=3.11"
readme = "README.md"
license = {text = "Proprietary"}
[project.scripts]
airtable = "bij1.erp.airtable:airtable"
bij1_airtable = "bij1.erp.airtable:airtable"
bij1_setup = "bij1.erp.config:configure"
[tool.pdm]
package-dir = "src"

65
src/bij1/erp/config.py Normal file
View File

@ -0,0 +1,65 @@
from decimal import Decimal
from typing import Any
from trytond.transaction import Transaction
from bij1.erp import pool
__all__ = ["config"]
COMPANY_NAME = "BIJ1"
CURRENCY_CODE = "EUR"
CURRENCY_SYMBOL = ""
SUBSCRIPTION_DESCRIPTION = f"Lidmaatschap {COMPANY_NAME}"
class CONFIG:
company: Any
currency: Any
subscription_description: str = SUBSCRIPTION_DESCRIPTION
def __init__(self):
with Transaction().start(pool.database_name, 0):
self._company()
self._currency()
def _party(self):
Party = pool.get("party.party")
if not (party := Party.search([("name", "=", COMPANY_NAME)])):
party = Party()
party.name = COMPANY_NAME
party.save()
else:
party = party[0]
return party
def _company(self):
Company = pool.get("company.company")
if not (company := Company.search([("party.name", "=", COMPANY_NAME)])):
company = Company()
company.party = self._party()
company.save()
else:
company = company[0]
self.company = company
def _currency(self):
Currency = pool.get("currency.currency")
if not (currency := Currency.search([("code", "=", "EUR")])):
currency = Currency()
currency.rounding = Decimal("0.01")
currency.digits = 2
else:
currency = currency[0]
currency.code = CURRENCY_CODE
currency.symbol = CURRENCY_SYMBOL
currency.save()
self.currency = currency
config = CONFIG()
def configure():
pass

View File

@ -5,6 +5,7 @@ from decimal import Decimal
import typing
import logging
from bij1.erp import pool
from bij1.erp.config import config
logger = logging.getLogger(__name__)
@ -42,8 +43,6 @@ class Member:
def save_party(self):
Party = pool.get("party.party")
Company = pool.get("company.company")
self.company = Company.search([])[0]
if not (obj := Party.search([("name", "=", self.name)])):
obj = Party()
obj.name = self.name
@ -61,6 +60,7 @@ class Member:
address.street = self.address
address.postal_code = self.postcode
address.city = self.city
address.invoice = True
address.save()
def save_email(self):
@ -150,7 +150,7 @@ class Member:
if not (self.iban and self.mandate):
return
Mandate = pool.get("account.payment.sepa.mandate")
if Mandate.search([('identification', '=', self.mandate)]):
if Mandate.search([("identification", "=", self.mandate)]):
return
BankAccount = pool.get("bank.account")
@ -167,7 +167,7 @@ class Member:
account_number = bank_account.numbers[0]
mandate = Mandate()
mandate.identification = self.mandate
mandate.company = self.company
mandate.company = config.company
mandate.account_number = account_number
mandate.party = self.party
mandate.signature_date = self.since
@ -176,45 +176,41 @@ class Member:
def save_subscription(self):
if not self.period:
return
Currency = pool.get('currency.currency')
currency, = Currency.search([('code', '=', 'EUR')])
Subscription = pool.get('sale.subscription')
SubscriptionLine = pool.get('sale.subscription.line')
SubscriptionService = pool.get('sale.subscription.service')
services = SubscriptionService.search([('active', '=', True)])
Subscription = pool.get("sale.subscription")
SubscriptionLine = pool.get("sale.subscription.line")
SubscriptionService = pool.get("sale.subscription.service")
services = SubscriptionService.search([("active", "=", True)])
services = {x.consumption_recurrence.name: x for x in services}
if not (subscription := Subscription.search(['party', '=', self.party])):
if not (service := services.get(self.period.lower())):
raise Exception("unkown period: %s" % self.period)
if not (subscription := Subscription.search(["party", "=", self.party])):
subscription = Subscription()
subscription.company = self.company
subscription.company = config.company
subscription.party = self.party
subscription.currency = currency
subscription.currency = config.currency
subscription.start_date = self.since
subscription.invoice_start_date = date(2024,1,1)
subscription.invoice_start_date = date(2024, 1, 1)
subscription.invoice_address = self.party.addresses[0]
subscription.invoice_recurrence = service.consumption_recurrence
else:
subscription = subscription[0]
subscription.description = "Lidmaatschap BIJ1"
if not subscription.invoice_address:
subscription.invoice_address = self.party.addresses[0]
service = services.get(self.period.lower())
if not service:
raise Exception("unkown period: %s" % self.period)
subscription.invoice_recurrence = service.consumption_recurrence
subscription.description = config.subscription_description
subscription.save()
if not (line := SubscriptionLine.search([
('subscription', '=', subscription),
('service', '=', service)
])):
if not (
line := SubscriptionLine.search(
[("subscription", "=", subscription), ("service", "=", service)]
)
):
line = SubscriptionLine()
line.service = service
line.subscription = subscription
line.quantity = 1
line.unit_price = self.amount
line.start_date = max([self.since, date(2024,1,1)])
line.start_date = max([self.since, date(2024, 1, 1)])
line.unit = service.product.default_uom
line.save()