From 2f440a412731bda60fd0c378196160a92565f369 Mon Sep 17 00:00:00 2001 From: tanshu Date: Fri, 6 Aug 2021 08:23:36 +0530 Subject: [PATCH] Feature: Sale Category also shows the products in it to make it easier to check for errors. --- barker/barker/routers/product.py | 125 ++++++++++---- bookie/src/app/product/product.service.ts | 9 + .../product-list-resolver.service.ts | 21 +++ .../sale-categories-routing.module.ts | 3 + .../sale-category-detail-datasource.ts | 24 +++ .../sale-category-detail.component.html | 163 +++++++++++------- .../sale-category-detail.component.ts | 10 +- .../sale-category-list.component.ts | 1 + 8 files changed, 260 insertions(+), 96 deletions(-) create mode 100644 bookie/src/app/sale-category/product-list-resolver.service.ts create mode 100644 bookie/src/app/sale-category/sale-category-detail/sale-category-detail-datasource.ts diff --git a/barker/barker/routers/product.py b/barker/barker/routers/product.py index bea607d..0dea117 100644 --- a/barker/barker/routers/product.py +++ b/barker/barker/routers/product.py @@ -1,7 +1,7 @@ import uuid from datetime import date, timedelta -from typing import List +from typing import List, Optional import barker.schemas.product as schemas @@ -299,45 +299,106 @@ def product_list(date_: date, db: Session) -> List[schemas.Product]: @router.get("/query") async def show_term( - mc: uuid.UUID = None, + mc: Optional[uuid.UUID] = None, + sc: Optional[uuid.UUID] = None, date_: date = Depends(effective_date), current_user: UserToken = Depends(get_user), ): list_ = [] + query = select(ProductVersion) + if sc is not None: + query = query.join(ProductVersion.menu_category) + if mc is not None: + query = query.join(ProductVersion.sale_category).join(SaleCategory.tax) + query = query.where( + and_( + or_( + ProductVersion.valid_from == None, # noqa: E711 + ProductVersion.valid_from <= date_, + ), + or_( + ProductVersion.valid_till == None, # noqa: E711 + ProductVersion.valid_till >= date_, + ), + ) + ) + if mc is not None: + query = query.where(ProductVersion.menu_category_id == mc).order_by( + ProductVersion.sort_order, ProductVersion.name + ) + if sc is not None: + query = query.where(ProductVersion.sale_category_id == sc).order_by( + MenuCategory.sort_order, ProductVersion.sort_order, ProductVersion.name + ) + + if mc is not None: + query = query.options( + joinedload(ProductVersion.sale_category, innerjoin=True), + joinedload(ProductVersion.sale_category, SaleCategory.tax, innerjoin=True), + contains_eager(ProductVersion.sale_category), + contains_eager(ProductVersion.sale_category, SaleCategory.tax), + ) + + if sc is not None: + query = query.options( + joinedload(ProductVersion.menu_category, innerjoin=True), + contains_eager(ProductVersion.menu_category), + ) + with SessionFuture() as db: - for item in ( - db.execute( - select(ProductVersion) - .join(ProductVersion.sale_category) - .join(SaleCategory.tax) - .where( - and_( - ProductVersion.menu_category_id == mc, - or_( - ProductVersion.valid_from == None, # noqa: E711 - ProductVersion.valid_from <= date_, - ), - or_( - ProductVersion.valid_till == None, # noqa: E711 - ProductVersion.valid_till >= date_, - ), - ) + for item in db.execute(query).scalars().all(): + if sc is not None: + list_.append( + { + "id": item.product_id, + "name": item.full_name, + "menuCategory": { + "id": item.menu_category_id, + "name": item.menu_category.name, + }, + "price": item.price, + } ) - .order_by(ProductVersion.sort_order, ProductVersion.name) - .options( - joinedload(ProductVersion.sale_category, innerjoin=True), - joinedload(ProductVersion.sale_category, SaleCategory.tax, innerjoin=True), - contains_eager(ProductVersion.sale_category), - contains_eager(ProductVersion.sale_category, SaleCategory.tax), + if mc is not None: + list_.append(query_product_info(item, False)) + if item.has_happy_hour: + list_.append(query_product_info(item, True)) + return list_ + + +def product_list_of_sale_category(date_: date, db: Session) -> List[schemas.Product]: + return [ + product_info(item) + for item in db.execute( + select(ProductVersion) + .join(ProductVersion.menu_category) + .join(ProductVersion.sale_category) + .where( + and_( + or_( + ProductVersion.valid_from == None, # noqa: E711 + ProductVersion.valid_from <= date_, + ), + or_( + ProductVersion.valid_till == None, # noqa: E711 + ProductVersion.valid_till >= date_, + ), ) ) - .scalars() - .all() - ): - list_.append(query_product_info(item, False)) - if item.has_happy_hour: - list_.append(query_product_info(item, True)) - return list_ + .order_by(MenuCategory.sort_order) + .order_by(MenuCategory.name) + .order_by(ProductVersion.sort_order) + .order_by(ProductVersion.name) + .options( + joinedload(ProductVersion.menu_category, innerjoin=True), + joinedload(ProductVersion.sale_category, innerjoin=True), + contains_eager(ProductVersion.menu_category), + contains_eager(ProductVersion.sale_category), + ) + ) + .scalars() + .all() + ] @router.get("/{id_}", response_model=schemas.Product) diff --git a/bookie/src/app/product/product.service.ts b/bookie/src/app/product/product.service.ts index dd0acc7..2be041d 100644 --- a/bookie/src/app/product/product.service.ts +++ b/bookie/src/app/product/product.service.ts @@ -30,6 +30,15 @@ export class ProductService { .pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable; } + listOfSaleCategory(id: string): Observable { + const options = { params: new HttpParams().set('sc', id) }; + return this.http + .get(`${url}/query`, options) + .pipe(catchError(this.log.handleError(serviceName, 'listOfSaleCategory'))) as Observable< + Product[] + >; + } + listIsActiveOfCategory(id: string): Observable { const options = { params: new HttpParams().set('mc', id) }; return this.http diff --git a/bookie/src/app/sale-category/product-list-resolver.service.ts b/bookie/src/app/sale-category/product-list-resolver.service.ts new file mode 100644 index 0000000..4a86906 --- /dev/null +++ b/bookie/src/app/sale-category/product-list-resolver.service.ts @@ -0,0 +1,21 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, Resolve } from '@angular/router'; +import { Observable, of as observableOf } from 'rxjs'; + +import { Product } from '../core/product'; +import { ProductService } from '../product/product.service'; + +@Injectable({ + providedIn: 'root', +}) +export class ProductListResolver implements Resolve { + constructor(private ser: ProductService) {} + + resolve(route: ActivatedRouteSnapshot): Observable { + const id = route.paramMap.get('id'); + if (id === null) { + return observableOf([]); + } + return this.ser.listOfSaleCategory(id); + } +} diff --git a/bookie/src/app/sale-category/sale-categories-routing.module.ts b/bookie/src/app/sale-category/sale-categories-routing.module.ts index dc6cbc0..7dbee31 100644 --- a/bookie/src/app/sale-category/sale-categories-routing.module.ts +++ b/bookie/src/app/sale-category/sale-categories-routing.module.ts @@ -5,6 +5,7 @@ import { RouterModule, Routes } from '@angular/router'; import { AuthGuard } from '../auth/auth-guard.service'; import { TaxListResolver } from '../taxes/tax-list-resolver.service'; +import { ProductListResolver } from './product-list-resolver.service'; import { SaleCategoryDetailComponent } from './sale-category-detail/sale-category-detail.component'; import { SaleCategoryListResolver } from './sale-category-list-resolver.service'; import { SaleCategoryListComponent } from './sale-category-list/sale-category-list.component'; @@ -32,6 +33,7 @@ const saleCategoriesRoutes: Routes = [ resolve: { item: SaleCategoryResolver, taxes: TaxListResolver, + products: ProductListResolver, }, }, { @@ -44,6 +46,7 @@ const saleCategoriesRoutes: Routes = [ resolve: { item: SaleCategoryResolver, taxes: TaxListResolver, + products: ProductListResolver, }, }, ]; diff --git a/bookie/src/app/sale-category/sale-category-detail/sale-category-detail-datasource.ts b/bookie/src/app/sale-category/sale-category-detail/sale-category-detail-datasource.ts new file mode 100644 index 0000000..88f9363 --- /dev/null +++ b/bookie/src/app/sale-category/sale-category-detail/sale-category-detail-datasource.ts @@ -0,0 +1,24 @@ +import { DataSource } from '@angular/cdk/collections'; +import { Observable } from 'rxjs'; +import { tap } from 'rxjs/operators'; + +import { Product } from '../../core/product'; + +export class SaleCategoryDetailDatasource extends DataSource { + private data: Product[] = []; + + constructor(private readonly dataObs: Observable) { + super(); + this.dataObs = dataObs.pipe( + tap((x) => { + this.data = x; + }), + ); + } + + connect(): Observable { + return this.dataObs; + } + + disconnect() {} +} diff --git a/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.html b/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.html index 844b06c..d3a11a7 100644 --- a/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.html +++ b/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.html @@ -1,64 +1,101 @@ -
- - - Sale Category - - -
-
- - Name - - -
-
- - Discount Limit - - % - -
-
- - Tax - - - {{ t.name }} - - - -
-
-
- - - - -
+
+
+ + + Sale Category + + +
+
+ + Name + + +
+
+ + Discount Limit + + % + +
+
+ + Tax + + + {{ t.name }} + + + +
+
+
+ + + + +
+
+
+ + + Products + + + + + + Name + {{ row.name }} + + + + + Price + {{ + row.price | currency: 'INR' + }} + + + + + Menu Category + {{ row.menuCategory.name }} + + + + + + + +
diff --git a/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.ts b/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.ts index 2ffa049..44d2c2b 100644 --- a/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.ts +++ b/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.ts @@ -3,13 +3,17 @@ import { FormBuilder, FormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Router } from '@angular/router'; import { round } from 'mathjs'; +import { BehaviorSubject } from 'rxjs'; +import { Product } from '../../core/product'; import { SaleCategory } from '../../core/sale-category'; import { Tax } from '../../core/tax'; import { ToasterService } from '../../core/toaster.service'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; import { SaleCategoryService } from '../sale-category.service'; +import { SaleCategoryDetailDatasource } from './sale-category-detail-datasource'; + @Component({ selector: 'app-sale-category-detail', templateUrl: './sale-category-detail.component.html', @@ -20,6 +24,9 @@ export class SaleCategoryDetailComponent implements OnInit, AfterViewInit { form: FormGroup; taxes: Tax[] = []; item: SaleCategory = new SaleCategory(); + products: BehaviorSubject = new BehaviorSubject([]); + dataSource: SaleCategoryDetailDatasource = new SaleCategoryDetailDatasource(this.products); + displayedColumns = ['name', 'price', 'menuCategory']; constructor( private route: ActivatedRoute, @@ -39,9 +46,10 @@ export class SaleCategoryDetailComponent implements OnInit, AfterViewInit { ngOnInit() { this.route.data.subscribe((value) => { - const data = value as { item: SaleCategory; taxes: Tax[] }; + const data = value as { item: SaleCategory; taxes: Tax[]; products: Product[] }; this.showItem(data.item); this.taxes = data.taxes; + this.products.next(data.products); }); } diff --git a/bookie/src/app/sale-category/sale-category-list/sale-category-list.component.ts b/bookie/src/app/sale-category/sale-category-list/sale-category-list.component.ts index 4d43874..97a305b 100644 --- a/bookie/src/app/sale-category/sale-category-list/sale-category-list.component.ts +++ b/bookie/src/app/sale-category/sale-category-list/sale-category-list.component.ts @@ -3,6 +3,7 @@ import { MatTable } from '@angular/material/table'; import { ActivatedRoute, Router } from '@angular/router'; import { BehaviorSubject } from 'rxjs'; +import { Product } from '../../core/product'; import { SaleCategory } from '../../core/sale-category'; import { ToasterService } from '../../core/toaster.service'; import { SaleCategoryService } from '../sale-category.service';