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:
Amritanshu 2019-08-18 22:05:33 +05:30
parent e697631cd4
commit 55ec2f8763
9 changed files with 167 additions and 37 deletions

View File

@ -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):

View File

@ -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": []
}

View File

@ -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>;

View File

@ -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;
}

View File

@ -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>&nbsp;/&nbsp;<span
[matTooltip]="bs.bill.creationDateTip">{{ bs.bill.creationDate}}</span>&nbsp;/&nbsp;<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>

View File

@ -18,3 +18,7 @@
.warn {
background-color: red;
}
.disabled {
background-color: #dddddd;
}

View File

@ -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()">

View File

@ -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;
}
}

View File

@ -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
],