Skip to content

Commit

Permalink
Merge pull request #709 from akshayitzme/feat-pos-page
Browse files Browse the repository at this point in the history
feat: point of sale
  • Loading branch information
akshayitzme authored Dec 4, 2023
2 parents 74a81de + 7ed2a08 commit 82a2c5e
Show file tree
Hide file tree
Showing 46 changed files with 3,155 additions and 4 deletions.
57 changes: 57 additions & 0 deletions backend/database/bespoke.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import {
import { ModelNameEnum } from '../../models/types';
import DatabaseCore from './core';
import { BespokeFunction } from './types';
import { DateTime } from 'luxon';
import { DocItem, ReturnDocItem } from 'models/inventory/types';
import { safeParseFloat } from 'utils/index';
import { Money } from 'pesa';

export class BespokeQueries {
[key: string]: BespokeFunction;
Expand Down Expand Up @@ -390,4 +392,59 @@ export class BespokeQueries {
}
return returnBalanceItems;
}

static async getPOSTransactedAmount(
db: DatabaseCore,
fromDate: Date,
toDate: Date,
lastShiftClosingDate?: Date
): Promise<Record<string, Money> | undefined> {
const sinvNamesQuery = db.knex!(ModelNameEnum.SalesInvoice)
.select('name')
.where('isPOS', true)
.andWhereBetween('date', [
DateTime.fromJSDate(fromDate).toSQLDate(),
DateTime.fromJSDate(toDate).toSQLDate(),
]);

if (lastShiftClosingDate) {
sinvNamesQuery.andWhere(
'created',
'>',
DateTime.fromJSDate(lastShiftClosingDate).toUTC().toString()
);
}

const sinvNames = (await sinvNamesQuery).map(
(row: { name: string }) => row.name
);

if (!sinvNames.length) {
return;
}

const paymentEntryNames: string[] = (
await db.knex!(ModelNameEnum.PaymentFor)
.select('parent')
.whereIn('referenceName', sinvNames)
).map((doc: { parent: string }) => doc.parent);

const groupedAmounts = (await db.knex!(ModelNameEnum.Payment)
.select('paymentMethod')
.whereIn('name', paymentEntryNames)
.groupBy('paymentMethod')
.sum({ amount: 'amount' })) as { paymentMethod: string; amount: Money }[];

const transactedAmounts = {} as { [paymentMethod: string]: Money };

if (!groupedAmounts) {
return;
}

for (const row of groupedAmounts) {
transactedAmounts[row.paymentMethod] = row.amount;
}

return transactedAmounts;
}
}
14 changes: 14 additions & 0 deletions fyo/core/dbHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
RawValueMap,
} from './types';
import { ReturnDocItem } from 'models/inventory/types';
import { Money } from 'pesa';

type FieldMap = Record<string, Record<string, Field>>;

Expand Down Expand Up @@ -342,6 +343,19 @@ export class DatabaseHandler extends DatabaseBase {
)) as Promise<Record<string, ReturnDocItem> | undefined>;
}

async getPOSTransactedAmount(
fromDate: Date,
toDate: Date,
lastShiftClosingDate?: Date
): Promise<Record<string, Money> | undefined> {
return (await this.#demux.callBespoke(
'getPOSTransactedAmount',
fromDate,
toDate,
lastShiftClosingDate
)) as Promise<Record<string, Money> | undefined>;
}

/**
* Internal methods
*/
Expand Down
4 changes: 4 additions & 0 deletions fyo/model/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import type { Defaults } from 'models/baseModels/Defaults/Defaults';
import type { PrintSettings } from 'models/baseModels/PrintSettings/PrintSettings';
import type { InventorySettings } from 'models/inventory/InventorySettings';
import type { Misc } from 'models/baseModels/Misc';
import type { POSSettings } from 'models/inventory/Point of Sale/POSSettings';
import type { POSShift } from 'models/inventory/Point of Sale/POSShift';

