From 73850560aa6db493e027ab63230d1c663fde4330 Mon Sep 17 00:00:00 2001 From: tanshu Date: Fri, 2 Apr 2021 14:34:07 +0530 Subject: [PATCH] Customer discount with prefill discount in sales. --- barker/alembic/env.py | 2 +- .../versions/8c06ac60d125_initial_commit.py | 25 ++++++ barker/barker/db/base.py | 1 + barker/barker/main.py | 5 ++ barker/barker/models/customer.py | 3 + barker/barker/models/customer_discount.py | 33 ++++++++ barker/barker/routers/customer.py | 57 +++++++++++-- barker/barker/routers/customer_discount.py | 75 +++++++++++++++++ barker/barker/routers/db_settings.py | 41 ++++++++++ barker/barker/routers/sale_category.py | 8 -- barker/barker/schemas/customer.py | 16 +++- barker/barker/schemas/settings.py | 5 ++ bookie/src/app/app-routing.module.ts | 4 + bookie/src/app/core/customer-discount.ts | 12 +++ bookie/src/app/core/customer.ts | 4 + .../customer-detail.component.html | 21 ++++- .../customer-detail.component.ts | 19 +++++ .../customer-discounts.service.spec.ts | 18 +++++ .../customers/customer-discounts.service.ts | 37 +++++++++ .../customer-list.component.html | 12 +++ .../customer-list/customer-list.component.ts | 2 +- bookie/src/app/home/home.component.html | 9 +++ .../sale-category/sale-category.service.ts | 8 -- .../src/app/sales/discount/discount-item.ts | 16 ++++ .../sales/discount/discount.component.html | 6 +- .../app/sales/discount/discount.component.ts | 26 +++--- .../app/sales/home/sales-home.component.ts | 12 +-- ...fill-customer-discount-resolver.service.ts | 16 ++++ .../app/settings/settings-routing.module.ts | 29 +++++++ .../src/app/settings/settings.component.css | 32 ++++++++ .../src/app/settings/settings.component.html | 18 +++++ bookie/src/app/settings/settings.component.ts | 50 ++++++++++++ bookie/src/app/settings/settings.module.ts | 81 +++++++++++++++++++ bookie/src/app/settings/settings.service.ts | 31 +++++++ .../user-detail/user-detail.component.ts | 4 +- 35 files changed, 690 insertions(+), 48 deletions(-) create mode 100644 barker/barker/models/customer_discount.py create mode 100644 barker/barker/routers/customer_discount.py create mode 100644 barker/barker/routers/db_settings.py create mode 100644 barker/barker/schemas/settings.py create mode 100644 bookie/src/app/core/customer-discount.ts create mode 100644 bookie/src/app/customers/customer-discounts.service.spec.ts create mode 100644 bookie/src/app/customers/customer-discounts.service.ts create mode 100644 bookie/src/app/sales/discount/discount-item.ts create mode 100644 bookie/src/app/settings/prefill-customer-discount-resolver.service.ts create mode 100644 bookie/src/app/settings/settings-routing.module.ts create mode 100644 bookie/src/app/settings/settings.component.css create mode 100644 bookie/src/app/settings/settings.component.html create mode 100644 bookie/src/app/settings/settings.component.ts create mode 100644 bookie/src/app/settings/settings.module.ts create mode 100644 bookie/src/app/settings/settings.service.ts diff --git a/barker/alembic/env.py b/barker/alembic/env.py index 00ba73e..37812f5 100644 --- a/barker/alembic/env.py +++ b/barker/alembic/env.py @@ -2,7 +2,7 @@ import logging from alembic import context from barker.core.config import settings -from barker.models.user import User +from barker.db.base import User from sqlalchemy import create_engine, pool diff --git a/barker/alembic/versions/8c06ac60d125_initial_commit.py b/barker/alembic/versions/8c06ac60d125_initial_commit.py index 3942a01..13685b7 100644 --- a/barker/alembic/versions/8c06ac60d125_initial_commit.py +++ b/barker/alembic/versions/8c06ac60d125_initial_commit.py @@ -277,6 +277,23 @@ def upgrade(): sa.PrimaryKeyConstraint("id", name=op.f("pk_sale_categories")), sa.UniqueConstraint("name", name=op.f("uq_sale_categories_name")), ) + op.create_table( + "customer_discount", + sa.Column("id", postgresql.UUID(as_uuid=True), server_default=sa.text("gen_random_uuid()"), nullable=False), + sa.Column("customer_id", postgresql.UUID(as_uuid=True), nullable=False), + sa.Column("sale_category_id", postgresql.UUID(as_uuid=True), nullable=False), + sa.Column("discount", sa.Numeric(precision=15, scale=5), nullable=False), + sa.ForeignKeyConstraint( + ["customer_id"], ["customers.id"], name=op.f("fk_customer_discount_customer_id_customers") + ), + sa.ForeignKeyConstraint( + ["sale_category_id"], + ["sale_categories.id"], + name=op.f("fk_customer_discount_sale_category_id_sale_categories"), + ), + sa.PrimaryKeyConstraint("id", name=op.f("pk_customer_discount")), + sa.UniqueConstraint("customer_id", "sale_category_id", name=op.f("uq_customer_discount_customer_id")), + ) op.create_table( "section_printers", sa.Column("id", postgresql.UUID(as_uuid=True), server_default=sa.text("gen_random_uuid()"), nullable=False), @@ -535,6 +552,7 @@ def upgrade(): ) op.execute(Permission.__table__.insert().values(id="5b66c6f6-003a-4ef8-ba28-49b8ff1ac33c", name="Printers")) + op.execute(Permission.__table__.insert().values(id="7c54039e-0ca3-45ca-a6e0-4d55a8bb10b0", name="Settings")) op.execute(Permission.__table__.insert().values(id="7a04ba63-5d08-4078-9051-a6d91cce3e48", name="Section Printers")) op.execute(Permission.__table__.insert().values(id="5f6110ba-2d3a-41cb-9597-1157774f10cb", name="Add Devices")) op.execute( @@ -628,6 +646,13 @@ def upgrade(): data={"Text": "Call: 0172-4026666, 8054923853, 8054923856"}, ) ) + op.execute( + DbSetting.__table__.insert().values( + id="fa3d415c-c770-4d7c-8705-90f4be302587", + name="Prefill Customer Discount", + data={"Value": "true"}, + ) + ) # ### end Alembic commands ### diff --git a/barker/barker/db/base.py b/barker/barker/db/base.py index ef6a3b7..4734e05 100644 --- a/barker/barker/db/base.py +++ b/barker/barker/db/base.py @@ -2,6 +2,7 @@ # imported by Alembic from barker.db.base_class import Base # noqa: F401 from barker.models.customer import Customer # noqa: F401 +from barker.models.customer_discount import CustomerDiscount # noqa: F401 from barker.models.db_setting import DbSetting # noqa: F401 from barker.models.device import Device # noqa: F401 from barker.models.food_table import FoodTable # noqa: F401 diff --git a/barker/barker/main.py b/barker/barker/main.py index ef197e5..a738174 100644 --- a/barker/barker/main.py +++ b/barker/barker/main.py @@ -8,6 +8,8 @@ from .db.base_class import Base from .db.session import engine from .routers import ( customer, + customer_discount, + db_settings, device, guest_book, header_footer, @@ -77,6 +79,8 @@ app.include_router(section.router, prefix="/api/sections", tags=["sections"]) app.include_router(section_printer.router, prefix="/api/section-printers", tags=["section-printers"]) app.include_router(settle_option.router, prefix="/api/settle-options", tags=["settle-options"]) +app.include_router(db_settings.router, prefix="/api/settings", tags=["settings"]) + app.include_router(tax.router, prefix="/api/taxes", tags=["taxes"]) app.include_router(table.router, prefix="/api/tables", tags=["sections"]) @@ -99,6 +103,7 @@ app.include_router(tax_report.router, prefix="/api/tax-report", tags=["reports"] app.include_router(guest_book.router, prefix="/api/guest-book", tags=["guest-book"]) app.include_router(customer.router, prefix="/api/customers", tags=["guest-book"]) +app.include_router(customer_discount.router, prefix="/api/customer-discounts", tags=["guest-book"]) app.include_router(show.router, prefix="/api/voucher", tags=["voucher"]) app.include_router(save.router, prefix="/api/voucher", tags=["voucher"]) app.include_router(update.router, prefix="/api/voucher", tags=["voucher"]) diff --git a/barker/barker/models/customer.py b/barker/barker/models/customer.py index d9b588f..0d7431d 100644 --- a/barker/barker/models/customer.py +++ b/barker/barker/models/customer.py @@ -3,6 +3,7 @@ import uuid from barker.models.meta import Base from sqlalchemy import Column, Unicode, text from sqlalchemy.dialects.postgresql import UUID +from sqlalchemy.orm import relationship class Customer(Base): @@ -15,6 +16,8 @@ class Customer(Base): phone = Column("phone", Unicode(255), nullable=False, unique=True) address = Column("address", Unicode(255), nullable=True) + discounts = relationship("CustomerDiscount") + @property def __name__(self): return self.name diff --git a/barker/barker/models/customer_discount.py b/barker/barker/models/customer_discount.py new file mode 100644 index 0000000..79caf7e --- /dev/null +++ b/barker/barker/models/customer_discount.py @@ -0,0 +1,33 @@ +import uuid + +from datetime import datetime + +from barker.models.meta import Base +from sqlalchemy import Column, ForeignKey, Numeric, UniqueConstraint, text +from sqlalchemy.dialects.postgresql import UUID +from sqlalchemy.orm import relationship + + +class CustomerDiscount(Base): + __tablename__ = "customer_discount" + __table_args__ = (UniqueConstraint("customer_id", "sale_category_id"),) + + id = Column( + "id", UUID(as_uuid=True), primary_key=True, server_default=text("gen_random_uuid()"), default=uuid.uuid4 + ) + customer_id = Column("customer_id", UUID(as_uuid=True), ForeignKey("customers.id"), nullable=False) + sale_category_id = Column("sale_category_id", UUID(as_uuid=True), ForeignKey("sale_categories.id"), nullable=False) + discount = Column("discount", Numeric(precision=15, scale=5), nullable=False) + + customer = relationship("Customer") + sale_category = relationship("SaleCategory") + + def __init__(self, sale_category_id=None, discount=None, id_=None, customer_id=None, customer=None): + self.sale_category_id = sale_category_id + self.discount = discount + self.id = id_ + self.date = datetime.utcnow() + if customer is None: + self.customer_id = customer_id + else: + self.customer = customer diff --git a/barker/barker/routers/customer.py b/barker/barker/routers/customer.py index 1c82ad5..1fe2e84 100644 --- a/barker/barker/routers/customer.py +++ b/barker/barker/routers/customer.py @@ -11,6 +11,8 @@ from sqlalchemy.orm import Session from ..core.security import get_current_active_user as get_user from ..db.session import SessionLocal from ..models.customer import Customer +from ..models.customer_discount import CustomerDiscount +from ..models.sale_category import SaleCategory from ..schemas.user_token import UserToken @@ -35,8 +37,9 @@ def save( try: item = Customer(name=data.name, phone=data.phone, address=data.address) db.add(item) + add_discounts(item, data.discounts, db) db.commit() - return customer_info(item) + return customer_info(item, db) except SQLAlchemyError as e: db.rollback() raise HTTPException( @@ -60,8 +63,9 @@ def update( item.name = data.name item.phone = data.phone item.address = data.address + add_discounts(item, data.discounts, db) db.commit() - return customer_info(item) + return customer_info(item, db) except SQLAlchemyError as e: db.rollback() raise HTTPException( @@ -73,6 +77,17 @@ def update( raise +def add_discounts(customer: Customer, discounts: List[schemas.DiscountItem], db: Session): + for discount in discounts: + cd = next((d for d in customer.discounts if d.sale_category_id == discount.id_), None) + if cd is None: + cd = CustomerDiscount(discount.id_, round(discount.discount, 5), customer=customer) + customer.discounts.append(cd) + db.add(cd) + else: + cd.discount = round(discount.discount, 5) + + @router.delete("/{id_}") def delete( id_: uuid.UUID, @@ -84,7 +99,7 @@ def delete( if item is None: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, - detail="Sale Category not found", + detail="Customer not found", ) db.delete(item) db.commit() @@ -103,7 +118,7 @@ def show_blank( @router.get("/list", response_model=List[schemas.Customer]) def show_list(db: Session = Depends(get_db), user: UserToken = Depends(get_user)) -> List[schemas.Customer]: - return [customer_info(item) for item in db.query(Customer).order_by(Customer.name).all()] + return [customer_info_for_list(item) for item in db.query(Customer).order_by(Customer.name).all()] @router.get("/query", response_model=List[schemas.Customer]) @@ -113,7 +128,7 @@ async def show_term( current_user: UserToken = Depends(get_user), ) -> List[schemas.Customer]: return [ - customer_info(item) + customer_info_for_list(item) for item in db.query(Customer).filter(Customer.phone.ilike(f"%{q}%")).order_by(Customer.name).all() ] @@ -125,17 +140,43 @@ def show_id( user: UserToken = Security(get_user, scopes=["customers"]), ) -> schemas.Customer: item: Customer = db.query(Customer).filter(Customer.id == id_).first() - return customer_info(item) + return customer_info(item, db) -def customer_info(item: Customer) -> schemas.Customer: +def customer_info(item: Customer, db: Session) -> schemas.Customer: return schemas.Customer( id=item.id, name=item.name, address=item.address, phone=item.phone, + discounts=[ + { + "id": sc.id, + "name": sc.name, + "discount": next((d.discount for d in item.discounts if d.sale_category_id == sc.id), 0), + } + for sc in db.query(SaleCategory).order_by(SaleCategory.name).all() + ], + ) + + +def customer_info_for_list(item: Customer) -> schemas.Customer: + return schemas.Customer( + id=item.id, + name=item.name, + address=item.address, + phone=item.phone, + discounts=[ + { + "id": d.sale_category_id, + "name": d.sale_category.name, + "discount": d.discount, + } + for d in item.discounts + if d.discount != 0 + ], ) def blank_customer_info() -> schemas.CustomerBlank: - return schemas.CustomerBlank(name="", address="", phone="") + return schemas.CustomerBlank(name="", address="", phone="", discounts=[]) diff --git a/barker/barker/routers/customer_discount.py b/barker/barker/routers/customer_discount.py new file mode 100644 index 0000000..130c8ff --- /dev/null +++ b/barker/barker/routers/customer_discount.py @@ -0,0 +1,75 @@ +import uuid + +from typing import List + +import barker.schemas.customer as schemas + +from fastapi import APIRouter, Depends, Security +from sqlalchemy.orm import Session + +from ..core.security import get_current_active_user as get_user +from ..db.session import SessionLocal +from ..models.customer import Customer +from ..models.db_setting import DbSetting +from ..models.sale_category import SaleCategory +from ..schemas.user_token import UserToken + + +router = APIRouter() + + +# Dependency +def get_db(): + try: + db = SessionLocal() + yield db + finally: + db.close() + + +@router.get("", response_model=List[schemas.DiscountItem]) +def show_blank( + db: Session = Depends(get_db), + user: UserToken = Security(get_user, scopes=["customers"]), +) -> List[schemas.DiscountItem]: + return customer_discounts_blank(db) + + +@router.get("/{id_}", response_model=List[schemas.DiscountItem]) +def show_id( + id_: uuid.UUID, + db: Session = Depends(get_db), + user: UserToken = Security(get_user, scopes=["customers"]), +) -> List[schemas.DiscountItem]: + item: Customer = db.query(Customer).filter(Customer.id == id_).first() + return customer_discounts(item, db) + + +def customer_discounts(item: Customer, db: Session) -> List[schemas.DiscountItem]: + default_discount = db.query(DbSetting).filter(DbSetting.name == "Prefill Customer Discount").first().data["Value"] + + return [ + schemas.DiscountItem( + id=sc.id, + name=sc.name, + discount=0 + if not default_discount + else next((d.discount for d in item.discounts if d.sale_category_id == sc.id), 0), + discountLimit=sc.discount_limit, + customerDiscount=next((d.discount for d in item.discounts if d.sale_category_id == sc.id), 0), + ) + for sc in db.query(SaleCategory).filter(SaleCategory.discount_limit != 0).order_by(SaleCategory.name).all() + ] + + +def customer_discounts_blank(db: Session) -> List[schemas.DiscountItem]: + return [ + schemas.DiscountItem( + id=sc.id, + name=sc.name, + discount=0, + discountLimit=sc.discount_limit, + customerDiscount=0, + ) + for sc in db.query(SaleCategory).filter(SaleCategory.discount_limit != 0).order_by(SaleCategory.name).all() + ] diff --git a/barker/barker/routers/db_settings.py b/barker/barker/routers/db_settings.py new file mode 100644 index 0000000..375703a --- /dev/null +++ b/barker/barker/routers/db_settings.py @@ -0,0 +1,41 @@ +from fastapi import APIRouter, Depends, Security +from sqlalchemy.orm import Session + +from ..core.security import get_current_active_user as get_user +from ..db.session import SessionLocal +from ..models.db_setting import DbSetting +from ..schemas.settings import PrefillCustomerDiscount +from ..schemas.user_token import UserToken + + +router = APIRouter() + + +# Dependency +def get_db() -> Session: + try: + db = SessionLocal() + yield db + finally: + db.close() + + +@router.get("/prefill-customer-discount", response_model=PrefillCustomerDiscount) +def get_prefill_customer_discount( + db: Session = Depends(get_db), + user: UserToken = Security(get_user), +) -> PrefillCustomerDiscount: + value = db.query(DbSetting).filter(DbSetting.name == "Prefill Customer Discount").first().data["Value"] + return PrefillCustomerDiscount(value=value) + + +@router.post("/prefill-customer-discount", response_model=PrefillCustomerDiscount) +def set_prefill_customer_discount( + data: PrefillCustomerDiscount, + db: Session = Depends(get_db), + user: UserToken = Security(get_user, scopes=["settings"]), +) -> PrefillCustomerDiscount: + item = db.query(DbSetting).filter(DbSetting.name == "Prefill Customer Discount").first() + item.data = {"Value": data.value} + db.commit() + return PrefillCustomerDiscount(value=item.data["Value"]) diff --git a/barker/barker/routers/sale_category.py b/barker/barker/routers/sale_category.py index 9c0199f..6735503 100644 --- a/barker/barker/routers/sale_category.py +++ b/barker/barker/routers/sale_category.py @@ -109,14 +109,6 @@ def show_list(db: Session = Depends(get_db), user: UserToken = Depends(get_user) return [sale_category_info(item) for item in db.query(SaleCategory).order_by(SaleCategory.name).all()] -@router.get("/for-discount", response_model=List[schemas.SaleCategoryForDiscount]) -def for_discount(db: Session = Depends(get_db), user: UserToken = Depends(get_user)) -> List[schemas.SaleCategory]: - return [ - schemas.SaleCategoryForDiscount(id=item.id, name=item.name, discountLimit=item.discount_limit, discount=0) - for item in db.query(SaleCategory).filter(SaleCategory.discount_limit != 0).order_by(SaleCategory.name).all() - ] - - @router.get("/{id_}", response_model=schemas.SaleCategory) def show_id( id_: uuid.UUID, diff --git a/barker/barker/schemas/customer.py b/barker/barker/schemas/customer.py index 2c08565..7980980 100644 --- a/barker/barker/schemas/customer.py +++ b/barker/barker/schemas/customer.py @@ -1,18 +1,32 @@ import uuid -from typing import Optional +from decimal import Decimal +from typing import List, Optional from pydantic import BaseModel, Field from . import to_camel +class DiscountItem(BaseModel): + id_: uuid.UUID + name: str + discount: Decimal = Field(ge=0, multiple_of=0.0001, default=0, le=1) + discount_limit: Optional[Decimal] + customer_discount: Optional[Decimal] + + class Config: + alias_generator = to_camel + + class CustomerIn(BaseModel): name: str = Field(..., min_length=1) # phone: str = Field(..., min_length=1) phone: str address: Optional[str] + discounts: List[DiscountItem] + class Config: anystr_strip_whitespace = True alias_generator = to_camel diff --git a/barker/barker/schemas/settings.py b/barker/barker/schemas/settings.py new file mode 100644 index 0000000..f799140 --- /dev/null +++ b/barker/barker/schemas/settings.py @@ -0,0 +1,5 @@ +from pydantic import BaseModel + + +class PrefillCustomerDiscount(BaseModel): + value: bool diff --git a/bookie/src/app/app-routing.module.ts b/bookie/src/app/app-routing.module.ts index 6913db5..e0e2180 100644 --- a/bookie/src/app/app-routing.module.ts +++ b/bookie/src/app/app-routing.module.ts @@ -110,6 +110,10 @@ const routes: Routes = [ loadChildren: () => import('./section-printers/section-printers.module').then((mod) => mod.SectionPrintersModule), }, + { + path: 'settings', + loadChildren: () => import('./settings/settings.module').then((mod) => mod.SettingsModule), + }, { path: 'settle-options', loadChildren: () => diff --git a/bookie/src/app/core/customer-discount.ts b/bookie/src/app/core/customer-discount.ts new file mode 100644 index 0000000..17917a2 --- /dev/null +++ b/bookie/src/app/core/customer-discount.ts @@ -0,0 +1,12 @@ +export class CustomerDiscount { + id: string; + name: string; + discount: number; + + public constructor(init?: Partial) { + this.id = ''; + this.name = ''; + this.discount = 0; + Object.assign(this, init); + } +} diff --git a/bookie/src/app/core/customer.ts b/bookie/src/app/core/customer.ts index be92423..f445c13 100644 --- a/bookie/src/app/core/customer.ts +++ b/bookie/src/app/core/customer.ts @@ -1,14 +1,18 @@ +import { CustomerDiscount } from './customer-discount'; + export class Customer { id: string; name: string; phone: string; address: string; + discounts: CustomerDiscount[]; public constructor(init?: Partial) { this.id = ''; this.name = ''; this.phone = ''; this.address = ''; + this.discounts = []; Object.assign(this, init); } } diff --git a/bookie/src/app/customers/customer-detail/customer-detail.component.html b/bookie/src/app/customers/customer-detail/customer-detail.component.html index 44d9ebc..bdf50ca 100644 --- a/bookie/src/app/customers/customer-detail/customer-detail.component.html +++ b/bookie/src/app/customers/customer-detail/customer-detail.component.html @@ -38,9 +38,28 @@ > Address - + + +
+
+ + Discount on {{ r.name }} + + % + +
+
diff --git a/bookie/src/app/customers/customer-detail/customer-detail.component.ts b/bookie/src/app/customers/customer-detail/customer-detail.component.ts index f35f60c..9cc7c04 100644 --- a/bookie/src/app/customers/customer-detail/customer-detail.component.ts +++ b/bookie/src/app/customers/customer-detail/customer-detail.component.ts @@ -2,6 +2,7 @@ import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angula import { AbstractControl, FormArray, FormBuilder, FormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Router } from '@angular/router'; +import { round } from 'mathjs'; import { Customer } from '../../core/customer'; import { ToasterService } from '../../core/toaster.service'; @@ -33,6 +34,7 @@ export class CustomerDetailComponent implements OnInit, AfterViewInit { name: '', phone: '', address: '', + discounts: this.fb.array([]), }); } @@ -48,6 +50,16 @@ export class CustomerDetailComponent implements OnInit, AfterViewInit { (this.form.get('name') as AbstractControl).setValue(item.name); (this.form.get('phone') as AbstractControl).setValue(item.phone); (this.form.get('address') as AbstractControl).setValue(item.address); + this.form.setControl( + 'discounts', + this.fb.array( + item.discounts.map((x) => + this.fb.group({ + discount: '' + x.discount * 100, + }), + ), + ), + ); } ngAfterViewInit() { @@ -100,6 +112,13 @@ export class CustomerDetailComponent implements OnInit, AfterViewInit { this.item.name = formModel.name; this.item.phone = formModel.phone; this.item.address = formModel.address; + const array = this.form.get('discounts') as FormArray; + this.item.discounts.forEach((item, index) => { + item.discount = Math.max( + Math.min(round(array.controls[index].value.discount / 100, 5), 100), + 0, + ); + }); return this.item; } } diff --git a/bookie/src/app/customers/customer-discounts.service.spec.ts b/bookie/src/app/customers/customer-discounts.service.spec.ts new file mode 100644 index 0000000..186bb3e --- /dev/null +++ b/bookie/src/app/customers/customer-discounts.service.spec.ts @@ -0,0 +1,18 @@ +import { inject, TestBed } from '@angular/core/testing'; + +import { CustomerDiscountsService } from './customer-discounts.service'; + +describe('CustomerDiscountsService', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [CustomerDiscountsService], + }); + }); + + it('should be created', inject( + [CustomerDiscountsService], + (service: CustomerDiscountsService) => { + expect(service).toBeTruthy(); + }, + )); +}); diff --git a/bookie/src/app/customers/customer-discounts.service.ts b/bookie/src/app/customers/customer-discounts.service.ts new file mode 100644 index 0000000..4445110 --- /dev/null +++ b/bookie/src/app/customers/customer-discounts.service.ts @@ -0,0 +1,37 @@ +import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs/internal/Observable'; +import { catchError } from 'rxjs/operators'; + +import { ErrorLoggerService } from '../core/error-logger.service'; +import { DiscountItem } from '../sales/discount/discount-item'; + +const httpOptions = { + headers: new HttpHeaders({ 'Content-Type': 'application/json' }), +}; +const url = '/api/customer-discounts'; +const serviceName = 'CustomerService'; + +@Injectable({ + providedIn: 'root', +}) +export class CustomerDiscountsService { + constructor(private http: HttpClient, private log: ErrorLoggerService) {} + + list(id: string | undefined): Observable { + const getUrl: string = id === undefined ? `${url}` : `${url}/${id}`; + return this.http + .get(getUrl) + .pipe(catchError(this.log.handleError(serviceName, `get id=${id}`))) as Observable< + DiscountItem[] + >; + } + + listForDiscount(): Observable<{ name: string; discount: number; discountLimit: number }[]> { + return this.http + .get<{ name: string; discount: number; discountLimit: number }[]>(`${url}/for-discount`) + .pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable< + { name: string; discount: number; discountLimit: number }[] + >; + } +} diff --git a/bookie/src/app/customers/customer-list/customer-list.component.html b/bookie/src/app/customers/customer-list/customer-list.component.html index 6166185..6e96d65 100644 --- a/bookie/src/app/customers/customer-list/customer-list.component.html +++ b/bookie/src/app/customers/customer-list/customer-list.component.html @@ -28,6 +28,18 @@ {{ row.address }} + + + Discounts + +
    +
  • + {{ discount.name }} - {{ discount.discount | percent: '1.2-2' }} +
  • +
+
+
+ diff --git a/bookie/src/app/customers/customer-list/customer-list.component.ts b/bookie/src/app/customers/customer-list/customer-list.component.ts index 6c5c056..4312e9f 100644 --- a/bookie/src/app/customers/customer-list/customer-list.component.ts +++ b/bookie/src/app/customers/customer-list/customer-list.component.ts @@ -14,7 +14,7 @@ export class CustomerListComponent implements OnInit { dataSource: CustomerListDatasource = new CustomerListDatasource([]); list: Customer[] = []; /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ - displayedColumns = ['name', 'phone', 'address']; + displayedColumns = ['name', 'phone', 'address', 'discounts']; constructor(private route: ActivatedRoute) {} diff --git a/bookie/src/app/home/home.component.html b/bookie/src/app/home/home.component.html index 1b2f191..45cb7e0 100644 --- a/bookie/src/app/home/home.component.html +++ b/bookie/src/app/home/home.component.html @@ -250,6 +250,15 @@ >

Settle Options

+ +

Settings

+