DB Normalization: Moved fractionUnits back to Product from SKU as it is better suited there.
Feature: Created the ProductSku schema for the product/sku autocomplete
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
import { Product } from './product';
|
||||
import { ProductSku } from './product-sku';
|
||||
|
||||
export class Batch {
|
||||
id: string | null;
|
||||
@ -7,7 +8,7 @@ export class Batch {
|
||||
tax: number;
|
||||
discount: number;
|
||||
rate: number;
|
||||
sku: Product;
|
||||
sku: ProductSku;
|
||||
|
||||
public constructor(init?: Partial<Batch>) {
|
||||
this.id = null;
|
||||
@ -16,7 +17,7 @@ export class Batch {
|
||||
this.tax = 0;
|
||||
this.discount = 0;
|
||||
this.rate = 0;
|
||||
this.sku = new Product();
|
||||
this.sku = new ProductSku();
|
||||
Object.assign(this, init);
|
||||
}
|
||||
}
|
||||
|
||||
24
overlord/src/app/core/product-sku.ts
Normal file
24
overlord/src/app/core/product-sku.ts
Normal file
@ -0,0 +1,24 @@
|
||||
export class ProductSku {
|
||||
id: string;
|
||||
name: string;
|
||||
costPrice: number;
|
||||
salePrice: number;
|
||||
fraction: number;
|
||||
productYield: number;
|
||||
fractionUnits: string;
|
||||
|
||||
isRateContracted: boolean;
|
||||
|
||||
public constructor(init?: Partial<ProductSku>) {
|
||||
this.id = '';
|
||||
this.name = '';
|
||||
this.costPrice = 0;
|
||||
this.salePrice = 0;
|
||||
this.fraction = 0;
|
||||
this.productYield = 0;
|
||||
this.fractionUnits = '';
|
||||
this.isRateContracted = false;
|
||||
|
||||
Object.assign(this, init);
|
||||
}
|
||||
}
|
||||
@ -1,21 +1,17 @@
|
||||
import { ProductGroup } from './product-group';
|
||||
|
||||
export class StockKeepingUnit {
|
||||
isDefault: boolean;
|
||||
units: string;
|
||||
fraction: number;
|
||||
fractionUnits: string;
|
||||
productYield: number;
|
||||
price: number;
|
||||
costPrice: number;
|
||||
salePrice: number;
|
||||
|
||||
public constructor(init?: Partial<StockKeepingUnit>) {
|
||||
this.isDefault = false;
|
||||
this.units = '';
|
||||
this.fraction = 1;
|
||||
this.fractionUnits = '';
|
||||
this.productYield = 1;
|
||||
this.price = 0;
|
||||
this.costPrice = 0;
|
||||
this.salePrice = 0;
|
||||
Object.assign(this, init);
|
||||
}
|
||||
@ -26,7 +22,6 @@ export class Product {
|
||||
code: number;
|
||||
name: string;
|
||||
skus: StockKeepingUnit[];
|
||||
price: number | undefined;
|
||||
fractionUnits: string | undefined;
|
||||
|
||||
isActive: boolean;
|
||||
@ -34,7 +29,6 @@ export class Product {
|
||||
isPurchased: boolean;
|
||||
isSold: boolean;
|
||||
productGroup?: ProductGroup;
|
||||
isRateContracted?: boolean;
|
||||
|
||||
public constructor(init?: Partial<Product>) {
|
||||
this.code = 0;
|
||||
|
||||
@ -9,6 +9,7 @@ import { Observable, of as observableOf } from 'rxjs';
|
||||
import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators';
|
||||
|
||||
import { Product } from '../core/product';
|
||||
import { ProductSku } from '../core/product-sku';
|
||||
import { ProductService } from '../product/product.service';
|
||||
import { ToCsvService } from '../shared/to-csv.service';
|
||||
|
||||
@ -49,7 +50,7 @@ export class ProductLedgerComponent implements OnInit, AfterViewInit {
|
||||
'runningAmount',
|
||||
];
|
||||
|
||||
products: Observable<Product[]>;
|
||||
products: Observable<ProductSku[]>;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
@ -71,7 +72,7 @@ export class ProductLedgerComponent implements OnInit, AfterViewInit {
|
||||
debounceTime(150),
|
||||
distinctUntilChanged(),
|
||||
switchMap((x) =>
|
||||
x === null ? observableOf([]) : this.productSer.autocomplete(x, null, false, false),
|
||||
x === null ? observableOf([]) : this.productSer.autocompleteProduct(x, null),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -16,10 +16,6 @@
|
||||
<mat-label>Fraction</mat-label>
|
||||
<input matInput type="number" placeholder="Fraction" formControlName="fraction" />
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex>
|
||||
<mat-label>Fraction Units</mat-label>
|
||||
<input matInput placeholder="Fraction Units" formControlName="fractionUnits" />
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex>
|
||||
<mat-label>Yield</mat-label>
|
||||
<input matInput type="number" placeholder="Yield" formControlName="productYield" />
|
||||
@ -30,7 +26,7 @@
|
||||
matInput
|
||||
type="number"
|
||||
placeholder="{{ data.isPurchased ? 'Purchase Price' : 'Cost Price' }}"
|
||||
formControlName="price"
|
||||
formControlName="costPrice"
|
||||
/>
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex [hidden]="!data.isSold">
|
||||
|
||||
@ -21,9 +21,8 @@ export class ProductDetailDialogComponent implements OnInit {
|
||||
this.form = this.fb.group({
|
||||
units: '',
|
||||
fraction: '',
|
||||
fractionUnits: '',
|
||||
productYield: '',
|
||||
price: '',
|
||||
costPrice: '',
|
||||
salePrice: '',
|
||||
});
|
||||
}
|
||||
@ -32,9 +31,8 @@ export class ProductDetailDialogComponent implements OnInit {
|
||||
this.form.setValue({
|
||||
units: this.data.item.units,
|
||||
fraction: '' + this.data.item.fraction,
|
||||
fractionUnits: this.data.item.fractionUnits,
|
||||
productYield: '' + this.data.item.productYield,
|
||||
price: '' + this.data.item.price,
|
||||
costPrice: '' + this.data.item.costPrice,
|
||||
salePrice: '' + this.data.item.salePrice,
|
||||
});
|
||||
}
|
||||
@ -49,8 +47,8 @@ export class ProductDetailDialogComponent implements OnInit {
|
||||
if (productYield < 0 || productYield > 1) {
|
||||
return;
|
||||
}
|
||||
const price = +formValue.price;
|
||||
if (price < 0) {
|
||||
const costPrice = +formValue.costPrice;
|
||||
if (costPrice < 0) {
|
||||
return;
|
||||
}
|
||||
const salePrice = +formValue.salePrice;
|
||||
@ -59,9 +57,8 @@ export class ProductDetailDialogComponent implements OnInit {
|
||||
}
|
||||
this.data.item.units = formValue.units;
|
||||
this.data.item.fraction = fraction;
|
||||
this.data.item.fractionUnits = formValue.fractionUnits;
|
||||
this.data.item.productYield = productYield;
|
||||
this.data.item.price = price;
|
||||
this.data.item.costPrice = costPrice;
|
||||
this.data.item.salePrice = salePrice;
|
||||
this.dialogRef.close(this.data.item);
|
||||
}
|
||||
|
||||
@ -24,10 +24,14 @@
|
||||
fxLayoutGap="20px"
|
||||
fxLayoutGap.lt-md="0px"
|
||||
>
|
||||
<mat-form-field fxFlex>
|
||||
<mat-form-field fxFlex="80">
|
||||
<mat-label>Name</mat-label>
|
||||
<input matInput #nameElement placeholder="Name" formControlName="name" />
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex="20">
|
||||
<mat-label>Fraction Units</mat-label>
|
||||
<input matInput placeholder="Fraction Units" formControlName="fractionUnits" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div
|
||||
fxLayout="row"
|
||||
@ -73,10 +77,6 @@
|
||||
<mat-label>Fraction</mat-label>
|
||||
<input matInput type="number" placeholder="Fraction" formControlName="fraction" />
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex>
|
||||
<mat-label>Fraction Units</mat-label>
|
||||
<input matInput placeholder="Fraction Units" formControlName="fractionUnits" />
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex>
|
||||
<mat-label>Yield</mat-label>
|
||||
<input matInput type="number" placeholder="Yield" formControlName="productYield" />
|
||||
@ -87,7 +87,7 @@
|
||||
matInput
|
||||
type="number"
|
||||
placeholder="{{ item.isPurchased ? 'Purchase Price' : 'Cost Price' }}"
|
||||
formControlName="price"
|
||||
formControlName="costPrice"
|
||||
/>
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex>
|
||||
@ -98,18 +98,6 @@
|
||||
</div>
|
||||
</form>
|
||||
<mat-table [dataSource]="dataSource" aria-label="Elements">
|
||||
<!-- Checkbox Column -->
|
||||
<ng-container matColumnDef="isDefault">
|
||||
<mat-header-cell *matHeaderCellDef>Default</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row">
|
||||
<mat-checkbox
|
||||
(click)="$event.stopPropagation()"
|
||||
(change)="changeDefault($event, row)"
|
||||
[checked]="row.isDefault"
|
||||
>
|
||||
</mat-checkbox>
|
||||
</mat-cell>
|
||||
</ng-container>
|
||||
<!-- Units Column -->
|
||||
<ng-container matColumnDef="units">
|
||||
<mat-header-cell *matHeaderCellDef>Units</mat-header-cell>
|
||||
@ -122,22 +110,18 @@
|
||||
<mat-cell *matCellDef="let row">{{ row.fraction }}</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<!-- Fraction Units Column -->
|
||||
<ng-container matColumnDef="fractionUnits">
|
||||
<mat-header-cell *matHeaderCellDef>Fraction Units</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row">{{ row.fractionUnits }}</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<!-- Yield Column -->
|
||||
<ng-container matColumnDef="yield">
|
||||
<mat-header-cell *matHeaderCellDef class="right">Yield</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row" class="right">{{ row.productYield }}</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<!-- Price Column -->
|
||||
<ng-container matColumnDef="price">
|
||||
<mat-header-cell *matHeaderCellDef class="right">Price</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row" class="right">{{ row.price | currency: 'INR' }}</mat-cell>
|
||||
<!-- Cost Price Column -->
|
||||
<ng-container matColumnDef="costPrice">
|
||||
<mat-header-cell *matHeaderCellDef class="right">Cost Price</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row" class="right">{{
|
||||
row.costPrice | currency: 'INR'
|
||||
}}</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<!-- Sale Price Column -->
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core';
|
||||
import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
|
||||
import { MatCheckboxChange } from '@angular/material/checkbox';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
@ -27,16 +26,7 @@ export class ProductDetailComponent implements OnInit, AfterViewInit {
|
||||
dataSource: ProductDetailDatasource = new ProductDetailDatasource(this.skus);
|
||||
item: Product = new Product();
|
||||
|
||||
displayedColumns = [
|
||||
'isDefault',
|
||||
'units',
|
||||
'fraction',
|
||||
'fractionUnits',
|
||||
'yield',
|
||||
'price',
|
||||
'salePrice',
|
||||
'action',
|
||||
];
|
||||
displayedColumns = ['units', 'fraction', 'yield', 'costPrice', 'salePrice', 'action'];
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
@ -49,12 +39,12 @@ export class ProductDetailComponent implements OnInit, AfterViewInit {
|
||||
this.form = this.fb.group({
|
||||
code: { value: '', disabled: true },
|
||||
name: '',
|
||||
fractionUnits: '',
|
||||
addRow: this.fb.group({
|
||||
units: '',
|
||||
fraction: '',
|
||||
fractionUnits: '',
|
||||
productYield: '',
|
||||
price: '',
|
||||
costPrice: '',
|
||||
salePrice: '',
|
||||
}),
|
||||
isPurchased: '',
|
||||
@ -79,13 +69,13 @@ export class ProductDetailComponent implements OnInit, AfterViewInit {
|
||||
this.item = item;
|
||||
this.form.setValue({
|
||||
code: this.item.code || '(Auto)',
|
||||
name: this.item.name || '',
|
||||
name: this.item.name,
|
||||
fractionUnits: this.item.fractionUnits,
|
||||
addRow: {
|
||||
units: '',
|
||||
fraction: '',
|
||||
fractionUnits: '',
|
||||
productYield: '',
|
||||
price: '',
|
||||
costPrice: '',
|
||||
salePrice: '',
|
||||
},
|
||||
isPurchased: this.item.isPurchased,
|
||||
@ -115,8 +105,8 @@ export class ProductDetailComponent implements OnInit, AfterViewInit {
|
||||
this.toaster.show('Danger', 'Product Yield has to be > 0 and <= 1');
|
||||
return;
|
||||
}
|
||||
const price = +formValue.price;
|
||||
if (price < 0) {
|
||||
const costPrice = +formValue.costPrice;
|
||||
if (costPrice < 0) {
|
||||
this.toaster.show('Danger', 'Price has to be >= 0');
|
||||
return;
|
||||
}
|
||||
@ -129,9 +119,8 @@ export class ProductDetailComponent implements OnInit, AfterViewInit {
|
||||
new StockKeepingUnit({
|
||||
units: formValue.units,
|
||||
fraction,
|
||||
fractionUnits: formValue.fractionUnits,
|
||||
productYield,
|
||||
price,
|
||||
costPrice,
|
||||
salePrice,
|
||||
}),
|
||||
);
|
||||
@ -143,9 +132,8 @@ export class ProductDetailComponent implements OnInit, AfterViewInit {
|
||||
(this.form.get('addRow') as FormControl).reset({
|
||||
units: '',
|
||||
fraction: '',
|
||||
fractionUnits: '',
|
||||
productYield: '',
|
||||
price: '',
|
||||
costPrice: '',
|
||||
salePrice: '',
|
||||
});
|
||||
}
|
||||
@ -216,6 +204,7 @@ export class ProductDetailComponent implements OnInit, AfterViewInit {
|
||||
getItem(): Product {
|
||||
const formModel = this.form.value;
|
||||
this.item.name = formModel.name;
|
||||
this.item.fractionUnits = formModel.fractionUnits;
|
||||
this.item.isPurchased = formModel.isPurchased;
|
||||
this.item.isSold = formModel.isSold;
|
||||
this.item.isActive = formModel.isActive;
|
||||
@ -225,9 +214,4 @@ export class ProductDetailComponent implements OnInit, AfterViewInit {
|
||||
this.item.productGroup.id = formModel.productGroup;
|
||||
return this.item;
|
||||
}
|
||||
|
||||
changeDefault($event: MatCheckboxChange, row: StockKeepingUnit) {
|
||||
this.item.skus.forEach((x) => (x.isDefault = false));
|
||||
row.isDefault = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@
|
||||
<li *ngFor="let sku of row.skus">
|
||||
<a [routerLink]="['/products', row.id]"
|
||||
>{{ row.name }} ({{
|
||||
showExtended ? sku.fraction + ' ' + sku.fractionUnits + ' = 1 ' : ''
|
||||
showExtended ? sku.fraction + ' ' + row.fractionUnits + ' = 1 ' : ''
|
||||
}}{{ sku.units }})</a
|
||||
>
|
||||
</li>
|
||||
@ -53,7 +53,7 @@
|
||||
<mat-cell *matCellDef="let row">
|
||||
<ul>
|
||||
<li *ngFor="let sku of row.skus">
|
||||
{{ sku.price | currency: 'INR' }}
|
||||
{{ sku.costPrice | currency: 'INR' }}
|
||||
</li>
|
||||
</ul>
|
||||
</mat-cell>
|
||||
|
||||
@ -5,6 +5,7 @@ import { catchError } from 'rxjs/operators';
|
||||
|
||||
import { ErrorLoggerService } from '../core/error-logger.service';
|
||||
import { Product } from '../core/product';
|
||||
import { ProductSku } from '../core/product-sku';
|
||||
|
||||
const url = '/api/products';
|
||||
const serviceName = 'ProductService';
|
||||
@ -51,16 +52,28 @@ export class ProductService {
|
||||
.pipe(catchError(this.log.handleError(serviceName, 'delete'))) as Observable<Product>;
|
||||
}
|
||||
|
||||
autocomplete(
|
||||
autocompleteProduct(query: string, isPurchased: boolean | null): Observable<ProductSku[]> {
|
||||
const options = {
|
||||
params: new HttpParams().set('q', query),
|
||||
};
|
||||
if (isPurchased !== null) {
|
||||
options.params = options.params.set('p', isPurchased.toString());
|
||||
}
|
||||
return this.http
|
||||
.get<ProductSku[]>(`${url}/q-product`, options)
|
||||
.pipe(catchError(this.log.handleError(serviceName, 'autocomplete'))) as Observable<
|
||||
ProductSku[]
|
||||
>;
|
||||
}
|
||||
|
||||
autocompleteSku(
|
||||
query: string,
|
||||
isPurchased: boolean | null,
|
||||
extended: boolean = false,
|
||||
skus: boolean = true,
|
||||
date?: string,
|
||||
vendorId?: string,
|
||||
): Observable<Product[]> {
|
||||
): Observable<ProductSku[]> {
|
||||
const options = {
|
||||
params: new HttpParams().set('q', query).set('e', extended.toString()).set('s', skus),
|
||||
params: new HttpParams().set('q', query),
|
||||
};
|
||||
if (isPurchased !== null) {
|
||||
options.params = options.params.set('p', isPurchased.toString());
|
||||
@ -69,7 +82,9 @@ export class ProductService {
|
||||
options.params = options.params.set('v', vendorId as string).set('d', date as string);
|
||||
}
|
||||
return this.http
|
||||
.get<Product[]>(`${url}/query`, options)
|
||||
.pipe(catchError(this.log.handleError(serviceName, 'autocomplete'))) as Observable<Product[]>;
|
||||
.get<ProductSku[]>(`${url}/q-sku`, options)
|
||||
.pipe(catchError(this.log.handleError(serviceName, 'autocomplete'))) as Observable<
|
||||
ProductSku[]
|
||||
>;
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from 'r
|
||||
import { Batch } from '../core/batch';
|
||||
import { Inventory } from '../core/inventory';
|
||||
import { Product } from '../core/product';
|
||||
import { ProductSku } from '../core/product-sku';
|
||||
import { ProductService } from '../product/product.service';
|
||||
import { MathService } from '../shared/math.service';
|
||||
|
||||
@ -18,9 +19,9 @@ import { MathService } from '../shared/math.service';
|
||||
styleUrls: ['./purchase-dialog.component.css'],
|
||||
})
|
||||
export class PurchaseDialogComponent implements OnInit {
|
||||
products: Observable<Product[]>;
|
||||
products: Observable<ProductSku[]>;
|
||||
form: FormGroup;
|
||||
product: Product = new Product();
|
||||
product: ProductSku = new ProductSku();
|
||||
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<PurchaseDialogComponent>,
|
||||
@ -42,7 +43,7 @@ export class PurchaseDialogComponent implements OnInit {
|
||||
map((x) => (x !== null && x.length >= 1 ? x : null)),
|
||||
debounceTime(150),
|
||||
distinctUntilChanged(),
|
||||
switchMap((x) => (x === null ? observableOf([]) : this.productSer.autocomplete(x, true))),
|
||||
switchMap((x) => (x === null ? observableOf([]) : this.productSer.autocompleteSku(x, true))),
|
||||
);
|
||||
}
|
||||
|
||||
@ -63,7 +64,7 @@ export class PurchaseDialogComponent implements OnInit {
|
||||
|
||||
productSelected(event: MatAutocompleteSelectedEvent): void {
|
||||
this.product = event.option.value;
|
||||
(this.form.get('price') as FormControl).setValue(this.product.price);
|
||||
(this.form.get('price') as FormControl).setValue(this.product.costPrice);
|
||||
}
|
||||
|
||||
accept(): void {
|
||||
|
||||
@ -17,6 +17,7 @@ import { Batch } from '../core/batch';
|
||||
import { DbFile } from '../core/db-file';
|
||||
import { Inventory } from '../core/inventory';
|
||||
import { Product } from '../core/product';
|
||||
import { ProductSku } from '../core/product-sku';
|
||||
import { ToasterService } from '../core/toaster.service';
|
||||
import { User } from '../core/user';
|
||||
import { Voucher } from '../core/voucher';
|
||||
@ -43,13 +44,13 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
dataSource: PurchaseDataSource = new PurchaseDataSource(this.inventoryObservable);
|
||||
form: FormGroup;
|
||||
voucher: Voucher = new Voucher();
|
||||
product: Product | null = null;
|
||||
product: ProductSku | null = null;
|
||||
accBal: AccountBalance | null = null;
|
||||
|
||||
displayedColumns = ['product', 'quantity', 'rate', 'tax', 'discount', 'amount', 'action'];
|
||||
|
||||
accounts: Observable<Account[]>;
|
||||
products: Observable<Product[]>;
|
||||
products: Observable<ProductSku[]>;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
@ -98,11 +99,9 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
switchMap((x) =>
|
||||
x === null
|
||||
? observableOf([])
|
||||
: this.productSer.autocomplete(
|
||||
: this.productSer.autocompleteSku(
|
||||
x,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
moment(this.form.value.date).format('DD-MMM-YYYY'),
|
||||
this.form.value.account.id,
|
||||
),
|
||||
@ -198,7 +197,7 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
return;
|
||||
}
|
||||
const price = this.product.isRateContracted
|
||||
? this.product.price
|
||||
? (this.product.costPrice as number)
|
||||
: this.math.parseAmount(formValue.price, 2);
|
||||
const tax = this.product.isRateContracted ? 0 : this.math.parseAmount(formValue.tax, 5);
|
||||
const discount = this.product.isRateContracted
|
||||
@ -208,7 +207,7 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
return;
|
||||
}
|
||||
const oldFiltered = this.voucher.inventories.filter(
|
||||
(x) => x.batch?.sku.id === (this.product as Product).id,
|
||||
(x) => x.batch?.sku.id === (this.product as ProductSku).id,
|
||||
);
|
||||
if (oldFiltered.length) {
|
||||
this.toaster.show('Danger', 'Product already added');
|
||||
@ -365,10 +364,10 @@ export class PurchaseComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
}
|
||||
|
||||
productSelected(event: MatAutocompleteSelectedEvent): void {
|
||||
const product: Product = event.option.value;
|
||||
const product: ProductSku = event.option.value;
|
||||
const addRowForm: FormControl = this.form.get('addRow') as FormControl;
|
||||
this.product = product;
|
||||
(addRowForm.get('price') as FormControl).setValue(product.price);
|
||||
(addRowForm.get('price') as FormControl).setValue(product.costPrice);
|
||||
if (product.isRateContracted) {
|
||||
(addRowForm.get('price') as FormControl).disable();
|
||||
(addRowForm.get('tax') as FormControl).disable();
|
||||
|
||||
@ -10,6 +10,7 @@ import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from 'r
|
||||
import { Account } from '../../core/account';
|
||||
import { AccountService } from '../../core/account.service';
|
||||
import { Product } from '../../core/product';
|
||||
import { ProductSku } from '../../core/product-sku';
|
||||
import { ToasterService } from '../../core/toaster.service';
|
||||
import { ProductService } from '../../product/product.service';
|
||||
import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component';
|
||||
@ -38,7 +39,7 @@ export class RateContractDetailComponent implements OnInit, AfterViewInit {
|
||||
displayedColumns = ['product', 'price', 'action'];
|
||||
|
||||
accounts: Observable<Account[]>;
|
||||
products: Observable<Product[]>;
|
||||
products: Observable<ProductSku[]>;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
@ -77,7 +78,7 @@ export class RateContractDetailComponent implements OnInit, AfterViewInit {
|
||||
map((x) => (x !== null && x.length >= 1 ? x : null)),
|
||||
debounceTime(150),
|
||||
distinctUntilChanged(),
|
||||
switchMap((x) => (x === null ? observableOf([]) : this.productSer.autocomplete(x, true))),
|
||||
switchMap((x) => (x === null ? observableOf([]) : this.productSer.autocompleteSku(x, true))),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user