/**
* The functions below are used for dynamic evaluation
Expand Down Expand Up @@ -54,6 +56,8 @@ export interface SinglesMap {
SystemSettings?: SystemSettings;
AccountingSettings?: AccountingSettings;
InventorySettings?: InventorySettings;
POSSettings?: POSSettings;
POSShift?: POSShift;
PrintSettings?: PrintSettings;
Defaults?: Defaults;
Misc?: Misc;
Expand Down
13 changes: 13 additions & 0 deletions models/baseModels/Defaults/Defaults.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { DefaultCashDenominations } from 'models/inventory/Point of Sale/DefaultCashDenominations';
import { Doc } from 'fyo/model/doc';
import { FiltersMap, HiddenMap } from 'fyo/model/types';
import { ModelNameEnum } from 'models/types';
import { PartyRoleEnum } from '../Party/types';

export class Defaults extends Doc {
// Auto Payments
Expand Down Expand Up @@ -35,6 +37,10 @@ export class Defaults extends Doc {
purchaseReceiptPrintTemplate?: string;
stockMovementPrintTemplate?: string;

// Point of Sale
posCashDenominations?: DefaultCashDenominations[];
posCustomer?: string;

static commonFilters = {
// Auto Payments
salesPaymentAccount: () => ({ isGroup: false, accountType: 'Cash' }),
Expand Down Expand Up @@ -73,6 +79,7 @@ export class Defaults extends Doc {
type: ModelNameEnum.PurchaseReceipt,
}),
stockMovementPrintTemplate: () => ({ type: ModelNameEnum.StockMovement }),
posCustomer: () => ({ role: PartyRoleEnum.Customer }),
};

static filters: FiltersMap = this.commonFilters;
Expand All @@ -82,6 +89,10 @@ export class Defaults extends Doc {
return () => !this.fyo.singles.AccountingSettings?.enableInventory;
}

getPointOfSaleHidden() {
return () => !this.fyo.singles.InventorySettings?.enablePointOfSale;
}

hidden: HiddenMap = {
stockMovementNumberSeries: this.getInventoryHidden(),
shipmentNumberSeries: this.getInventoryHidden(),
Expand All @@ -91,6 +102,8 @@ export class Defaults extends Doc {
shipmentPrintTemplate: this.getInventoryHidden(),
purchaseReceiptPrintTemplate: this.getInventoryHidden(),
stockMovementPrintTemplate: this.getInventoryHidden(),
posCashDenominations: this.getPointOfSaleHidden(),
posCustomer: this.getPointOfSaleHidden(),
};
}

Expand Down
13 changes: 13 additions & 0 deletions models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ import { ShipmentItem } from './inventory/ShipmentItem';
import { StockLedgerEntry } from './inventory/StockLedgerEntry';
import { StockMovement } from './inventory/StockMovement';
import { StockMovementItem } from './inventory/StockMovementItem';
import { ClosingAmounts } from './inventory/Point of Sale/ClosingAmounts';
import { ClosingCash } from './inventory/Point of Sale/ClosingCash';
import { OpeningAmounts } from './inventory/Point of Sale/OpeningAmounts';
import { OpeningCash } from './inventory/Point of Sale/OpeningCash';
import { POSSettings } from './inventory/Point of Sale/POSSettings';
import { POSShift } from './inventory/Point of Sale/POSShift';

export const models = {
Account,
Expand Down Expand Up @@ -70,6 +76,13 @@ export const models = {
ShipmentItem,
PurchaseReceipt,
PurchaseReceiptItem,
// POS Models
ClosingAmounts,
ClosingCash,
OpeningAmounts,
OpeningCash,
POSSettings,
POSShift,
} as ModelMap;

export async function getRegionalModels(
Expand Down
4 changes: 4 additions & 0 deletions models/inventory/InventorySettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export class InventorySettings extends Doc {
enableSerialNumber?: boolean;
enableUomConversions?: boolean;
enableStockReturns?: boolean;
enablePointOfSale?: boolean;

static filters: FiltersMap = {
stockInHand: () => ({
Expand Down Expand Up @@ -44,5 +45,8 @@ export class InventorySettings extends Doc {
enableStockReturns: () => {
return !!this.enableStockReturns;
},
enablePointOfSale: () => {
return !!this.fyo.singles.POSShift?.isShiftOpen;
},
};
}
6 changes: 6 additions & 0 deletions models/inventory/Point of Sale/CashDenominations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { Doc } from 'fyo/model/doc';
import { Money } from 'pesa';

export abstract class CashDenominations extends Doc {
denomination?: Money;
}
27 changes: 27 additions & 0 deletions models/inventory/Point of Sale/ClosingAmounts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Doc } from 'fyo/model/doc';
import { FormulaMap } from 'fyo/model/types';
import { Money } from 'pesa';

export class ClosingAmounts extends Doc {
closingAmount?: Money;
differenceAmount?: Money;
expectedAmount?: Money;
openingAmount?: Money;
paymentMethod?: string;

formulas: FormulaMap = {
differenceAmount: {
formula: () => {
if (!this.closingAmount) {
return this.fyo.pesa(0);
}

if (!this.expectedAmount) {
return this.fyo.pesa(0);
}

return this.closingAmount.sub(this.expectedAmount);
},
},
};
}
5 changes: 5 additions & 0 deletions models/inventory/Point of Sale/ClosingCash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { CashDenominations } from './CashDenominations';

export class ClosingCash extends CashDenominations {
count?: number;
}
3 changes: 3 additions & 0 deletions models/inventory/Point of Sale/DefaultCashDenominations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { CashDenominations } from './CashDenominations';

export class DefaultCashDenominations extends CashDenominations {}
11 changes: 11 additions & 0 deletions models/inventory/Point of Sale/OpeningAmounts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Doc } from 'fyo/model/doc';
import { Money } from 'pesa';

export class OpeningAmounts extends Doc {
amount?: Money;
paymentMethod?: 'Cash' | 'Transfer';

get openingCashAmount() {
return this.parentdoc?.openingCashAmount as Money;
}
}
5 changes: 5 additions & 0 deletions models/inventory/Point of Sale/OpeningCash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { CashDenominations } from './CashDenominations';

export class OpeningCash extends CashDenominations {
count?: number;
}
19 changes: 19 additions & 0 deletions models/inventory/Point of Sale/POSSettings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Doc } from 'fyo/model/doc';
import { FiltersMap } from 'fyo/model/types';
import {
AccountRootTypeEnum,
AccountTypeEnum,
} from 'models/baseModels/Account/types';

export class POSSettings extends Doc {
inventory?: string;
cashAccount?: string;
writeOffAccount?: string;

static filters: FiltersMap = {
cashAccount: () => ({
rootType: AccountRootTypeEnum.Asset,
accountType: AccountTypeEnum.Cash,
}),
};
}
61 changes: 61 additions & 0 deletions models/inventory/Point of Sale/POSShift.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { ClosingAmounts } from './ClosingAmounts';
import { ClosingCash } from './ClosingCash';
import { Doc } from 'fyo/model/doc';
import { OpeningAmounts } from './OpeningAmounts';
import { OpeningCash } from './OpeningCash';

export class POSShift extends Doc {
closingAmounts?: ClosingAmounts[];
closingCash?: ClosingCash[];
closingDate?: Date;
isShiftOpen?: boolean;
openingAmounts?: OpeningAmounts[];
openingCash?: OpeningCash[];
openingDate?: Date;

get openingCashAmount() {
if (!this.openingCash) {
return this.fyo.pesa(0);
}

let openingAmount = this.fyo.pesa(0);

this.openingCash.map((row: OpeningCash) => {
const denomination = row.denomination ?? this.fyo.pesa(0);
const count = row.count ?? 0;

const amount = denomination.mul(count);
openingAmount = openingAmount.add(amount);
});
return openingAmount;
}

get closingCashAmount() {
if (!this.closingCash) {
return this.fyo.pesa(0);
}

let closingAmount = this.fyo.pesa(0);

this.closingCash.map((row: ClosingCash) => {
const denomination = row.denomination ?? this.fyo.pesa(0);
const count = row.count ?? 0;

const amount = denomination.mul(count);
closingAmount = closingAmount.add(amount);
});
return closingAmount;
}

get openingTransferAmount() {
if (!this.openingAmounts) {
return this.fyo.pesa(0);
}

const transferAmountRow = this.openingAmounts.filter(
(row) => row.paymentMethod === 'Transfer'
)[0];

return transferAmountRow.amount ?? this.fyo.pesa(0);
}
}
Loading

0 comments on commit 82a2c5e

Please sign in to comment.