Base logging setup
Models for products/services/billables
This commit is contained in:
parent
b3ebe1f101
commit
95c9748dc2
8 changed files with 165 additions and 5 deletions
21
core/classes/products.py
Normal file
21
core/classes/products.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
class BaseProductHandler:
|
||||
def __init__(self, product_id):
|
||||
self.product_id = product_id
|
||||
|
||||
@property
|
||||
def is_creatable(self):
|
||||
'''Returns True if this product can be created right now, or False if it cannot. Should return True if the module is correctly configured, the product is in stock (if physical), etc.'''
|
||||
return False
|
||||
|
||||
@property
|
||||
def setup_view(self):
|
||||
'''Returns a view in which the product can be configured, or None if no configuration is possible/necessary.'''
|
||||
return None
|
||||
|
||||
class FallbackProductHandler(BaseProductHandler):
|
||||
pass
|
||||
|
||||
class CoreProductHandler(BaseProductHandler):
|
||||
pass
|
||||
|
||||
ProductHandler = CoreProductHandler
|
|
@ -2,4 +2,7 @@ from core.models.files import *
|
|||
from core.models.profiles import *
|
||||
from core.models.auth import *
|
||||
from core.models.local import *
|
||||
from core.models.cron import *
|
||||
from core.models.cron import *
|
||||
from core.models.products import *
|
||||
from core.models.billable import *
|
||||
from core.models.services import *
|
10
core/models/billable.py
Normal file
10
core/models/billable.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
from django.db.models import IntegerChoices, Model
|
||||
|
||||
class CycleChoices(IntegerChoices):
|
||||
DAYS = 0, "Days"
|
||||
WEEKS = 1, "Weeks"
|
||||
MONTHS = 2, "Months"
|
||||
YEARS = 3, "Years"
|
||||
|
||||
class Billable(Model):
|
||||
pass
|
37
core/models/products.py
Normal file
37
core/models/products.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
from core.models.billable import CycleChoices
|
||||
|
||||
from django.db.models import Model, IntegerChoices, PositiveIntegerField, DecimalField, ForeignKey, CASCADE, CharField, TextField, ManyToManyField
|
||||
|
||||
from importlib import import_module
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class ProductGroup(Model):
|
||||
name = CharField(max_length=255)
|
||||
|
||||
class Product(Model):
|
||||
name = CharField(max_length=255)
|
||||
description = TextField(null=True, blank=True)
|
||||
handler_module = CharField(max_length=255, null=True, blank=True)
|
||||
product_groups = ManyToManyField(ProductGroup)
|
||||
|
||||
@property
|
||||
def handler(self):
|
||||
if self.handler_module:
|
||||
try:
|
||||
handler_module = import_module(self.handler_module)
|
||||
return handler_module.ProductRouter(self.id)
|
||||
except Exception as e:
|
||||
logger.error(f"Could not load product handler {self.handler_module} for product {self.id}: {e}")
|
||||
return None
|
||||
|
||||
class ProductPlan(Model):
|
||||
product = ForeignKey(Product, on_delete=CASCADE)
|
||||
|
||||
class ProductPlanItem(Model):
|
||||
plan = ForeignKey(ProductPlan, on_delete=CASCADE)
|
||||
cycle = PositiveIntegerField(choices=CycleChoices.choices)
|
||||
count = PositiveIntegerField()
|
||||
cost = DecimalField(max_digits=30, decimal_places=2)
|
41
core/models/services.py
Normal file
41
core/models/services.py
Normal file
|
@ -0,0 +1,41 @@
|
|||
from core.models.billable import CycleChoices
|
||||
from core.models.products import ProductGroup
|
||||
|
||||
from django.db.models import Model, TextField, CharField, ManyToManyField, ForeignKey, CASCADE, PositiveIntegerField, DecimalField, OneToOneField
|
||||
|
||||
from importlib import import_module
|
||||
from logging import getLogger
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
class Service(Model):
|
||||
name = CharField(max_length=255)
|
||||
description = TextField(null=True, blank=True)
|
||||
handler_module = CharField(max_length=255, null=True, blank=True)
|
||||
product_groups = ManyToManyField(ProductGroup)
|
||||
|
||||
@property
|
||||
def handler(self):
|
||||
if self.handler_module:
|
||||
try:
|
||||
handler_module = import_module(self.handler_module)
|
||||
return handler_module.ProductRouter(self.id)
|
||||
except Exception as e:
|
||||
logger.error(f"Could not load product handler {self.handler_module} for product {self.id}: {e}")
|
||||
return None
|
||||
|
||||
class ServicePlan(Model):
|
||||
service = OneToOneField(Service, on_delete=CASCADE)
|
||||
|
||||
@classmethod
|
||||
def from_productplan(cls, productplan, service):
|
||||
plan = cls.objects.create(service=service)
|
||||
|
||||
for item in productplan.serviceplanitem_set:
|
||||
ServicePlanItem.objects.create(plan=plan, cycle=item.cycle, count=item.count, cost=item.cost)
|
||||
|
||||
class ServicePlanItem(Model):
|
||||
plan = ForeignKey(ServicePlan, on_delete=CASCADE)
|
||||
cycle = PositiveIntegerField(choices=CycleChoices.choices)
|
||||
count = PositiveIntegerField()
|
||||
cost = DecimalField(max_digits=30, decimal_places=2)
|
|
@ -1,7 +1,8 @@
|
|||
from celery import shared_task, task
|
||||
from celery.utils.log import get_task_logger
|
||||
|
||||
logger = get_task_logger(__name__)
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@task(name="cron")
|
||||
def process_crons():
|
||||
|
@ -16,7 +17,7 @@ def run_cron(name, *args, **kwargs):
|
|||
from core.modules.cron import cronfunctions
|
||||
|
||||
log = CronLog.objects.create(task=name)
|
||||
|
||||
|
||||
try:
|
||||
output = cronfunctions[name]()
|
||||
if output:
|
||||
|
|
|
@ -49,4 +49,8 @@ MEMCACHED_LOCATION = ["127.0.0.1:11211"]
|
|||
RABBITMQ_LOCATION = "127.0.0.1:5672"
|
||||
RABBITMQ_VHOST = ""
|
||||
RABBITMQ_USER = "guest"
|
||||
RABBITMQ_PASS = "guest"
|
||||
RABBITMQ_PASS = "guest"
|
||||
|
||||
# Logging
|
||||
|
||||
LOG_DIRECTORY = "/var/log/expephalon/"
|
|
@ -155,3 +155,46 @@ CELERY_TASK_RESULT_EXPIRES = 12 * 60 * 60
|
|||
LOGIN_REDIRECT_URL = reverse_lazy('dashboard')
|
||||
LOGIN_URL = reverse_lazy('login')
|
||||
LOGOUT_URL = reverse_lazy('logout')
|
||||
|
||||
# Logging
|
||||
|
||||
try:
|
||||
os.makedirs(LOG_DIRECTORY, exist_ok=True)
|
||||
except:
|
||||
raise Exception(f"Could not create log directory {LOG_DIRECTORY}, please create it manually and make sure the Expephalon user account has sufficient privileges to write to it.")
|
||||
|
||||
try:
|
||||
with open(os.path.join(LOG_DIRECTORY, "expephalon.log"), "a") as logfile:
|
||||
logfile.write("\n----------\n")
|
||||
except:
|
||||
raise Exception(f"Unable to write to log file {os.path.join(LOG_DIRECTORY, 'expephalon.log')}, please make sure the Expephalon user account has sufficient privileges to write to the {LOG_DIRECTORY} directory and all files within it.")
|
||||
|
||||
LOGGING = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': False,
|
||||
'formatters': {
|
||||
'verbose': {
|
||||
'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
|
||||
},
|
||||
'simple': {
|
||||
'format': '%(levelname)s %(message)s'
|
||||
},
|
||||
},
|
||||
'handlers': {
|
||||
'expephalon': {
|
||||
'level': 'DEBUG',
|
||||
'class': 'logging.handlers.TimedRotatingFileHandler',
|
||||
'filename': os.path.join(LOG_DIRECTORY, 'expephalon.log'),
|
||||
'when': 'midnight',
|
||||
'backupCount': 10,
|
||||
'formatter': 'verbose',
|
||||
},
|
||||
},
|
||||
'loggers': {
|
||||
'': {
|
||||
'handlers': ['expephalon'],
|
||||
'level': 'DEBUG',
|
||||
'propagate': False,
|
||||
},
|
||||
},
|
||||
}
|
Loading…
Reference in a new issue