-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* generate new nr number * bug fix * _generate_nr_num
- Loading branch information
Showing
7 changed files
with
173 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
api/migrations/versions/6be595afb9ba_add_nr_num_lifespan_and_nr_num_exclude_.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
"""Add nr_num_lifespan and nr_num_exclude tables | ||
Revision ID: 6be595afb9ba | ||
Revises: e7c2ca8b223a | ||
Create Date: 2024-07-03 14:09:17.896835 | ||
""" | ||
from alembic import op | ||
import sqlalchemy as sa | ||
from sqlalchemy.dialects import postgresql | ||
|
||
# revision identifiers, used by Alembic. | ||
revision = '6be595afb9ba' | ||
down_revision = 'e7c2ca8b223a' | ||
branch_labels = None | ||
depends_on = None | ||
|
||
|
||
def upgrade(): | ||
op.create_table('nr_number_exclude', | ||
sa.Column('nr_num', sa.String(length=10), nullable=False), | ||
sa.PrimaryKeyConstraint('nr_num') | ||
) | ||
op.create_table('nr_number_lifespan', | ||
sa.Column('nr_num', sa.String(length=10), nullable=False), | ||
sa.Column('nr_timestamp', sa.DateTime(timezone=True), nullable=True), | ||
sa.PrimaryKeyConstraint('nr_num') | ||
) | ||
|
||
|
||
def downgrade(): | ||
op.drop_table('nr_number_lifespan') | ||
op.drop_table('nr_number_exclude') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
from . import db, ma | ||
|
||
|
||
class NRNumberExclude(db.Model): | ||
__tablename__ = 'nr_number_exclude' | ||
nr_num = db.Column(db.String(10), primary_key=True) | ||
|
||
@classmethod | ||
def check_nr_num_exclude(cls, nr_num): | ||
return db.session.query(db.exists().where(cls.nr_num == nr_num)).scalar() | ||
|
||
def json(self): | ||
return {'nr_num': self.nr_num} | ||
|
||
def save_to_db(self): | ||
db.session.add(self) | ||
db.session.commit() | ||
|
||
|
||
class NRNumberExcludeSchema(ma.SQLAlchemySchema): | ||
class Meta: | ||
model = NRNumberExclude |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
from datetime import datetime, timedelta | ||
from . import db, ma | ||
|
||
|
||
class NRNumberLifespan(db.Model): | ||
__tablename__ = 'nr_number_lifespan' | ||
nr_num = db.Column(db.String(10), primary_key=True) | ||
nr_timestamp = db.Column(db.DateTime(timezone=True), default=datetime.utcnow) | ||
|
||
@classmethod | ||
def check_nr_num_lifespan(cls, nr_num): | ||
return db.session.query(db.exists().where(cls.nr_num == nr_num)).scalar() | ||
|
||
@classmethod | ||
def insert_nr_num(cls, nr_num): | ||
entry = cls(nr_num=nr_num) | ||
db.session.add(entry) | ||
db.session.commit() | ||
|
||
@classmethod | ||
def delete_old_entries(cls, lifespan_seconds): | ||
expiration_time = datetime.utcnow() - timedelta(seconds=lifespan_seconds) | ||
db.session.query(cls).filter(cls.nr_timestamp < expiration_time).delete() | ||
db.session.commit() | ||
|
||
def json(self): | ||
return {'nr_num': self.nr_num, 'nr_timestamp': self.nr_timestamp} | ||
|
||
def save_to_db(self): | ||
db.session.add(self) | ||
db.session.commit() | ||
|
||
|
||
class NRNumberLifespanSchema(ma.SQLAlchemySchema): | ||
class Meta: | ||
model = NRNumberLifespan |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
from flask import current_app | ||
from namex.models import NRNumberLifespan, NRNumberExclude, Request | ||
|
||
import random | ||
import logging | ||
|
||
|
||
def set_nr_num_lifespan(nr_num, span): | ||
"""Set the lifespan of a number by deleting old entries and inserting the new one.""" | ||
NRNumberLifespan.delete_old_entries(span) | ||
if NRNumberLifespan.check_nr_num_lifespan(nr_num): | ||
return False | ||
NRNumberLifespan.insert_nr_num(nr_num) | ||
return True | ||
|
||
|
||
def check_nr_num_exists(nr_num): | ||
"""Check if a number exists in the NRNumber table.""" | ||
return bool(Request.find_by_nr(nr_num)) | ||
|
||
|
||
def check_nr_num_exclude(nr_num): | ||
"""Check if a number exists in the NRNumExclude table.""" | ||
return NRNumberExclude.check_nr_num_exclude(nr_num) | ||
|
||
|
||
class NRNumberService: | ||
""" | ||
Service class for handling operations related to NR numbers. | ||
This class provides methods for generating new NR numbers, | ||
ensuring they are unique and valid within a specified lifespan. | ||
""" | ||
|
||
@classmethod | ||
def get_new_nr_num(cls): | ||
""" | ||
Generate a new NR number that is unique and within the specified lifespan. | ||
Returns: | ||
str: A new unique NR number. | ||
""" | ||
try: | ||
floor = 1 # assumed there is no NR 0000000 | ||
ceiling = 9999999 | ||
attempts = 100000000 | ||
count = 0 | ||
|
||
span = current_app.config.get('NR_NUM_LIFESPAN') | ||
|
||
while count < attempts: | ||
random_num = random.randint(floor, ceiling) | ||
nr_num = f'NR {str(random_num).zfill(7)}' | ||
count += 1 | ||
|
||
if not set_nr_num_lifespan(nr_num, span): | ||
continue | ||
|
||
if check_nr_num_exists(nr_num): | ||
continue | ||
|
||
if check_nr_num_exclude(nr_num): | ||
continue | ||
|
||
return nr_num | ||
|
||
raise Exception( | ||
f'Unable to generate random number from range {floor} to {ceiling} after {count} attempts.' | ||
) | ||
except Exception as e: | ||
logging.error(f'Exception in get_new_nr_num; {str(e)}') | ||
raise |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters