Attendance Done!!
Changed the datatype of dates in attendance and employee to date from datetime this might bork things in other places
This commit is contained in:
parent
0a79b1acbb
commit
bd05e6bb17
alembic
brewman
core
models
routers
schemas
overlord/src/app
@ -50,6 +50,7 @@ def run_migrations_offline():
|
||||
target_metadata=target_metadata,
|
||||
literal_binds=True,
|
||||
dialect_opts={"paramstyle": "named"},
|
||||
compare_type=True
|
||||
)
|
||||
|
||||
with context.begin_transaction():
|
||||
@ -73,7 +74,8 @@ def run_migrations_online():
|
||||
|
||||
with connectable.connect() as connection:
|
||||
context.configure(
|
||||
connection=connection, target_metadata=target_metadata
|
||||
connection=connection, target_metadata=target_metadata,
|
||||
compare_type=True
|
||||
)
|
||||
|
||||
with context.begin_transaction():
|
||||
|
54
alembic/versions/03ea3e9cb1e5_rename_further.py
Normal file
54
alembic/versions/03ea3e9cb1e5_rename_further.py
Normal file
@ -0,0 +1,54 @@
|
||||
"""test
|
||||
|
||||
Revision ID: 03ea3e9cb1e5
|
||||
Revises: 5498fc4bf58d
|
||||
Create Date: 2020-05-14 21:25:08.945280
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '03ea3e9cb1e5'
|
||||
down_revision = '5498fc4bf58d'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table("attendances") as batch_op:
|
||||
batch_op.alter_column('date', type_=sa.Date(), nullable=False)
|
||||
with op.batch_alter_table("employees") as batch_op:
|
||||
batch_op.alter_column('Designation', new_column_name='designation', nullable=False)
|
||||
batch_op.alter_column('Salary', new_column_name='salary', nullable=False)
|
||||
batch_op.alter_column('ServicePoints', new_column_name='points', nullable=False)
|
||||
batch_op.alter_column('JoiningDate', new_column_name='joining_date', type_=sa.Date(), nullable=False)
|
||||
batch_op.alter_column('LeavingDate', new_column_name='leaving_date', type_=sa.Date(), nullable=True)
|
||||
with op.batch_alter_table("settings") as batch_op:
|
||||
batch_op.alter_column('SettingID', new_column_name='id')
|
||||
batch_op.alter_column('Name', new_column_name='name')
|
||||
batch_op.alter_column('Data', new_column_name='data')
|
||||
op.create_unique_constraint(op.f('uq_settings_name'), 'settings', ['name'])
|
||||
op.drop_constraint('uq_settings_Name', 'settings', type_='unique')
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table("attendances") as batch_op:
|
||||
batch_op.alter_column('date', type_=sa.DateTime())
|
||||
with op.batch_alter_table("employees") as batch_op:
|
||||
batch_op.alter_column('designation', new_column_name='Designation', nullable=True)
|
||||
batch_op.alter_column('salary', new_column_name='Salary', nullable=True)
|
||||
batch_op.alter_column('points', new_column_name='ServicePoints', nullable=True)
|
||||
batch_op.alter_column('joining_date', new_column_name='JoiningDate', type_=sa.DateTime(), nullable=True)
|
||||
batch_op.alter_column('leaving_date', new_column_name='LeavingDate', type_=sa.DateTime(), nullable=True)
|
||||
with op.batch_alter_table("settings") as batch_op:
|
||||
batch_op.alter_column('id', new_column_name='SettingID')
|
||||
batch_op.alter_column('name', new_column_name='Name')
|
||||
batch_op.alter_column('data', new_column_name='Data')
|
||||
op.create_unique_constraint('uq_settings_Name', 'settings', ['name'])
|
||||
op.drop_constraint(op.f('uq_settings_name'), 'settings', type_='unique')
|
||||
# ### end Alembic commands ###
|
@ -7,7 +7,7 @@ def get_date(session) -> str:
|
||||
return session["date"]
|
||||
|
||||
|
||||
def set_date(session, date_):
|
||||
def set_date(date_, session):
|
||||
session["date"] = date_
|
||||
return session["date"]
|
||||
|
||||
|
@ -392,11 +392,11 @@ class Employee(AccountBase):
|
||||
__mapper_args__ = {"polymorphic_identity": "employees"}
|
||||
|
||||
id = Column("id", GUID(), ForeignKey(AccountBase.id), primary_key=True)
|
||||
designation = Column("Designation", Unicode(255))
|
||||
salary = Column("Salary", Integer)
|
||||
points = Column("ServicePoints", Numeric(precision=5, scale=2))
|
||||
joining_date = Column("JoiningDate", DateTime)
|
||||
leaving_date = Column("LeavingDate", DateTime)
|
||||
designation = Column("designation", Unicode(255), nullable=False)
|
||||
salary = Column("salary", Integer, nullable=False)
|
||||
points = Column("points", Numeric(precision=5, scale=2), nullable=False)
|
||||
joining_date = Column("joining_date", Date, nullable=False)
|
||||
leaving_date = Column("leaving_date", Date, nullable=True)
|
||||
|
||||
attendances = relationship(
|
||||
"Attendance", backref="employee", cascade=None, cascade_backrefs=False
|
||||
@ -562,9 +562,9 @@ class AccountType:
|
||||
class DbSetting(Base):
|
||||
__tablename__ = "settings"
|
||||
|
||||
id = Column("SettingID", GUID(), primary_key=True, default=uuid.uuid4)
|
||||
name = Column("Name", Unicode(255), unique=True, nullable=False)
|
||||
data = Column("Data", PickleType)
|
||||
id = Column("id", GUID(), primary_key=True, default=uuid.uuid4)
|
||||
name = Column("name", Unicode(255), unique=True, nullable=False)
|
||||
data = Column("data", PickleType)
|
||||
|
||||
def __init__(self, id=None, name=None, data=None):
|
||||
self.id = id
|
||||
|
@ -9,7 +9,7 @@ from sqlalchemy import (
|
||||
DateTime,
|
||||
Numeric,
|
||||
ForeignKey,
|
||||
UniqueConstraint,
|
||||
UniqueConstraint, Date,
|
||||
)
|
||||
from sqlalchemy.dialects.postgresql import BYTEA
|
||||
from sqlalchemy.ext.hybrid import hybrid_property
|
||||
@ -378,7 +378,7 @@ class Attendance(Base):
|
||||
|
||||
id = Column("id", GUID(), primary_key=True, default=uuid.uuid4)
|
||||
employee_id = Column("employee_id", GUID(), ForeignKey("employees.id"))
|
||||
date = Column("date", DateTime)
|
||||
date = Column("date", Date, nullable=False)
|
||||
attendance_type = Column("attendance_type", Integer)
|
||||
amount = Column("amount", Numeric)
|
||||
creation_date = Column("creation_date", DateTime(timezone=True))
|
||||
|
@ -1,15 +1,17 @@
|
||||
from typing import List
|
||||
from fastapi import APIRouter, Depends
|
||||
|
||||
from ..schemas.auth import UserToken
|
||||
from ..core.security import get_current_active_user as get_user
|
||||
import brewman.schemas.master as schemas
|
||||
from brewman.models.master import AccountType
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("")
|
||||
@router.get("", response_model=List[schemas.AccountType])
|
||||
def account_type_list(user: UserToken = Depends(get_user)):
|
||||
return [
|
||||
{"id": item.id, "name": item.name}
|
||||
schemas.AccountType(id=item.id, name=item.name)
|
||||
for item in AccountType.list()
|
||||
]
|
||||
|
@ -1,8 +1,9 @@
|
||||
import uuid
|
||||
from datetime import datetime, date, timedelta
|
||||
import traceback
|
||||
from datetime import datetime, date, timedelta, time
|
||||
|
||||
from fastapi import APIRouter, HTTPException, status, Depends, Security, Request
|
||||
from sqlalchemy import or_
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from sqlalchemy.orm import Session
|
||||
from ..schemas.auth import UserToken
|
||||
from ..core.security import get_current_active_user as get_user
|
||||
@ -10,7 +11,7 @@ from ..db.session import SessionLocal
|
||||
from ..models.master import Employee
|
||||
from ..models.voucher import Attendance
|
||||
from ..routers.fingerprint import get_prints
|
||||
from ..core.session import get_date
|
||||
from ..core.session import get_date, set_date
|
||||
import brewman.schemas.voucher as schemas
|
||||
|
||||
router = APIRouter()
|
||||
@ -26,26 +27,37 @@ def get_db() -> Session:
|
||||
|
||||
|
||||
@router.get("")
|
||||
def attendance_blank(request: Request, user: UserToken = Security(get_user, scopes=["attendance"])):
|
||||
def attendance_blank(
|
||||
request: Request, user: UserToken = Security(get_user, scopes=["attendance"])
|
||||
):
|
||||
return {"date": get_date(request.session), "body": []}
|
||||
|
||||
|
||||
@router.get("/{date_}")
|
||||
def attendance_date(
|
||||
date_: str,
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
user: UserToken = Security(get_user, scopes=["attendance"]),
|
||||
):
|
||||
return attendance_date_report(date_, db)
|
||||
set_date(date_, request.session)
|
||||
return {
|
||||
"date": date_,
|
||||
"body": attendance_date_report(datetime.strptime(date_, "%d-%b-%Y"), db),
|
||||
}
|
||||
|
||||
|
||||
def attendance_date_report(date_: str, db):
|
||||
report = {"date": date_, "body": []}
|
||||
date_ = datetime.strptime(date_, "%d-%b-%Y").date()
|
||||
def attendance_date_report(date_: date, db: Session):
|
||||
body = []
|
||||
employees = (
|
||||
db.query(Employee)
|
||||
.filter(Employee.joining_date <= date_)
|
||||
.filter(or_(Employee.is_active, Employee.leaving_date >= date_))
|
||||
.filter(
|
||||
or_(
|
||||
Employee.is_active,
|
||||
Employee.leaving_date >= date_,
|
||||
)
|
||||
)
|
||||
.order_by(Employee.cost_centre_id)
|
||||
.order_by(Employee.designation)
|
||||
.order_by(Employee.name)
|
||||
@ -55,50 +67,60 @@ def attendance_date_report(date_: str, db):
|
||||
att = (
|
||||
db.query(Attendance)
|
||||
.filter(Attendance.employee_id == item.id)
|
||||
.filter(Attendance.date == date)
|
||||
.filter(Attendance.date == date_)
|
||||
.filter(Attendance.is_valid == True)
|
||||
.first()
|
||||
)
|
||||
att = 0 if att is None else att.attendance_type
|
||||
|
||||
prints, hours, worked = get_prints(item.id, date, db)
|
||||
report["body"].append(
|
||||
{
|
||||
"id": item.id,
|
||||
"code": item.code,
|
||||
"name": item.name,
|
||||
"designation": item.designation,
|
||||
"department": item.cost_centre.name,
|
||||
"attendanceType": {"id": att},
|
||||
"prints": prints,
|
||||
"hours": hours,
|
||||
"worked": worked,
|
||||
}
|
||||
prints, hours_worked, full_day = get_prints(item.id, date_, db)
|
||||
body.append(
|
||||
schemas.AttendanceItem(
|
||||
id=item.id,
|
||||
code=item.code,
|
||||
name=item.name,
|
||||
designation=item.designation,
|
||||
department=item.cost_centre.name,
|
||||
attendanceType=schemas.AttendanceType(id=att),
|
||||
prints=prints,
|
||||
hoursWorked=hours_worked,
|
||||
fullDay=full_day,
|
||||
)
|
||||
return report
|
||||
)
|
||||
return body
|
||||
|
||||
|
||||
@router.post("/{date_}") # "Attendance"
|
||||
@router.post("/{date_}")
|
||||
def save(
|
||||
date_: str,
|
||||
data: schemas.AttendanceIn,
|
||||
db: Session = Depends(get_db),
|
||||
user: UserToken = Security(get_user, scopes=["attendance"]),
|
||||
):
|
||||
date_object = datetime.strptime(date_, "%d-%b-%Y").date()
|
||||
|
||||
try:
|
||||
att_date = datetime.strptime(date_, "%d-%b-%Y").date()
|
||||
for item in data.body:
|
||||
attendance_type = item.attendance_type.id_
|
||||
if attendance_type != 0:
|
||||
if item.attendance_type.id_ != 0:
|
||||
attendance = Attendance(
|
||||
employee_id=item.employee_id,
|
||||
date=date_object,
|
||||
attendance_type=attendance_type,
|
||||
employee_id=item.id_,
|
||||
date=att_date,
|
||||
attendance_type=item.attendance_type.id_,
|
||||
user_id=user.id_,
|
||||
)
|
||||
attendance.create(db)
|
||||
db.commit()
|
||||
return attendance_date_report(date_, db)
|
||||
return {"date": date_, "body": attendance_date_report(att_date, db)}
|
||||
except SQLAlchemyError as e:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e),
|
||||
)
|
||||
except Exception:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=traceback.format_exc(),
|
||||
)
|
||||
|
||||
|
||||
def date_range(start: date, stop: date, step=timedelta(days=1), inclusive=False):
|
||||
|
@ -1,12 +1,13 @@
|
||||
from brewman.models.master import AttendanceType, Employee
|
||||
|
||||
from fastapi import APIRouter
|
||||
from fastapi import APIRouter, Depends
|
||||
from ..schemas.auth import UserToken
|
||||
from ..core.security import get_current_active_user as get_user
|
||||
from brewman.models.master import AttendanceType
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/") # "Authenticated"
|
||||
def show_list(request):
|
||||
@router.get("")
|
||||
async def show_list(user: UserToken = Depends(get_user)):
|
||||
list_ = AttendanceType.list()
|
||||
attendance_types = []
|
||||
for item in list_:
|
||||
|
@ -1,11 +1,12 @@
|
||||
import csv
|
||||
import datetime
|
||||
from datetime import datetime, date, timedelta, time
|
||||
import uuid
|
||||
from io import StringIO
|
||||
|
||||
from sqlalchemy import bindparam, select, exists, and_
|
||||
from sqlalchemy.dialects.postgresql import insert as pg_insert
|
||||
# from zope.sqlalchemy import mark_changed
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from brewman.models.master import Employee
|
||||
from brewman.models.voucher import Fingerprint
|
||||
@ -117,14 +118,12 @@ def fp(file_data, employees):
|
||||
# return Fingerprint.__table__.insert().from_select([Fingerprint.id, Fingerprint.employee_id, Fingerprint.date], sel)
|
||||
|
||||
|
||||
def get_prints(employee_id, date, dbsession):
|
||||
start_fp = date + datetime.timedelta(hours=7)
|
||||
finish_fp = date + datetime.timedelta(hours=7, days=1)
|
||||
def get_prints(employee_id: uuid.UUID, date_: date, db: Session):
|
||||
prints = (
|
||||
dbsession.query(Fingerprint)
|
||||
db.query(Fingerprint)
|
||||
.filter(Fingerprint.employee_id == employee_id)
|
||||
.filter(Fingerprint.date >= start_fp)
|
||||
.filter(Fingerprint.date < finish_fp)
|
||||
.filter(Fingerprint.date >= datetime.combine(date_, time(hour=7)))
|
||||
.filter(Fingerprint.date < datetime.combine(date_ + timedelta(days=1), time(hour=7)))
|
||||
.order_by(Fingerprint.date)
|
||||
.all()
|
||||
)
|
||||
@ -132,31 +131,31 @@ def get_prints(employee_id, date, dbsession):
|
||||
last = None
|
||||
for i in range(len(prints), 0, -1):
|
||||
item = prints[i - 1].date
|
||||
if last is not None and last - item < datetime.timedelta(minutes=10):
|
||||
if last is not None and last - item < timedelta(minutes=10):
|
||||
prints.remove(prints[i - 1])
|
||||
else:
|
||||
last = item
|
||||
|
||||
if len(prints) == 0:
|
||||
hours = "", ""
|
||||
hours_worked, full_day = "", None
|
||||
elif len(prints) == 2:
|
||||
hours = prints[1].date - prints[0].date
|
||||
hours = working_hours(hours)
|
||||
time_worked = prints[1].date - prints[0].date
|
||||
hours_worked, full_day = working_hours(time_worked)
|
||||
elif len(prints) == 4:
|
||||
hours = (prints[1].date - prints[0].date) + (prints[3].date - prints[2].date)
|
||||
hours = working_hours(hours)
|
||||
time_worked = (prints[1].date - prints[0].date) + (prints[3].date - prints[2].date)
|
||||
hours_worked, full_day = working_hours(time_worked)
|
||||
else:
|
||||
hours = "Error", "Error"
|
||||
hours_worked, full_day = "Error", False
|
||||
return (
|
||||
", ".join([x.date.strftime("%H:%M") for x in prints]) + " ",
|
||||
hours[0],
|
||||
hours[1],
|
||||
hours_worked,
|
||||
full_day,
|
||||
)
|
||||
|
||||
|
||||
def working_hours(delta):
|
||||
def working_hours(delta: timedelta):
|
||||
minutes = (delta.seconds // 60) % 60
|
||||
minutes = int(5 * round(float(minutes) / 5))
|
||||
hours = delta.seconds // 3600
|
||||
worked = str(hours).zfill(2) + ":" + str(minutes).zfill(2)
|
||||
return worked, delta.seconds >= 60 * 60 * 9 # 9hrs
|
||||
hours_worked = str(hours).zfill(2) + ":" + str(minutes).zfill(2)
|
||||
return hours_worked, delta.seconds >= 60 * 60 * 9 # 9hrs
|
||||
|
@ -0,0 +1,5 @@
|
||||
def to_camel(string: str) -> str:
|
||||
first, *others = string.split("_")
|
||||
return "".join([first] + [word.capitalize() for word in others])
|
||||
|
||||
|
@ -3,10 +3,7 @@ from typing import List, Optional
|
||||
from datetime import datetime
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
def to_camel(string: str) -> str:
|
||||
first, *others = string.split("_")
|
||||
return "".join([first] + [word.capitalize() for word in others])
|
||||
from brewman.schemas import to_camel
|
||||
|
||||
|
||||
class ClientIn(BaseModel):
|
||||
|
@ -5,10 +5,7 @@ from decimal import Decimal
|
||||
|
||||
from pydantic import BaseModel, Field, validator
|
||||
|
||||
|
||||
def to_camel(string: str) -> str:
|
||||
first, *others = string.split('_')
|
||||
return ''.join([first] + [word.capitalize() for word in others])
|
||||
from brewman.schemas import to_camel
|
||||
|
||||
|
||||
class AccountLink(BaseModel):
|
||||
@ -55,7 +52,6 @@ class ProductIn(BaseModel):
|
||||
fraction_units: str
|
||||
product_yield: Decimal = Field(ge=0, le=1, multiple_of=0.00001, default=1)
|
||||
product_group: ProductGroupLink = Field(...)
|
||||
account_id: AccountLink = Field(...)
|
||||
price: Decimal = Field(ge=0, multiple_of=0.01, default=0)
|
||||
sale_price: Decimal = Field(ge=0, multiple_of=0.01, default=0)
|
||||
is_active: bool
|
||||
@ -71,6 +67,7 @@ class ProductIn(BaseModel):
|
||||
class Product(ProductIn):
|
||||
id_: uuid.UUID
|
||||
code: int
|
||||
account: AccountLink = Field(...)
|
||||
is_fixture: bool
|
||||
|
||||
|
||||
@ -185,3 +182,13 @@ class DbSetting(BaseModel):
|
||||
id_: uuid.UUID
|
||||
name: str
|
||||
data: bytes
|
||||
|
||||
|
||||
class AccountType(BaseModel):
|
||||
id_: int
|
||||
name: str
|
||||
|
||||
class Config:
|
||||
fields = {'id_': 'id'}
|
||||
|
||||
|
||||
|
@ -4,14 +4,10 @@ from typing import List, Optional
|
||||
from datetime import datetime, date
|
||||
from pydantic import BaseModel, Field, validator
|
||||
|
||||
from brewman.schemas import to_camel
|
||||
from brewman.schemas.master import AccountLink, ProductLink
|
||||
|
||||
|
||||
def to_camel(string: str) -> str:
|
||||
first, *others = string.split("_")
|
||||
return "".join([first] + [word.capitalize() for word in others])
|
||||
|
||||
|
||||
class LedgerItem(BaseModel):
|
||||
id_: Optional[uuid.UUID]
|
||||
date_: date
|
||||
|
@ -1,8 +1,10 @@
|
||||
import uuid
|
||||
from datetime import datetime, date
|
||||
from decimal import Decimal
|
||||
from typing import List
|
||||
from pydantic import BaseModel
|
||||
from typing import List, Optional
|
||||
from pydantic import BaseModel, validator
|
||||
|
||||
from brewman.schemas import to_camel
|
||||
|
||||
|
||||
class Voucher(BaseModel):
|
||||
@ -72,20 +74,26 @@ class Batch(BaseModel):
|
||||
|
||||
class AttendanceType(BaseModel):
|
||||
id_: int
|
||||
name: str
|
||||
value: Decimal
|
||||
name: Optional[str]
|
||||
value: Optional[Decimal]
|
||||
|
||||
class Config:
|
||||
alias_generator = to_camel
|
||||
|
||||
|
||||
class AttendanceItem(BaseModel):
|
||||
id: uuid.UUID
|
||||
employee_id: uuid.UUID
|
||||
date: date
|
||||
id_: uuid.UUID
|
||||
code: int
|
||||
name: str
|
||||
designation: str
|
||||
department: str
|
||||
attendance_type: AttendanceType
|
||||
amount: Decimal
|
||||
creation_date: datetime
|
||||
user_id: uuid.UUID
|
||||
is_valid: bool
|
||||
prints: str
|
||||
hours_worked: str
|
||||
full_day: Optional[bool]
|
||||
|
||||
class Config:
|
||||
alias_generator = to_camel
|
||||
|
||||
class AttendanceIn(BaseModel):
|
||||
body: List[AttendanceItem]
|
||||
|
@ -58,9 +58,9 @@
|
||||
{{row.prints}}
|
||||
<mat-icon *ngIf="!form.controls.attendances.controls[i].pristine">new_releases</mat-icon>
|
||||
<mat-chip-list class="no-bg">
|
||||
<mat-chip *ngIf="row.hours.length" class="no-bg" [selected]="row.worked !== 'Error'"
|
||||
[color]="row.worked === true ? 'primary' : 'warn'">
|
||||
{{row.hours}}
|
||||
<mat-chip *ngIf="row.hoursWorked.length" class="no-bg" [selected]="true"
|
||||
[color]="row.fullDay === true ? 'primary' : 'warn'">
|
||||
{{row.hoursWorked}}
|
||||
</mat-chip>
|
||||
</mat-chip-list>
|
||||
</mat-cell>
|
||||
|
@ -17,8 +17,8 @@ export class AttendanceItem {
|
||||
department: string;
|
||||
attendanceType: AttendanceType;
|
||||
prints: string;
|
||||
hours: string;
|
||||
worked: string;
|
||||
hoursWorked: string;
|
||||
fullDay?: boolean;
|
||||
|
||||
public constructor(init?: Partial<AttendanceItem>) {
|
||||
Object.assign(this, init);
|
||||
|
@ -46,7 +46,7 @@ export class UnpostedDataSource extends DataSource<Unposted> {
|
||||
case 'date':
|
||||
return compare(a.date, b.date, isAsc);
|
||||
case 'type':
|
||||
return compare(a.voucherType, b.voucherType, isAsc);
|
||||
return compare(a.type, b.type, isAsc);
|
||||
case 'debitAmount':
|
||||
return compare(+a.debitAmount, +b.debitAmount, isAsc);
|
||||
case 'creditAmount':
|
||||
|
Loading…
x
Reference in New Issue
Block a user