Fix: get_bill_id now skips the 10000th number so that it displays properly in our system
Bill now shows the bill details on the top Started adding checks for disabled features during sales.
This commit is contained in:
parent
e697631cd4
commit
55ec2f8763
|
@ -19,11 +19,14 @@ def get_tax(tax, voucher_type):
|
|||
def get_bill_id(voucher_type, dbsession):
|
||||
if voucher_type == VoucherType.KOT:
|
||||
return None
|
||||
return (
|
||||
bill_id = (
|
||||
dbsession.query(func.coalesce(func.max(Voucher.bill_id), 0) + 1)
|
||||
.filter(Voucher.voucher_type == voucher_type.value)
|
||||
.scalar()
|
||||
)
|
||||
if voucher_type == VoucherType.REGULAR_BILL and bill_id % 10000 == 0:
|
||||
bill_id += 1
|
||||
return bill_id
|
||||
|
||||
|
||||
def do_update_table(item, guest_book, dbsession):
|
||||
|
|
|
@ -4,7 +4,7 @@ import uuid
|
|||
from pyramid.view import view_config
|
||||
|
||||
from barker.exceptions import ValidationFailure
|
||||
from barker.models import Voucher, Overview, FoodTable, GuestBook
|
||||
from barker.models import Voucher, Overview, FoodTable, GuestBook, VoucherType
|
||||
|
||||
|
||||
@view_config(
|
||||
|
@ -85,12 +85,15 @@ def show_for_table(request):
|
|||
def voucher_info(item):
|
||||
return {
|
||||
"id": item.id,
|
||||
"date": item.date.strftime("%d-%b-%Y %H:%M:%S"),
|
||||
"date": item.date.strftime("%H:%M"),
|
||||
"dateTip": item.date.strftime("%d-%b-%Y %H:%M:%S"),
|
||||
"pax": item.pax,
|
||||
"user": {"id": item.user_id, "name": item.user.name},
|
||||
"creationDate": item.creation_date.strftime("%d-%b-%Y %H:%M:%S"),
|
||||
"lastEditDate": item.last_edit_date.strftime("%d-%b-%Y %H:%M:%S"),
|
||||
"billId": item.bill_id,
|
||||
"creationDate": item.creation_date.strftime("%H:%M"),
|
||||
"creationDateTip": item.creation_date.strftime("%d-%b-%Y %H:%M:%S"),
|
||||
"lastEditDate": item.last_edit_date.strftime("%H:%M"),
|
||||
"lastEditDateTip": item.last_edit_date.strftime("%d-%b-%Y %H:%M:%S"),
|
||||
"billId": item.full_bill_id,
|
||||
"table": {"id": item.food_table_id, "name": item.food_table.name},
|
||||
"customer": {"id": item.customer_id, "name": item.customer.name} if item.customer is not None else {},
|
||||
"settlements": [],
|
||||
|
@ -154,6 +157,7 @@ def voucher_blank(table, guest):
|
|||
return {
|
||||
"pax": table.seats if guest is None else guest.pax,
|
||||
"table": {"id": table.id, "name": table.name},
|
||||
"voucherType": VoucherType.KOT.name,
|
||||
"customer": {"id": guest.customer_id, "name": guest.customer.name} if guest is not None else {},
|
||||
"kots": []
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ import { SelectionModel } from "@angular/cdk/collections";
|
|||
export class BillService {
|
||||
public dataObs;
|
||||
public data: any[];
|
||||
private bill;
|
||||
public bill;
|
||||
public netAmount: BehaviorSubject<number>;
|
||||
public discountAmount: BehaviorSubject<number>;
|
||||
public taxAmount: BehaviorSubject<number>;
|
||||
|
|
|
@ -20,6 +20,7 @@ table {
|
|||
.grey900 {
|
||||
background-color: #1b5e20;
|
||||
color: #ffffff;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.grey700 {
|
||||
|
@ -51,3 +52,18 @@ table {
|
|||
background-color: #ffcdd2;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.deep-purple-50 {
|
||||
background-color: #ede7f6;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.deep-purple-100 {
|
||||
background-color: #d1c4e9;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.deep-purple-200 {
|
||||
background-color: #b39ddb;
|
||||
color: #000000;
|
||||
}
|
||||
|
|
|
@ -8,22 +8,46 @@
|
|||
</mat-card-title-group>
|
||||
<mat-card-content>
|
||||
<table mat-table #table [dataSource]="dataSource" aria-label="Elements" class="mat-elevation-z8">
|
||||
<!-- Checkbox Column -->
|
||||
<ng-container matColumnDef="select">
|
||||
<mat-cell *matCellDef="let row">
|
||||
<mat-checkbox *ngIf="row.oldKot"
|
||||
(change)="$event ? masterToggle(row) : null"
|
||||
[checked]="bs.selection.hasValue() && isAllSelected(row)"
|
||||
[indeterminate]="isAnySelected(row)">
|
||||
</mat-checkbox>
|
||||
<mat-checkbox *ngIf="!row.isKot" [disabled]="!row.id"
|
||||
(click)="$event.stopPropagation()"
|
||||
(change)="$event ? bs.selection.toggle(row) : null"
|
||||
[checked]="bs.selection.isSelected(row)">
|
||||
</mat-checkbox>
|
||||
</mat-cell>
|
||||
<mat-footer-cell *matFooterCellDef class="grey900">Amount</mat-footer-cell>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="bill-no-title">
|
||||
<mat-header-cell *matHeaderCellDef class="deep-purple-200 bold">Bill / KOT number</mat-header-cell>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="bill-no-details">
|
||||
<mat-header-cell *matHeaderCellDef class="deep-purple-200 bold right-align">{{ bs.bill.billId }} /
|
||||
K-{{ bs.bill.kotId }}</mat-header-cell>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="time-title">
|
||||
<mat-header-cell *matHeaderCellDef class="deep-purple-100 bold">Time / Start Time / Last Edit Time
|
||||
</mat-header-cell>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="time-details">
|
||||
<mat-header-cell *matHeaderCellDef class="deep-purple-100 bold right-align"><span
|
||||
[matTooltip]="bs.bill.dateTip">{{ bs.bill.date }}</span> / <span
|
||||
[matTooltip]="bs.bill.creationDateTip">{{ bs.bill.creationDate}}</span> / <span
|
||||
[matTooltip]="bs.bill.lastEditDateTip">{{ bs.bill.lastEditDate }}</span></mat-header-cell>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="table-title">
|
||||
<mat-header-cell *matHeaderCellDef class="deep-purple-50 bold">Table / Pax / Customer</mat-header-cell>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="table-details">
|
||||
<mat-header-cell *matHeaderCellDef class="deep-purple-50 bold right-align">{{ bs.bill.table.name }}
|
||||
/ {{ bs.bill.pax }} / {{ bs.bill.customer.name }}</mat-header-cell>
|
||||
</ng-container>
|
||||
|
||||
<!-- Checkbox Column -->
|
||||
<ng-container matColumnDef="select">
|
||||
<mat-cell *matCellDef="let row">
|
||||
<mat-checkbox *ngIf="row.oldKot"
|
||||
(change)="$event ? masterToggle(row) : null"
|
||||
[checked]="bs.selection.hasValue() && isAllSelected(row)"
|
||||
[indeterminate]="isAnySelected(row)">
|
||||
</mat-checkbox>
|
||||
<mat-checkbox *ngIf="!row.isKot" [disabled]="!row.id"
|
||||
(click)="$event.stopPropagation()"
|
||||
(change)="$event ? bs.selection.toggle(row) : null"
|
||||
[checked]="bs.selection.isSelected(row)">
|
||||
</mat-checkbox>
|
||||
</mat-cell>
|
||||
</ng-container>
|
||||
<!-- Info Column -->
|
||||
<ng-container matColumnDef="info">
|
||||
<mat-cell *matCellDef="let row" [class.blue800]="row.newKot">
|
||||
|
@ -34,7 +58,6 @@
|
|||
<li *ngFor="let m of row.modifiers">{{m.name}}</li>
|
||||
</ul>
|
||||
</mat-cell>
|
||||
<mat-footer-cell *matFooterCellDef class="grey900 bold"></mat-footer-cell>
|
||||
</ng-container>
|
||||
<!-- Quantity Column -->
|
||||
<ng-container matColumnDef="quantity">
|
||||
|
@ -59,33 +82,46 @@
|
|||
<mat-icon class="del">open_in_new</mat-icon>
|
||||
</button>
|
||||
</mat-cell>
|
||||
<mat-footer-cell *matFooterCellDef class="grey900 bold right-align">{{ bs.amount | async | currency: 'INR' }}</mat-footer-cell>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="net-title">
|
||||
<mat-footer-cell *matFooterCellDef class="grey300 bold">Net</mat-footer-cell>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="net-amount">
|
||||
<mat-footer-cell *matFooterCellDef class="grey300 bold right-align">{{ bs.netAmount | async | currency: 'INR' }}</mat-footer-cell>
|
||||
<mat-footer-cell *matFooterCellDef
|
||||
class="grey300 bold right-align">{{ bs.netAmount | async | currency: 'INR' }}</mat-footer-cell>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="discount-title">
|
||||
<mat-footer-cell *matFooterCellDef class="grey500 bold">Discount</mat-footer-cell>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="discount-amount">
|
||||
<mat-footer-cell *matFooterCellDef class="grey500 bold right-align">{{ bs.discountAmount | async | currency: 'INR' }}</mat-footer-cell>
|
||||
<mat-footer-cell *matFooterCellDef
|
||||
class="grey500 bold right-align">{{ bs.discountAmount | async | currency: 'INR' }}</mat-footer-cell>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="tax-title">
|
||||
<mat-footer-cell *matFooterCellDef class="grey700 bold">Tax</mat-footer-cell>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="tax-amount">
|
||||
<mat-footer-cell *matFooterCellDef class="grey700 bold right-align">{{ bs.taxAmount | async | currency: 'INR' }}</mat-footer-cell>
|
||||
<mat-footer-cell *matFooterCellDef
|
||||
class="grey700 bold right-align">{{ bs.taxAmount | async | currency: 'INR' }}</mat-footer-cell>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="amount-title">
|
||||
<mat-footer-cell *matFooterCellDef class="grey900">Amount</mat-footer-cell>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="amount-amount">
|
||||
<mat-footer-cell *matFooterCellDef
|
||||
class="grey900 bold right-align">{{ bs.amount | async | currency: 'INR' }}</mat-footer-cell>
|
||||
</ng-container>
|
||||
|
||||
<mat-row *matRowDef="let row; columns: displayedColumns;" [class.blue400]="row.oldKot" [class.blue800]="row.newKot"
|
||||
<mat-header-row *matHeaderRowDef="['bill-no-title', 'bill-no-details']"></mat-header-row>
|
||||
<mat-header-row *matHeaderRowDef="['time-title', 'time-details']"></mat-header-row>
|
||||
<mat-header-row *matHeaderRowDef="['table-title', 'table-details']"></mat-header-row>
|
||||
<mat-row *matRowDef="let row; columns: displayedColumns;" [class.blue400]="row.oldKot"
|
||||
[class.blue800]="row.newKot"
|
||||
[class.red100]="row.isPrinted"></mat-row>
|
||||
<mat-footer-row *matFooterRowDef="['net-title', 'net-amount']"></mat-footer-row>
|
||||
<mat-footer-row *matFooterRowDef="['discount-title', 'discount-amount']"></mat-footer-row>
|
||||
<mat-footer-row *matFooterRowDef="['tax-title', 'tax-amount']"></mat-footer-row>
|
||||
<mat-footer-row *matFooterRowDef="displayedColumns"></mat-footer-row>
|
||||
<mat-footer-row *matFooterRowDef="['amount-title', 'amount-amount']"></mat-footer-row>
|
||||
</table>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
|
|
|
@ -18,3 +18,7 @@
|
|||
.warn {
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.disabled {
|
||||
background-color: #dddddd;
|
||||
}
|
||||
|
|
|
@ -3,19 +3,23 @@
|
|||
queryParamsHandling="preserve">
|
||||
<h3 class="item-name">Add Product</h3>
|
||||
</mat-card>
|
||||
<mat-card fxLayout="column" class="square-button" matRipple (click)="discount()">
|
||||
<mat-card fxLayout="column" class="square-button" matRipple (click)="discount()"
|
||||
[class.disabled]="!discountAllowed()">
|
||||
<h3 class="item-name">Discount</h3>
|
||||
</mat-card>
|
||||
<mat-card fxLayout="column" class="square-button" matRipple (click)="printKot()">
|
||||
<mat-card fxLayout="column" class="square-button" matRipple (click)="printKot()"
|
||||
[class.disabled]="!printKotAllowed()">
|
||||
<h3 class="item-name">Print KOT</h3>
|
||||
</mat-card>
|
||||
<mat-card fxLayout="column" class="square-button" matRipple (click)="printBill()">
|
||||
<mat-card fxLayout="column" class="square-button" matRipple (click)="printBill()"
|
||||
[class.disabled]="!printBillAllowed()">
|
||||
<h3 class="item-name">Print Bill</h3>
|
||||
</mat-card>
|
||||
<mat-card fxLayout="column" class="square-button warn" matRipple [routerLink]="['../../tables']">
|
||||
<h3 class="item-name">Back to Tables</h3>
|
||||
</mat-card>
|
||||
<mat-card fxLayout="column" class="square-button" matRipple (click)="receivePayment()">
|
||||
<mat-card fxLayout="column" class="square-button" matRipple (click)="receivePayment()"
|
||||
[class.disabled]="!receivePaymentAllowed()">
|
||||
<h3 class="item-name">Receive Payment</h3>
|
||||
</mat-card>
|
||||
<mat-card fxLayout="column" class="square-button" matRipple (click)="moveTable()">
|
||||
|
|
|
@ -39,6 +39,9 @@ export class SalesHomeComponent implements OnInit {
|
|||
}
|
||||
|
||||
printKot() {
|
||||
if (!this.printKotAllowed()) {
|
||||
return;
|
||||
}
|
||||
let guestBookId = null;
|
||||
if (this.route.snapshot.queryParamMap.has('guest')) {
|
||||
guestBookId = this.route.snapshot.queryParamMap.get('guest');
|
||||
|
@ -50,9 +53,10 @@ export class SalesHomeComponent implements OnInit {
|
|||
}
|
||||
|
||||
discount(): void {
|
||||
if (this.auth.hasPermission('Discount')) {
|
||||
this.showDiscount().subscribe();
|
||||
if (!this.discountAllowed()) {
|
||||
return;
|
||||
}
|
||||
this.showDiscount().subscribe();
|
||||
}
|
||||
|
||||
showDiscount(): Observable<boolean | { id: string, name: string, discount: number }[]> {
|
||||
|
@ -106,6 +110,9 @@ export class SalesHomeComponent implements OnInit {
|
|||
}
|
||||
|
||||
printBill() {
|
||||
if (!this.printBillAllowed()) {
|
||||
return;
|
||||
}
|
||||
const canGiveDiscount = this.auth.hasPermission('Discount');
|
||||
let guestBookId = null;
|
||||
if (this.route.snapshot.queryParamMap.has('guest')) {
|
||||
|
@ -130,6 +137,9 @@ export class SalesHomeComponent implements OnInit {
|
|||
}
|
||||
|
||||
receivePayment() {
|
||||
if (!this.receivePaymentAllowed()) {
|
||||
return;
|
||||
}
|
||||
const amount = this.bs.amountVal();
|
||||
const type = this.bs.type();
|
||||
const dialogRef = this.dialog.open(ReceivePaymentComponent, {
|
||||
|
@ -241,4 +251,56 @@ export class SalesHomeComponent implements OnInit {
|
|||
this.toaster.show('Error', x);
|
||||
});
|
||||
}
|
||||
|
||||
discountAllowed(): boolean {
|
||||
return this.auth.hasPermission('Discount');
|
||||
}
|
||||
|
||||
printKotAllowed(): boolean {
|
||||
if (!this.auth.hasPermission('Print Kot')) {
|
||||
return false;
|
||||
}
|
||||
if (!this.bs.bill.id) {
|
||||
return true;
|
||||
}
|
||||
if (this.bs.bill.voucherType !== PrintType.Kot) {
|
||||
return false;
|
||||
}
|
||||
if (this.bs.bill.isVoid) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
printBillAllowed(): boolean {
|
||||
if (!this.auth.hasPermission('Print Bill')) {
|
||||
return false;
|
||||
}
|
||||
if (!this.bs.bill.id) {
|
||||
return true;
|
||||
}
|
||||
if (this.bs.bill.voucherType !== PrintType.Kot && !this.auth.hasPermission('Edit Printed Bill')) {
|
||||
return false;
|
||||
}
|
||||
if (this.bs.bill.isVoid) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
receivePaymentAllowed(): boolean {
|
||||
if (!this.auth.hasPermission('Settle Bill')) {
|
||||
return false;
|
||||
}
|
||||
if (!this.bs.bill.id) {
|
||||
return false;
|
||||
}
|
||||
if (this.bs.bill.voucherType === PrintType.Kot) {
|
||||
return false
|
||||
}
|
||||
if (this.bs.bill.isVoid) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import { MatDialogModule } from '@angular/material/dialog';
|
|||
import { MatDividerModule } from '@angular/material/divider';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatRippleModule } from '@angular/material';
|
||||
import { MatRippleModule, MatTooltipModule } from '@angular/material';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
import { MatTabsModule } from '@angular/material/tabs';
|
||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
||||
|
@ -67,6 +67,7 @@ import { VoidReasonComponent } from './void-reason/void-reason.component';
|
|||
MatRippleModule,
|
||||
MatTableModule,
|
||||
MatTabsModule,
|
||||
MatTooltipModule,
|
||||
SharedModule,
|
||||
SalesRoutingModule
|
||||
],
|
||||
|
|
Loading…
Reference in New Issue