Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: point of sale #709

Merged
merged 54 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
22b32cb
feat: pos schemas
akshayitzme Aug 16, 2023
ad9401e
chore: fix code format
akshayitzme Aug 21, 2023
7ce556b
feat: pos shift opening schemas
akshayitzme Aug 22, 2023
e490716
feat: pos shift closing schemas
akshayitzme Aug 22, 2023
65018bd
refactor: pos shift & pos settings schemas
akshayitzme Aug 22, 2023
4f3e353
feat(ui): neupos icon
akshayitzme Aug 22, 2023
a01dfed
feat: neupos route & sidebar config
akshayitzme Aug 22, 2023
b8518c6
feat: cash denomination models
akshayitzme Aug 22, 2023
9930a15
feat: pos shift models
akshayitzme Aug 22, 2023
69b213e
feat: neupos page
akshayitzme Aug 22, 2023
49cf461
feat: pos shift open page
akshayitzme Aug 22, 2023
0172551
fix: enabled create for pos default customer
akshayitzme Aug 22, 2023
9cf3ee0
feat: isPOS field to identify inv created in pos
akshayitzme Aug 22, 2023
b9b2f3d
fix: added closingAmounts in posShift
akshayitzme Aug 22, 2023
06da764
incr: posShiftOpen modal
akshayitzme Aug 22, 2023
746b3b2
incr: close pos shift modal
akshayitzme Aug 22, 2023
2185472
feat: get pos transacted amount
akshayitzme Aug 22, 2023
79ef11b
incr: pos shift models
akshayitzme Aug 22, 2023
e7486db
incr: added pos open & close modal
akshayitzme Aug 22, 2023
ab3f1e0
feat: payment modal init
akshayitzme Aug 23, 2023
1878f26
feat: items table
akshayitzme Aug 23, 2023
c12d9e1
feat: selected items table
akshayitzme Aug 23, 2023
0189e99
feat: floating label input base
akshayitzme Aug 23, 2023
f43161a
feat: floating label currency input
akshayitzme Aug 23, 2023
5395504
feat: floating label float input
akshayitzme Aug 23, 2023
5b66b98
incr: selected item row component
akshayitzme Aug 23, 2023
d3bc03a
incr: added payment, cancel action buttons
akshayitzme Aug 23, 2023
5f59550
fix: balance quantity not updating after submit
akshayitzme Aug 24, 2023
a04e2af
feat: payment modal
akshayitzme Aug 24, 2023
b072253
fix: enable POS only if discounts enabled
akshayitzme Aug 24, 2023
c483c4b
fix: show item discount amount & percent
akshayitzme Aug 24, 2023
3bbf529
fix: add item triggering multiple times
akshayitzme Aug 25, 2023
65c4725
fix(ui): table overflowing
akshayitzme Aug 25, 2023
a3c61e0
chore: remove redundant comment
akshayitzme Aug 25, 2023
b7e4b3d
fix(ui): modal sizing
akshayitzme Aug 25, 2023
83615ea
chore: rename neupos to pos
akshayitzme Aug 30, 2023
ebaf110
chore: remove POSSettings as its redundant for now
akshayitzme Aug 30, 2023
f50932c
chore: set additional discount field to readonly
akshayitzme Aug 30, 2023
238f477
chore: code cleanup
akshayitzme Aug 31, 2023
db2a97d
test: pos transacted amount
akshayitzme Sep 1, 2023
8186f12
feat: pos settings
akshayitzme Sep 5, 2023
7db0cf5
fix: party creation from POS
akshayitzme Sep 5, 2023
7e7e3ed
chore: code cleanup
akshayitzme Sep 5, 2023
ffbce23
fix: minor fixes
akshayitzme Sep 6, 2023
81be57b
feat: pos settings validations
akshayitzme Sep 14, 2023
819d88f
fix: failing test
akshayitzme Sep 18, 2023
23f9fc9
fix: list only inventory items (trackItem enabled)
akshayitzme Sep 25, 2023
f86275d
feat: validate serial number count in row
akshayitzme Sep 25, 2023
9874d71
chore: add missing types
akshayitzme Nov 7, 2023
8d1e0ca
fix(ux): disable submit button
akshayitzme Nov 7, 2023
df6c472
chore: refactor sinv validations
akshayitzme Nov 7, 2023
97f9fbb
feat: toast popus on sinv, shpm, pay submit
akshayitzme Nov 7, 2023
a769537
fix(ux): disable Pay, Submit buttons on conditions
akshayitzme Dec 2, 2023
7ed2a08
fix: expectedAmount calculation
akshayitzme Dec 4, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading