DbImage works!!

Credit Salary works!!

Refresh router created, now need to use it in angular

Errors should now show up in the frontend.
This commit is contained in:
Amritanshu Agrawal 2020-05-30 01:58:17 +05:30
parent e3286c87ba
commit 10dbe6663d
34 changed files with 264 additions and 233 deletions

@ -10,6 +10,8 @@ from .routers import (
attendance,
batch,
cost_centre,
credit_salary,
db_image,
db_integrity,
employee,
employee_attendance,
@ -61,7 +63,7 @@ app = FastAPI()
app.add_middleware(SessionMiddleware, secret_key="c982367648")
# app.include_router(brewman.routers, prefix="/api/db-image", tags=["db-image"])
app.include_router(db_image.router, prefix="/db-image", tags=["db-image"])
app.include_router(login.router, tags=["login"])
app.include_router(account.router, prefix="/api/accounts", tags=["accounts"])
app.include_router(account_types.router, prefix="/api/account-types", tags=["accounts"])
@ -134,6 +136,7 @@ app.include_router(
employee_benefit.router, prefix="/api/employee-benefit", tags=["vouchers"]
)
app.include_router(incentive.router, prefix="/api/incentive", tags=["vouchers"])
app.include_router(credit_salary.router, prefix="/api/credit-salary", tags=["vouchers"])
app.include_router(
lock_information.router, prefix="/api/lock-information", tags=["settings"]

@ -366,6 +366,10 @@ class AccountBase(Base):
def salary(cls):
return {"id": "5c2b54d0-c174-004d-a0d5-92cdaadcefa7", "name": "Staff Salary"}
@classmethod
def salary_id(cls):
return uuid.UUID("5c2b54d0-c174-004d-a0d5-92cdaadcefa7")
@classmethod
def incentive(cls):
return {"id": "b7eff754-e8ba-e047-ab06-9132c15c7640", "name": "Incentives"}

@ -14,7 +14,7 @@ from sqlalchemy import (
)
from sqlalchemy.dialects.postgresql import BYTEA
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import relationship, synonym, backref
from sqlalchemy.orm import relationship, synonym, backref, Session
from brewman.models.guidtype import GUID
from brewman.models.master import Product
@ -176,14 +176,14 @@ class Journal(Base):
def __init__(
self,
id=None,
id_=None,
debit=None,
amount=None,
voucher_id=None,
account_id=None,
cost_centre_id=None,
):
self.id = id
self.id = id_
self.debit = debit
self.amount = amount
self.voucher_id = voucher_id
@ -357,14 +357,14 @@ class Batch(Base):
)
@classmethod
def list(cls, name, include_nil, date, dbsession):
query = dbsession.query(Batch).join(Batch.product)
def list(cls, name, include_nil, date, db: Session):
query = db.query(Batch).join(Batch.product)
if not include_nil:
query = query.filter(cls.quantity_remaining > 0)
if date is not None:
query = query.filter(cls.name <= date)
for item in name.split():
query = query.filter(Product.name.ilike("%" + item + "%"))
query = query.filter(Product.name.ilike(f"%{item}%"))
return query.order_by(Product.name).order_by(cls.name).all()
@classmethod
@ -388,7 +388,7 @@ class Attendance(Base):
def __init__(
self,
id=None,
id_=None,
employee_id=None,
date=None,
attendance_type=None,
@ -397,20 +397,18 @@ class Attendance(Base):
user_id=None,
is_valid=None,
):
self.id = id
self.id = id_
self.employee_id = employee_id
self.date = date
self.attendance_type = attendance_type
self.amount = amount if amount is not None else 0
self.creation_date = (
datetime.utcnow() if creation_date is None else creation_date
)
self.creation_date = creation_date or datetime.utcnow()
self.user_id = user_id
self.is_valid = is_valid if is_valid is not None else True
def create(self, dbsession):
def create(self, db: Session):
old = (
dbsession.query(Attendance)
db.query(Attendance)
.filter(Attendance.date == self.date)
.filter(Attendance.employee_id == self.employee_id)
.filter(Attendance.is_valid == True)
@ -453,13 +451,11 @@ class DbImage(Base):
image=None,
thumbnail=None,
creation_date=None,
id=None,
id_=None,
):
self.resource_id = resource_id
self.resource_type = resource_type
self.image = image
self.thumbnail = thumbnail
self.creation_date = (
datetime.utcnow() if creation_date is None else creation_date
)
self.id = id
self.creation_date = creation_date or datetime.utcnow()
self.id = id_

@ -5,6 +5,8 @@ from decimal import Decimal
from io import BytesIO
from typing import Optional
from sqlalchemy.orm import Session
from brewman.models.master import DbSetting
from brewman.models.voucher import DbImage
@ -13,26 +15,10 @@ from fastapi import APIRouter
router = APIRouter()
@router.get("/{id}/{type}")
def db_image(request):
item = (
request.dbsession.query(DbImage)
.filter(DbImage.id == uuid.UUID(request.matchdict["id"]))
.first()
)
if request.matchdict["type"] == "thumbnail":
item = BytesIO(item.thumbnail)
else:
item = BytesIO(item.image)
response = Response(content_type="image/jpeg")
response.app_iter = item
return response
def get_lock_info(dbsession) -> (Optional[date], Optional[date]):
def get_lock_info(db: Session) -> (Optional[date], Optional[date]):
start: Optional[date]
finish: Optional[date]
data = dbsession.query(DbSetting).filter(DbSetting.name == "Lock Info").first()
data = db.query(DbSetting).filter(DbSetting.name == "Lock Info").first()
if data is None:
return None, None

@ -0,0 +1,101 @@
from calendar import monthrange
from datetime import datetime, date
from fastapi import APIRouter, Depends, Security, Body, HTTPException, status
from sqlalchemy import or_
from sqlalchemy.orm import Session
from ..core.session import get_first_day, get_last_day
from ..schemas.auth import UserToken
from ..core.security import get_current_active_user as get_user
from ..db.session import SessionLocal
from ..models.master import Account, Employee, AttendanceType
from ..models.voucher import Voucher, Journal, VoucherType, Attendance
router = APIRouter()
# Dependency
def get_db() -> Session:
try:
db = SessionLocal()
yield db
finally:
db.close()
@router.post("")
def credit_salary(
month: str = Body(..., embed=True),
db: Session = Depends(get_db),
user: UserToken = Security(get_user, scopes=["attendance"]),
):
month = datetime.strptime(month, "%d-%b-%Y").date()
start_date = get_first_day(month)
finish_date = get_last_day(month)
voucher = Voucher(
date=finish_date,
narration="Auto Generated Salary Entry",
user_id=user.id_,
type_=VoucherType.by_name("Journal"),
posted=True,
poster_id=user.id_,
)
db.add(voucher)
for item in salary_journals(start_date, finish_date, db):
voucher.journals.append(item)
db.add(item)
db.commit()
return {"message": "Salary Entry created"}
def salary_journals(start_date: date, finish_date: date, db: Session):
days = monthrange(start_date.year, start_date.month)[1]
amount = 0
journals = []
employees = (
db.query(Employee)
.filter(Employee.joining_date <= finish_date)
.filter(or_(Employee.is_active, Employee.leaving_date >= start_date))
.order_by(Employee.cost_centre_id)
.order_by(Employee.designation)
.order_by(Employee.name)
.all()
)
for employee in employees:
att = (
db.query(Attendance)
.filter(Attendance.employee_id == employee.id)
.filter(Attendance.date >= start_date)
.filter(Attendance.date <= finish_date)
.filter(Attendance.is_valid == True)
.all()
)
att = sum(map(lambda x: AttendanceType.by_id(x.attendance_type).value, att))
att = round(att * employee.salary / days)
if att != 0:
amount += att
journals.append(
Journal(
amount=att,
debit=-1,
account_id=employee.id,
cost_centre_id=employee.cost_centre_id,
)
)
salary = db.query(Account).filter(Account.id == Account.salary_id()).first()
if amount == 0:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="No salaries to credit",
)
journals.append(
Journal(
amount=amount,
debit=1,
account_id=salary.id,
cost_centre_id=salary.cost_centre_id,
)
)
return journals

@ -0,0 +1,36 @@
import uuid
from io import BytesIO
from fastapi import APIRouter, Depends, Security
from fastapi.responses import StreamingResponse
from sqlalchemy.orm import Session
from ..core.security import get_user
from ..models.voucher import DbImage
from ..db.session import SessionLocal
from ..schemas.auth import UserToken
router = APIRouter()
# Dependency
def get_db() -> Session:
try:
db = SessionLocal()
yield db
finally:
db.close()
@router.get("/{id_}/{type_}")
def db_image(
id_: uuid.UUID,
type_: str,
db: Session = Depends(get_db)
):
item = db.query(DbImage).filter(DbImage.id == id_).first()
if type_ == "thumbnail":
item = BytesIO(item.thumbnail)
else:
item = BytesIO(item.image)
return StreamingResponse(item, media_type="image/jpeg")

@ -26,7 +26,7 @@ from ..models import AccountBase
from ..schemas.auth import UserToken
from ..core.security import get_current_active_user as get_user
from ..db.session import SessionLocal
from ..models.voucher import Voucher, VoucherType, Journal
from ..models.voucher import Voucher, VoucherType, Journal, DbImage
import brewman.schemas.voucher as output
import brewman.schemas.input as schema_in
@ -47,15 +47,14 @@ def save_route(
request: Request,
data: schema_in.JournalIn = Depends(schema_in.JournalIn.load_form),
db: Session = Depends(get_db),
i: List[UploadFile] = File(None),
t: List[UploadFile] = File(None),
i: List[bytes] = File(None),
t: List[bytes] = File(None),
user: UserToken = Security(get_user, scopes=["journal"]),
):
try:
i = i or []
t = t or []
item: Voucher = save(data, user, db)
save_files(i + t, db)
db.flush()
save_files(item.id, i, t, db)
db.commit()
set_date(data.date_.strftime("%d-%b-%Y"), request.session)
info = voucher_info(item, db)
@ -66,11 +65,7 @@ def save_route(
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(),
)
raise
def save(data: schema_in.JournalIn, user: UserToken, db: Session) -> Voucher:
@ -88,7 +83,6 @@ def save(data: schema_in.JournalIn, user: UserToken, db: Session) -> Voucher:
AccountBase.id == item.account.id_
).first()
journal = Journal(
id=item.id_,
amount=item.amount,
debit=item.debit,
account_id=account.id,
@ -99,10 +93,9 @@ def save(data: schema_in.JournalIn, user: UserToken, db: Session) -> Voucher:
return voucher
def save_files(files: List[UploadFile], db: Session):
# for key, value in files.items():
# db.add(DbImage(voucher.id, "voucher", value["f"], value["t"]))
pass
def save_files(voucher_id: uuid.UUID, i: List[bytes], t: List[bytes], db: Session):
for index, value in enumerate(i):
db.add(DbImage(voucher_id, "voucher", i[index], t[index]))
@router.put("/{id_}", response_model=output.Voucher)
@ -111,15 +104,13 @@ def update_route(
request: Request,
data: schema_in.JournalIn = Depends(schema_in.JournalIn.load_form),
db: Session = Depends(get_db),
i: List[UploadFile] = File(None),
t: List[UploadFile] = File(None),
i: List[bytes] = File(None),
t: List[bytes] = File(None),
user: UserToken = Security(get_user, scopes=["journal"]),
):
try:
i = i or []
t = t or []
item: Voucher = update(id_, data, user, db)
update_files(data, i + t, db)
update_files(item.id, data.files, i, t, db)
db.commit()
set_date(data.date_.strftime("%d-%b-%Y"), request.session)
return voucher_info(item, db)
@ -174,7 +165,6 @@ def update(
db.query(AccountBase).filter(AccountBase.id == new_item.account.id_).first()
)
journal = Journal(
id=None,
amount=new_item.amount,
debit=new_item.debit,
account_id=account.id,
@ -185,16 +175,13 @@ def update(
return voucher
def update_files(data: schema_in.VoucherIn, files: List[UploadFile], db: Session):
pass
# old_files = [
# uuid.UUID(f["id"]) for f in json["files"] if "id" in f and f["id"] is not None
# ]
# images = db.query(DbImage).filter(DbImage.resource_id == voucher.id).all()
# for image in [i for i in images if i.id not in old_files]:
# db.delete(image)
# for key, value in files.items():
# db.add(DbImage(voucher.id, "voucher", value["f"], value["t"]))
def update_files(voucher_id: uuid.UUID, data: List[output.ImageUpload], i: List[bytes], t: List[bytes], db: Session):
old = [f.id_ for f in data if f.id_]
images = db.query(DbImage).filter(DbImage.resource_id == voucher_id).all()
for image in [i for i in images if i.id not in old]:
db.delete(image)
for index, value in enumerate(i):
db.add(DbImage(voucher_id, "voucher", i[index], t[index]))
@router.get("/{id_}", response_model=output.Voucher)

@ -7,9 +7,10 @@ from ..core.security import (
Token,
authenticate_user,
ACCESS_TOKEN_EXPIRE_MINUTES,
create_access_token,
create_access_token, get_user,
)
from ..db.session import SessionLocal
from ..schemas.auth import UserToken
router = APIRouter()
@ -54,3 +55,21 @@ async def login_for_access_token(
expires_delta=access_token_expires,
)
return {"access_token": access_token, "token_type": "bearer"}
@router.post("/refresh", response_model=Token)
async def refresh_token(
db: Session = Depends(get_db),
user: UserToken = Depends(get_user)
):
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
access_token = create_access_token(
data={
"sub": user.name,
"scopes": user.permissions,
"userId": str(user.id_),
"lockedOut": user.locked_out,
},
expires_delta=access_token_expires,
)
return {"access_token": access_token, "token_type": "bearer"}

@ -283,7 +283,7 @@ def voucher_info(voucher, db):
)
images = db.query(DbImage).filter(DbImage.resource_id == voucher.id).all()
for image in images:
json_voucher["files"].append({"id": image.id, "resized": "", "thumbnail": ""})
json_voucher["files"].append({"id": image.id, "resized": f"/db-image/{image.id}/resized", "thumbnail": f"/db-image/{image.id}/thumbnail"})
return json_voucher
@ -301,6 +301,7 @@ def blank_voucher(info, db):
"narration": "",
"journals": [],
"inventories": [],
"employeeBenefits": [],
}
if type_ == "Journal":
pass

@ -1,87 +0,0 @@
import calendar
import datetime
import uuid
from sqlalchemy import or_
from ....models.auth import User
from ....models.master import Employee, AttendanceType, Account
from ....models.voucher import Voucher, VoucherType, Attendance, Journal
from ..session import get_first_day, get_last_day
@router.post("/api/credit-salary") # "Attendance"
def credit_salary(request):
user = (
request.dbsession.query(User)
.filter(User.id == uuid.UUID(request.authenticated_userid))
.one()
)
month = datetime.datetime.strptime(request.json_body["month"], "%d-%b-%Y")
start_date = get_first_day(month)
finish_date = get_last_day(month)
voucher = Voucher(
date=finish_date,
narration="Auto Generated Salary Entry",
user_id=user.id,
type=VoucherType.by_name("Journal"),
posted=True,
poster_id=user.id,
)
request.dbsession.add(voucher)
for item in salary_journals(start_date, finish_date, request.dbsession):
voucher.journals.append(item)
request.dbsession.add(item)
transaction.commit()
return {"message": "Salary Entry created"}
def salary_journals(start_date, finish_date, dbsession):
days = calendar.monthrange(start_date.year, start_date.month)[1]
finish_date = finish_date + datetime.timedelta(1)
amount = 0
journals = []
employees = (
dbsession.query(Employee)
.filter(Employee.joining_date <= finish_date)
.filter(or_(Employee.is_active, Employee.leaving_date >= start_date))
.order_by(Employee.cost_centre_id)
.order_by(Employee.designation)
.order_by(Employee.name)
.all()
)
for employee in employees:
att = (
dbsession.query(Attendance)
.filter(Attendance.employee_id == employee.id)
.filter(Attendance.date >= start_date)
.filter(Attendance.date < finish_date)
.filter(Attendance.is_valid == True)
.all()
)
att = sum(map(lambda x: AttendanceType.by_id(x.attendance_type).value, att))
att = round(att * employee.salary / days)
if att != 0:
amount += att
journals.append(
Journal(
amount=att,
debit=-1,
account_id=employee.id,
cost_centre_id=employee.cost_centre_id,
)
)
salary = (
dbsession.query(Account)
.filter(Account.id == uuid.UUID(Account.salary()["id"]))
.first()
)
journals.append(
Journal(
amount=amount,
debit=1,
account_id=salary.id,
cost_centre_id=salary.cost_centre_id,
)
)
return journals

@ -1,27 +0,0 @@
from ....core.session import get_date
from brewman.routers.services.voucher import blank_voucher
class EmptyVoucher(object):
def __init__(self, request):
self.request = request
@router.get("/api/voucher", request_param="t=Incentive") # "Incentive"
def incentive(self):
voucher_type = self.request.GET.get("t", None)
date = self.request.GET.get("d", None)
if date is not None:
return blank_voucher(
{"type": voucher_type, "date": date}, self.request.dbsession
)
else:
return self.get_blank()
def get_blank(self, additional_info=None):
voucher_type = self.request.GET.get("t", None)
if additional_info is None:
additional_info = {}
additional_info["date"] = get_date(self.request)
additional_info["type"] = voucher_type
return blank_voucher(additional_info, self.request.dbsession)

@ -16,6 +16,15 @@ from brewman.schemas.master import (
)
class ImageUpload(BaseModel):
id_: Optional[uuid.UUID]
resized: Optional[str]
thumbnail: Optional[str]
class Config:
alias_generator = to_camel
class UserLink(BaseModel):
id_: uuid.UUID
name: str
@ -94,6 +103,7 @@ class VoucherIn(BaseModel):
narration: str
is_starred: bool
type_: str
files: List[ImageUpload]
@classmethod
def load_form(cls, data: str = Form(...)):
@ -118,7 +128,7 @@ class Voucher(VoucherIn):
incentives: Optional[List[Incentive]]
incentive: Optional[Decimal]
employee_benefits: List[EmployeeBenefit]
files: List[Any]
files: List[ImageUpload]
class Config:
anystr_strip_whitespace = True

@ -78,7 +78,7 @@ export class AccountDetailComponent implements OnInit, AfterViewInit {
this.router.navigateByUrl('/accounts');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}
@ -91,7 +91,7 @@ export class AccountDetailComponent implements OnInit, AfterViewInit {
this.router.navigateByUrl('/accounts');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}

@ -82,7 +82,7 @@ export class AttendanceComponent implements OnInit {
this.toaster.show('Success', '');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}

@ -69,7 +69,7 @@ export class ClientDetailComponent implements OnInit, AfterViewInit {
this.router.navigateByUrl('/clients');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}
@ -82,7 +82,7 @@ export class ClientDetailComponent implements OnInit, AfterViewInit {
this.router.navigateByUrl('/clients');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}

@ -22,7 +22,7 @@ export class ErrorLoggerService {
console.error(error); // log to console instead
// TODO: better job of transforming error for user consumption
this.log(serviceName, `${operation} failed: ${error.message}`);
this.log(serviceName, `${operation} failed: ${error}`);
// // Let the app keep running by returning an empty result.
// return of(result as T);

@ -60,7 +60,7 @@ export class CostCentreDetailComponent implements OnInit, AfterViewInit {
this.router.navigateByUrl('/cost-centres');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}

@ -129,7 +129,7 @@ export class EmployeeAttendanceComponent implements OnInit, AfterViewInit {
this.toaster.show('Success', '');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}

@ -185,7 +185,7 @@ export class EmployeeBenefitsComponent implements OnInit, AfterViewInit {
this.toaster.show('Success', 'Voucher Posted');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}
@ -198,7 +198,7 @@ export class EmployeeBenefitsComponent implements OnInit, AfterViewInit {
this.router.navigate(['/employee-benefits', result.id]);
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}
@ -217,7 +217,7 @@ export class EmployeeBenefitsComponent implements OnInit, AfterViewInit {
this.router.navigate(['/employee-benefits'], {replaceUrl: true});
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}

@ -79,7 +79,8 @@ export class EmployeeFunctionsComponent implements OnInit {
this.toaster.show('Success', 'Salaries Credited');
},
(error) => {
this.toaster.show('Danger', error.error);
console.log('Error:', error);
this.toaster.show('Danger', error);
}
);
}
@ -109,7 +110,7 @@ export class EmployeeFunctionsComponent implements OnInit {
this.toaster.show('Success', 'Fingerprints uploaded');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}

@ -90,7 +90,7 @@ export class EmployeeDetailComponent implements OnInit, AfterViewInit {
this.router.navigateByUrl('/employees');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}
@ -103,7 +103,7 @@ export class EmployeeDetailComponent implements OnInit, AfterViewInit {
this.router.navigateByUrl('/employees');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}

@ -140,7 +140,7 @@ export class IncentiveComponent implements OnInit {
this.toaster.show('Success', 'Voucher Posted');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}
@ -153,7 +153,7 @@ export class IncentiveComponent implements OnInit {
this.router.navigate(['/incentive', result.id]);
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}
@ -176,7 +176,7 @@ export class IncentiveComponent implements OnInit {
this.router.navigate(['/incentive'], {replaceUrl: true});
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}

@ -223,7 +223,7 @@ export class IssueComponent implements OnInit, AfterViewInit, OnDestroy {
this.router.navigate(['/issue', result.id]);
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}
@ -249,7 +249,7 @@ export class IssueComponent implements OnInit, AfterViewInit, OnDestroy {
this.router.navigate(['/issue'], {replaceUrl: true});
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}

@ -218,7 +218,7 @@ export class JournalComponent implements OnInit, AfterViewInit, OnDestroy {
this.toaster.show('Success', 'Voucher Posted');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}
@ -232,7 +232,7 @@ export class JournalComponent implements OnInit, AfterViewInit, OnDestroy {
this.router.navigate(['/journal', result.id]);
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}
@ -252,7 +252,7 @@ export class JournalComponent implements OnInit, AfterViewInit, OnDestroy {
this.router.navigate(['/journal'], {replaceUrl: true});
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}

@ -222,7 +222,7 @@ export class PaymentComponent implements OnInit, AfterViewInit, OnDestroy {
this.toaster.show('Success', 'Voucher Posted');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}
@ -236,7 +236,7 @@ export class PaymentComponent implements OnInit, AfterViewInit, OnDestroy {
this.router.navigate(['/payment', result.id]);
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}
@ -257,7 +257,7 @@ export class PaymentComponent implements OnInit, AfterViewInit, OnDestroy {
this.router.navigate(['/payment'], {replaceUrl: true});
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}

@ -60,7 +60,7 @@ export class ProductGroupDetailComponent implements OnInit, AfterViewInit {
this.router.navigateByUrl('/product-groups');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}

@ -87,7 +87,7 @@ export class ProductDetailComponent implements OnInit, AfterViewInit {
this.router.navigateByUrl('/products');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}
@ -100,7 +100,7 @@ export class ProductDetailComponent implements OnInit, AfterViewInit {
this.router.navigateByUrl('/products');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}

@ -209,7 +209,7 @@ export class PurchaseReturnComponent implements OnInit, AfterViewInit, OnDestroy
this.toaster.show('Success', 'Voucher Posted');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}
@ -223,7 +223,7 @@ export class PurchaseReturnComponent implements OnInit, AfterViewInit, OnDestroy
this.router.navigate(['/purchase-return', result.id]);
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}
@ -244,7 +244,7 @@ export class PurchaseReturnComponent implements OnInit, AfterViewInit, OnDestroy
this.router.navigate(['/purchase-return'], {replaceUrl: true});
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}

@ -222,7 +222,7 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy {
this.toaster.show('Success', 'Voucher Posted');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}
@ -236,7 +236,7 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy {
this.router.navigate(['/purchase', result.id]);
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}
@ -257,7 +257,7 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy {
this.router.navigate(['/purchase'], {replaceUrl: true});
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}

@ -221,7 +221,7 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
this.toaster.show('Success', 'Voucher Posted');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}
@ -235,7 +235,7 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
this.router.navigate(['/receipt', result.id]);
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}
@ -256,7 +256,7 @@ export class ReceiptComponent implements OnInit, AfterViewInit, OnDestroy {
this.router.navigate(['/receipt'], {replaceUrl: true});
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}

@ -65,7 +65,7 @@ export class RoleDetailComponent implements OnInit, AfterViewInit {
this.router.navigateByUrl('/roles');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}
@ -78,7 +78,7 @@ export class RoleDetailComponent implements OnInit, AfterViewInit {
this.router.navigateByUrl('/roles');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}

@ -132,7 +132,7 @@ export class SettingsComponent implements OnInit {
this.toaster.show('Success', 'Lock information Updated');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}
@ -162,7 +162,7 @@ export class SettingsComponent implements OnInit {
this.toaster.show('Success', 'Data has been rebased!');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}
@ -213,7 +213,7 @@ export class SettingsComponent implements OnInit {
this.toaster.show('Success', 'Stock has been reset!');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}
@ -227,7 +227,7 @@ export class SettingsComponent implements OnInit {
this.toaster.show('Success', 'Database checked, it is fine!');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}

@ -76,7 +76,7 @@ export class UserDetailComponent implements OnInit, AfterViewInit {
this.router.navigateByUrl('/users');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}
@ -89,7 +89,7 @@ export class UserDetailComponent implements OnInit, AfterViewInit {
this.router.navigateByUrl('/users');
},
(error) => {
this.toaster.show('Danger', error.error);
this.toaster.show('Danger', error);
}
);
}

@ -4,7 +4,8 @@ fastapi
environs
python-jose[cryptography]
passlib[bcrypt]
psycopg2
psycopg2-binary
sqlalchemy
python-multipart
pyjwt
alembic