mirror of
https://github.com/frappe/books.git
synced 2026-08-24 02:24:17 -05:00
Merge pull request #1254 from frappe/feat-pos-profile
feat: pos profile functionality
This commit is contained in:
+10
-6
@@ -14,6 +14,7 @@ import type { POSSettings } from 'models/inventory/Point of Sale/POSSettings';
|
||||
import type { POSOpeningShift } from 'models/inventory/Point of Sale/POSOpeningShift';
|
||||
import type { POSClosingShift } from 'models/inventory/Point of Sale/POSClosingShift';
|
||||
import { ERPNextSyncSettings } from 'models/baseModels/ERPNextSyncSettings/ERPNextSyncSettings';
|
||||
import { POSProfile } from 'models/baseModels/POSProfile/PosProfile';
|
||||
|
||||
/**
|
||||
* The functions below are used for dynamic evaluation
|
||||
@@ -28,7 +29,9 @@ import { ERPNextSyncSettings } from 'models/baseModels/ERPNextSyncSettings/ERPNe
|
||||
* - `Required`: Regular function used to decide if a value is mandatory (there are !notnul in the db).
|
||||
*/
|
||||
export type FormulaReturn = DocValue | DocValueMap[] | undefined | Doc[];
|
||||
export type Formula = (fieldname?: string) => Promise<FormulaReturn> | FormulaReturn;
|
||||
export type Formula = (
|
||||
fieldname?: string
|
||||
) => Promise<FormulaReturn> | FormulaReturn;
|
||||
export type FormulaConfig = { dependsOn?: string[]; formula: Formula };
|
||||
export type Default = (doc: Doc) => DocValue;
|
||||
export type Validation = (value: DocValue) => Promise<void> | void;
|
||||
@@ -59,6 +62,7 @@ export interface SinglesMap {
|
||||
AccountingSettings?: AccountingSettings;
|
||||
InventorySettings?: InventorySettings;
|
||||
POSSettings?: POSSettings;
|
||||
POSProfile?: POSProfile;
|
||||
POSOpeningShift?: POSOpeningShift;
|
||||
ERPNextSyncSettings?: ERPNextSyncSettings;
|
||||
POSClosingShift?: POSClosingShift;
|
||||
@@ -91,8 +95,8 @@ export interface Action {
|
||||
}
|
||||
|
||||
export interface RenderData {
|
||||
schema: Schema,
|
||||
[key: string]: DocValue | Schema
|
||||
schema: Schema;
|
||||
[key: string]: DocValue | Schema;
|
||||
}
|
||||
|
||||
export type ColumnConfig = {
|
||||
@@ -101,7 +105,7 @@ export type ColumnConfig = {
|
||||
fieldname: string;
|
||||
render?: (doc: RenderData) => { template: string };
|
||||
display?: (value: unknown, fyo: Fyo) => string;
|
||||
}
|
||||
};
|
||||
|
||||
export type ListViewColumn = string | ColumnConfig;
|
||||
export interface ListViewSettings {
|
||||
@@ -122,7 +126,7 @@ export type DocStatus =
|
||||
| 'Submitted'
|
||||
| 'Cancelled';
|
||||
|
||||
export type LeadStatus =
|
||||
export type LeadStatus =
|
||||
| ''
|
||||
| 'Open'
|
||||
| 'Replied'
|
||||
@@ -130,4 +134,4 @@ export type DocStatus =
|
||||
| 'Opportunity'
|
||||
| 'Converted'
|
||||
| 'Quotation'
|
||||
| 'DonotContact'
|
||||
| 'DonotContact';
|
||||
|
||||
@@ -111,13 +111,6 @@ export abstract class Invoice extends Transactional {
|
||||
return !!this.fyo.singles?.AccountingSettings?.enableDiscounting;
|
||||
}
|
||||
|
||||
get ignorePricingRules(): boolean {
|
||||
if (this.schemaName !== ModelNameEnum.SalesInvoice) {
|
||||
return false;
|
||||
}
|
||||
return !!this.fyo.singles.POSSettings?.ignorePricingRule;
|
||||
}
|
||||
|
||||
get isMultiCurrency() {
|
||||
if (!this.currency) {
|
||||
return false;
|
||||
@@ -1457,7 +1450,7 @@ export abstract class Invoice extends Transactional {
|
||||
}
|
||||
|
||||
async applyProductDiscount() {
|
||||
if (!this.items || this.ignorePricingRules) {
|
||||
if (!this.items || (await this.ignorePricingRules())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1522,6 +1515,23 @@ export abstract class Invoice extends Transactional {
|
||||
}
|
||||
}
|
||||
|
||||
async ignorePricingRules(): Promise<boolean> {
|
||||
const posProfileName = this.fyo.singles.POSSettings?.posProfile as string;
|
||||
|
||||
if (posProfileName) {
|
||||
const posProfile = await this.fyo.doc.getDoc(
|
||||
ModelNameEnum.POSProfile,
|
||||
posProfileName
|
||||
);
|
||||
|
||||
if (posProfile) {
|
||||
return posProfile.ignorePricingRule as boolean;
|
||||
}
|
||||
}
|
||||
|
||||
return !!this.fyo.singles.POSSettings?.ignorePricingRule;
|
||||
}
|
||||
|
||||
async getPricingRuleDocNames(
|
||||
item: SalesInvoiceItem,
|
||||
sinvDoc: SalesInvoice
|
||||
@@ -1538,7 +1548,7 @@ export abstract class Invoice extends Transactional {
|
||||
}
|
||||
|
||||
async getPricingRule(): Promise<ApplicablePricingRules[] | undefined> {
|
||||
if (this.ignorePricingRules) {
|
||||
if (await this.ignorePricingRules()) {
|
||||
return;
|
||||
}
|
||||
if (!this.isSales || !this.items) {
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Doc } from 'fyo/model/doc';
|
||||
import { FiltersMap } from 'fyo/model/types';
|
||||
import { ModelNameEnum } from 'models/types';
|
||||
|
||||
export class POSProfile extends Doc {
|
||||
posProfile?: string;
|
||||
posCustomer?: string;
|
||||
defaultLocation?: string;
|
||||
posPrintTemplate?: string;
|
||||
inventory?: string;
|
||||
posUI?: 'Classic' | 'Modern';
|
||||
isShiftOpen?: boolean;
|
||||
itemVisibility?: string;
|
||||
canChangeRate?: boolean;
|
||||
hideUnavailableItems?: boolean;
|
||||
canEditDiscount?: boolean;
|
||||
ignorePricingRule?: boolean;
|
||||
|
||||
static filters: FiltersMap = {
|
||||
posPrintTemplate: () => ({ type: ModelNameEnum.SalesInvoice }),
|
||||
};
|
||||
}
|
||||
+16
-3
@@ -79,10 +79,23 @@ export async function getItemQtyMap(doc: SalesInvoice): Promise<ItemQtyMap> {
|
||||
|
||||
const rawSLEs = await getRawStockLedgerEntries(doc.fyo);
|
||||
const rawData = getStockLedgerEntries(rawSLEs, valuationMethod);
|
||||
const posInventory = doc.fyo.singles.POSSettings?.inventory;
|
||||
|
||||
const posProfileName = doc.fyo.singles.POSSettings?.posProfile;
|
||||
let inventoryLocation: string | undefined;
|
||||
|
||||
if (posProfileName) {
|
||||
const posProfile = await doc.fyo.doc.getDoc(
|
||||
ModelNameEnum.POSProfile,
|
||||
posProfileName as string
|
||||
);
|
||||
|
||||
inventoryLocation = posProfile?.inventory as string | undefined;
|
||||
} else {
|
||||
inventoryLocation = doc.fyo.singles.POSSettings?.inventory;
|
||||
}
|
||||
|
||||
const stockBalance = getStockBalanceEntries(rawData, {
|
||||
location: posInventory,
|
||||
location: inventoryLocation,
|
||||
});
|
||||
|
||||
for (const row of stockBalance) {
|
||||
@@ -842,7 +855,7 @@ export async function removeLoyaltyPoint(doc: Doc) {
|
||||
|
||||
export async function validateQty(
|
||||
sinvDoc: SalesInvoice,
|
||||
item: Item | undefined,
|
||||
item: Item | SalesInvoiceItem | undefined,
|
||||
existingItems: InvoiceItem[]
|
||||
) {
|
||||
if (!item) {
|
||||
|
||||
@@ -50,6 +50,7 @@ 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 { POSProfile } from './baseModels/POSProfile/PosProfile';
|
||||
import { POSOpeningShift } from './inventory/Point of Sale/POSOpeningShift';
|
||||
import { POSClosingShift } from './inventory/Point of Sale/POSClosingShift';
|
||||
import { ERPNextSyncSettings } from './baseModels/ERPNextSyncSettings/ERPNextSyncSettings';
|
||||
@@ -111,6 +112,7 @@ export const models = {
|
||||
OpeningAmounts,
|
||||
OpeningCash,
|
||||
POSSettings,
|
||||
POSProfile,
|
||||
POSOpeningShift,
|
||||
POSClosingShift,
|
||||
// ERPNext Sync
|
||||
|
||||
@@ -69,6 +69,7 @@ export enum ModelNameEnum {
|
||||
CustomForm = 'CustomForm',
|
||||
CustomField = 'CustomField',
|
||||
POSSettings = 'POSSettings',
|
||||
POSProfile = 'POSProfile',
|
||||
POSOpeningShift = 'POSOpeningShift',
|
||||
POSClosingShift = 'POSClosingShift',
|
||||
|
||||
|
||||
@@ -0,0 +1,519 @@
|
||||
{
|
||||
"name": "POSProfile",
|
||||
"label": "POS Profile",
|
||||
"extends": "POSSettings",
|
||||
"naming": "manual",
|
||||
"showTitle": true,
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "name",
|
||||
"label": "Profile",
|
||||
"fieldtype": "Data",
|
||||
"create": true,
|
||||
"unique": true
|
||||
},
|
||||
{
|
||||
"fieldname": "posCustomer",
|
||||
"label": "POS Customer",
|
||||
"fieldtype": "Link",
|
||||
"target": "Party",
|
||||
"create": true
|
||||
},
|
||||
{
|
||||
"fieldname": "inventory",
|
||||
"label": "Inventory",
|
||||
"fieldtype": "Link",
|
||||
"target": "Location",
|
||||
"create": true,
|
||||
"required": true,
|
||||
"section": "Default"
|
||||
},
|
||||
{
|
||||
"fieldname": "posPrintTemplate",
|
||||
"label": "Pos Print Template",
|
||||
"fieldtype": "Link",
|
||||
"target": "PrintTemplate"
|
||||
},
|
||||
{
|
||||
"fieldname": "posUI",
|
||||
"label": "Pos Ui",
|
||||
"fieldtype": "Select",
|
||||
"options": [
|
||||
{
|
||||
"value": "Classic",
|
||||
"label": "Classic"
|
||||
},
|
||||
{
|
||||
"value": "Modern",
|
||||
"label": "Modern"
|
||||
}
|
||||
],
|
||||
"default": "Classic",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"fieldname": "isShiftOpen",
|
||||
"label": "Is POS Shift Open",
|
||||
"fieldtype": "Check",
|
||||
"default": false,
|
||||
"hidden": true
|
||||
},
|
||||
{
|
||||
"fieldname": "itemVisibility",
|
||||
"label": "Item Visibility",
|
||||
"fieldtype": "Select",
|
||||
"options": [
|
||||
{
|
||||
"value": "Inventory Items",
|
||||
"label": "Inventory Items"
|
||||
},
|
||||
{
|
||||
"value": "Non-Inventory Items",
|
||||
"label": "Non-Inventory Items"
|
||||
}
|
||||
],
|
||||
"default": "Inventory Items",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"fieldname": "canChangeRate",
|
||||
"label": "Can Change Rate",
|
||||
"fieldtype": "Check",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"fieldname": "hideUnavailableItems",
|
||||
"label": "Hide Unavailable Items",
|
||||
"fieldtype": "Check",
|
||||
"default": false,
|
||||
"section": "Default"
|
||||
},
|
||||
{
|
||||
"fieldname": "canEditDiscount",
|
||||
"label": "Can Change Discount",
|
||||
"fieldtype": "Check",
|
||||
"default": false,
|
||||
"section": "Default"
|
||||
},
|
||||
{
|
||||
"fieldname": "ignorePricingRule",
|
||||
"label": "Ignore Pricing Rule",
|
||||
"fieldtype": "Check",
|
||||
"section": "Default",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"fieldname": "saveButtonColour",
|
||||
"label": "Save Button Colour",
|
||||
"placeholder": "Select Colour",
|
||||
"fieldtype": "Color",
|
||||
"default": "#9575cd",
|
||||
"options": [
|
||||
{
|
||||
"label": "Red",
|
||||
"value": "#e86674"
|
||||
},
|
||||
{
|
||||
"label": "Orange",
|
||||
"value": "#ff9800"
|
||||
},
|
||||
{
|
||||
"label": "Yellow",
|
||||
"value": "#ecc94b"
|
||||
},
|
||||
{
|
||||
"label": "Green",
|
||||
"value": "#66bb6a"
|
||||
},
|
||||
{
|
||||
"label": "Teal",
|
||||
"value": "#38b2ac"
|
||||
},
|
||||
{
|
||||
"label": "Blue",
|
||||
"value": "#00bcd4"
|
||||
},
|
||||
{
|
||||
"label": "Indigo",
|
||||
"value": "#667eea"
|
||||
},
|
||||
{
|
||||
"label": "Purple",
|
||||
"value": "#9575cd"
|
||||
},
|
||||
{
|
||||
"label": "Pink",
|
||||
"value": "#ed64a6"
|
||||
},
|
||||
{
|
||||
"label": "Black",
|
||||
"value": "#112B42"
|
||||
}
|
||||
],
|
||||
"section": "Colour"
|
||||
},
|
||||
{
|
||||
"fieldname": "cancelButtonColour",
|
||||
"label": "Cancel Button Colour",
|
||||
"placeholder": "Select Colour",
|
||||
"fieldtype": "Color",
|
||||
"default": "#e86674",
|
||||
"options": [
|
||||
{
|
||||
"label": "Red",
|
||||
"value": "#e86674"
|
||||
},
|
||||
{
|
||||
"label": "Orange",
|
||||
"value": "#ff9800"
|
||||
},
|
||||
{
|
||||
"label": "Yellow",
|
||||
"value": "#ecc94b"
|
||||
},
|
||||
{
|
||||
"label": "Green",
|
||||
"value": "#66bb6a"
|
||||
},
|
||||
{
|
||||
"label": "Teal",
|
||||
"value": "#38b2ac"
|
||||
},
|
||||
{
|
||||
"label": "Blue",
|
||||
"value": "#00bcd4"
|
||||
},
|
||||
{
|
||||
"label": "Indigo",
|
||||
"value": "#667eea"
|
||||
},
|
||||
{
|
||||
"label": "Purple",
|
||||
"value": "#9575cd"
|
||||
},
|
||||
{
|
||||
"label": "Pink",
|
||||
"value": "#ed64a6"
|
||||
},
|
||||
{
|
||||
"label": "Black",
|
||||
"value": "#112B42"
|
||||
}
|
||||
],
|
||||
"section": "Colour"
|
||||
},
|
||||
{
|
||||
"fieldname": "submitButtonColour",
|
||||
"label": "Submit Button Colour",
|
||||
"placeholder": "Select Colour",
|
||||
"fieldtype": "Color",
|
||||
"default": "#00bcd4",
|
||||
"options": [
|
||||
{
|
||||
"label": "Red",
|
||||
"value": "#e86674"
|
||||
},
|
||||
{
|
||||
"label": "Orange",
|
||||
"value": "#ff9800"
|
||||
},
|
||||
{
|
||||
"label": "Yellow",
|
||||
"value": "#ecc94b"
|
||||
},
|
||||
{
|
||||
"label": "Green",
|
||||
"value": "#66bb6a"
|
||||
},
|
||||
{
|
||||
"label": "Teal",
|
||||
"value": "#38b2ac"
|
||||
},
|
||||
{
|
||||
"label": "Blue",
|
||||
"value": "#00bcd4"
|
||||
},
|
||||
{
|
||||
"label": "Indigo",
|
||||
"value": "#667eea"
|
||||
},
|
||||
{
|
||||
"label": "Purple",
|
||||
"value": "#9575cd"
|
||||
},
|
||||
{
|
||||
"label": "Pink",
|
||||
"value": "#ed64a6"
|
||||
},
|
||||
{
|
||||
"label": "Black",
|
||||
"value": "#112B42"
|
||||
}
|
||||
],
|
||||
"section": "Colour"
|
||||
},
|
||||
{
|
||||
"fieldname": "heldButtonColour",
|
||||
"label": "Held Button Colour",
|
||||
"placeholder": "Select Colour",
|
||||
"fieldtype": "Color",
|
||||
"default": "#ff9800",
|
||||
"options": [
|
||||
{
|
||||
"label": "Red",
|
||||
"value": "#e86674"
|
||||
},
|
||||
{
|
||||
"label": "Orange",
|
||||
"value": "#ff9800"
|
||||
},
|
||||
{
|
||||
"label": "Yellow",
|
||||
"value": "#ecc94b"
|
||||
},
|
||||
{
|
||||
"label": "Green",
|
||||
"value": "#66bb6a"
|
||||
},
|
||||
{
|
||||
"label": "Teal",
|
||||
"value": "#38b2ac"
|
||||
},
|
||||
{
|
||||
"label": "Blue",
|
||||
"value": "#00bcd4"
|
||||
},
|
||||
{
|
||||
"label": "Indigo",
|
||||
"value": "#667eea"
|
||||
},
|
||||
{
|
||||
"label": "Purple",
|
||||
"value": "#9575cd"
|
||||
},
|
||||
{
|
||||
"label": "Pink",
|
||||
"value": "#ed64a6"
|
||||
},
|
||||
{
|
||||
"label": "Black",
|
||||
"value": "#112B42"
|
||||
}
|
||||
],
|
||||
"section": "Colour"
|
||||
},
|
||||
{
|
||||
"fieldname": "returnButtonColour",
|
||||
"label": "Return Button Colour",
|
||||
"placeholder": "Select Colour",
|
||||
"fieldtype": "Color",
|
||||
"default": "#00bcd4",
|
||||
"options": [
|
||||
{
|
||||
"label": "Red",
|
||||
"value": "#e86674"
|
||||
},
|
||||
{
|
||||
"label": "Orange",
|
||||
"value": "#ff9800"
|
||||
},
|
||||
{
|
||||
"label": "Yellow",
|
||||
"value": "#ecc94b"
|
||||
},
|
||||
{
|
||||
"label": "Green",
|
||||
"value": "#66bb6a"
|
||||
},
|
||||
{
|
||||
"label": "Teal",
|
||||
"value": "#38b2ac"
|
||||
},
|
||||
{
|
||||
"label": "Blue",
|
||||
"value": "#00bcd4"
|
||||
},
|
||||
{
|
||||
"label": "Indigo",
|
||||
"value": "#667eea"
|
||||
},
|
||||
{
|
||||
"label": "Purple",
|
||||
"value": "#9575cd"
|
||||
},
|
||||
{
|
||||
"label": "Pink",
|
||||
"value": "#ed64a6"
|
||||
},
|
||||
{
|
||||
"label": "Black",
|
||||
"value": "#112B42"
|
||||
}
|
||||
],
|
||||
"section": "Colour"
|
||||
},
|
||||
{
|
||||
"fieldname": "buyButtonColour",
|
||||
"label": "Buy Button Colour",
|
||||
"placeholder": "Select Colour",
|
||||
"fieldtype": "Color",
|
||||
"default": "#66bb6a",
|
||||
"options": [
|
||||
{
|
||||
"label": "Red",
|
||||
"value": "#e86674"
|
||||
},
|
||||
{
|
||||
"label": "Orange",
|
||||
"value": "#ff9800"
|
||||
},
|
||||
{
|
||||
"label": "Yellow",
|
||||
"value": "#ecc94b"
|
||||
},
|
||||
{
|
||||
"label": "Green",
|
||||
"value": "#66bb6a"
|
||||
},
|
||||
{
|
||||
"label": "Teal",
|
||||
"value": "#38b2ac"
|
||||
},
|
||||
{
|
||||
"label": "Blue",
|
||||
"value": "#00bcd4"
|
||||
},
|
||||
{
|
||||
"label": "Indigo",
|
||||
"value": "#667eea"
|
||||
},
|
||||
{
|
||||
"label": "Purple",
|
||||
"value": "#9575cd"
|
||||
},
|
||||
{
|
||||
"label": "Pink",
|
||||
"value": "#ed64a6"
|
||||
},
|
||||
{
|
||||
"label": "Black",
|
||||
"value": "#112B42"
|
||||
}
|
||||
],
|
||||
"section": "Colour"
|
||||
},
|
||||
{
|
||||
"fieldname": "payButtonColour",
|
||||
"label": "Pay Button Colour",
|
||||
"placeholder": "Select Colour",
|
||||
"fieldtype": "Color",
|
||||
"default": "#66bb6a",
|
||||
"options": [
|
||||
{
|
||||
"label": "Red",
|
||||
"value": "#e86674"
|
||||
},
|
||||
{
|
||||
"label": "Orange",
|
||||
"value": "#ff9800"
|
||||
},
|
||||
{
|
||||
"label": "Yellow",
|
||||
"value": "#ecc94b"
|
||||
},
|
||||
{
|
||||
"label": "Green",
|
||||
"value": "#66bb6a"
|
||||
},
|
||||
{
|
||||
"label": "Teal",
|
||||
"value": "#38b2ac"
|
||||
},
|
||||
{
|
||||
"label": "Blue",
|
||||
"value": "#00bcd4"
|
||||
},
|
||||
{
|
||||
"label": "Indigo",
|
||||
"value": "#667eea"
|
||||
},
|
||||
{
|
||||
"label": "Purple",
|
||||
"value": "#9575cd"
|
||||
},
|
||||
{
|
||||
"label": "Pink",
|
||||
"value": "#ed64a6"
|
||||
},
|
||||
{
|
||||
"label": "Black",
|
||||
"value": "#112B42"
|
||||
}
|
||||
],
|
||||
"section": "Colour"
|
||||
},
|
||||
{
|
||||
"fieldname": "payAndPrintButtonColour",
|
||||
"label": "Pay And Print Button Colour",
|
||||
"placeholder": "Select Colour",
|
||||
"fieldtype": "Color",
|
||||
"default": "#ff9800",
|
||||
"options": [
|
||||
{
|
||||
"label": "Red",
|
||||
"value": "#e86674"
|
||||
},
|
||||
{
|
||||
"label": "Orange",
|
||||
"value": "#ff9800"
|
||||
},
|
||||
{
|
||||
"label": "Yellow",
|
||||
"value": "#ecc94b"
|
||||
},
|
||||
{
|
||||
"label": "Green",
|
||||
"value": "#66bb6a"
|
||||
},
|
||||
{
|
||||
"label": "Teal",
|
||||
"value": "#38b2ac"
|
||||
},
|
||||
{
|
||||
"label": "Blue",
|
||||
"value": "#00bcd4"
|
||||
},
|
||||
{
|
||||
"label": "Indigo",
|
||||
"value": "#667eea"
|
||||
},
|
||||
{
|
||||
"label": "Purple",
|
||||
"value": "#9575cd"
|
||||
},
|
||||
{
|
||||
"label": "Pink",
|
||||
"value": "#ed64a6"
|
||||
},
|
||||
{
|
||||
"label": "Black",
|
||||
"value": "#112B42"
|
||||
}
|
||||
],
|
||||
"section": "Colour"
|
||||
}
|
||||
],
|
||||
"quickEditFields": [
|
||||
"name",
|
||||
"posCustomer",
|
||||
"inventory",
|
||||
"posPrintTemplate",
|
||||
"posUI",
|
||||
"isShiftOpen",
|
||||
"itemVisibility",
|
||||
"canChangeRate",
|
||||
"hideUnavailableItems",
|
||||
"canEditDiscount",
|
||||
"ignorePricingRule"
|
||||
]
|
||||
}
|
||||
@@ -13,6 +13,14 @@
|
||||
"default": "Stores",
|
||||
"section": "Default"
|
||||
},
|
||||
{
|
||||
"fieldname": "posProfile",
|
||||
"label": "POS Profile",
|
||||
"fieldtype": "Link",
|
||||
"target": "POSProfile",
|
||||
"create": true,
|
||||
"section": "Default"
|
||||
},
|
||||
{
|
||||
"fieldname": "cashAccount",
|
||||
"label": "Counter Cash Account",
|
||||
@@ -128,7 +136,7 @@
|
||||
},
|
||||
{
|
||||
"fieldname": "canEditDiscount",
|
||||
"label": "Can Edit Discount",
|
||||
"label": "Can Change Discount",
|
||||
"fieldtype": "Check",
|
||||
"default": false,
|
||||
"section": "Default"
|
||||
|
||||
@@ -71,6 +71,7 @@ import DefaultCashDenominations from './app/inventory/Point of Sale/DefaultCashD
|
||||
import OpeningAmounts from './app/inventory/Point of Sale/OpeningAmounts.json';
|
||||
import OpeningCash from './app/inventory/Point of Sale/OpeningCash.json';
|
||||
import POSSettings from './app/inventory/Point of Sale/POSSettings.json';
|
||||
import POSProfile from './app/POSProfile.json';
|
||||
import POSOpeningShift from './app/inventory/Point of Sale/POSOpeningShift.json';
|
||||
import POSClosingShift from './app/inventory/Point of Sale/POSClosingShift.json';
|
||||
import POSShiftAmounts from './app/inventory/Point of Sale/POSShiftAmounts.json';
|
||||
@@ -179,6 +180,7 @@ export const appSchemas: Schema[] | SchemaStub[] = [
|
||||
OpeningAmounts as Schema,
|
||||
OpeningCash as Schema,
|
||||
POSSettings as Schema,
|
||||
POSProfile as Schema,
|
||||
POSOpeningShift as Schema,
|
||||
POSClosingShift as Schema,
|
||||
POSShiftAmounts as Schema,
|
||||
|
||||
@@ -277,6 +277,7 @@ import { validateQty } from 'models/helpers';
|
||||
import { InvoiceItem } from 'models/baseModels/InvoiceItem/InvoiceItem';
|
||||
import { SalesInvoice } from 'models/baseModels/SalesInvoice/SalesInvoice';
|
||||
import { showToast } from 'src/utils/interactive';
|
||||
import { ModelNameEnum } from 'models/types';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SelectedItemRow',
|
||||
@@ -300,6 +301,8 @@ export default defineComponent({
|
||||
availableQtyInBatch: 0,
|
||||
|
||||
defaultRate: this.row.rate as Money,
|
||||
profileDiscountSetting: null as boolean | null,
|
||||
profileRateSetting: null as boolean | null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -313,6 +316,31 @@ export default defineComponent({
|
||||
return this.row.isFreeItem;
|
||||
},
|
||||
},
|
||||
|
||||
async mounted() {
|
||||
const posProfileName = this.fyo.singles.POSSettings?.posProfile;
|
||||
|
||||
if (posProfileName) {
|
||||
const profile = await this.fyo.doc.getDoc(
|
||||
ModelNameEnum.POSProfile,
|
||||
posProfileName as string
|
||||
);
|
||||
|
||||
this.profileDiscountSetting =
|
||||
!!profile?.canEditDiscount ||
|
||||
!!this.fyo.singles.POSSettings?.canEditDiscount;
|
||||
|
||||
this.profileRateSetting =
|
||||
!!profile?.canChangeRate ||
|
||||
!!this.fyo.singles.POSSettings?.canChangeRate;
|
||||
} else {
|
||||
this.profileDiscountSetting =
|
||||
!!this.fyo.singles.POSSettings?.canEditDiscount;
|
||||
|
||||
this.profileRateSetting = !!this.fyo.singles.POSSettings?.canChangeRate;
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
async getAvailableQtyInBatch(): Promise<number> {
|
||||
if (!this.row.batch) {
|
||||
@@ -341,11 +369,9 @@ export default defineComponent({
|
||||
},
|
||||
|
||||
isDiscountsReadOnly(isValidDiscount: boolean) {
|
||||
return (
|
||||
this.row.isFreeItem ||
|
||||
!this.fyo.singles.POSSettings?.canEditDiscount ||
|
||||
isValidDiscount
|
||||
);
|
||||
const canEditDiscount = this.profileDiscountSetting;
|
||||
|
||||
return this.row.isFreeItem || !canEditDiscount || isValidDiscount;
|
||||
},
|
||||
async setBatch(batch: string) {
|
||||
this.row.set('batch', batch);
|
||||
@@ -364,9 +390,8 @@ export default defineComponent({
|
||||
);
|
||||
},
|
||||
isRateReadOnly() {
|
||||
return (
|
||||
this.row.isFreeItem || !this.fyo.singles.POSSettings?.canChangeRate
|
||||
);
|
||||
const canChangeRate = this.profileRateSetting;
|
||||
return this.row.isFreeItem || !canChangeRate;
|
||||
},
|
||||
setItemDiscount(type: DiscountType, value: Money | number) {
|
||||
if (type === 'percent') {
|
||||
|
||||
@@ -244,7 +244,9 @@
|
||||
<Button
|
||||
class="w-full"
|
||||
:style="{
|
||||
backgroundColor: fyo.singles.Defaults?.saveButtonColour,
|
||||
backgroundColor:
|
||||
profile?.saveButtonColour ||
|
||||
fyo.singles.Defaults?.saveButtonColour,
|
||||
}"
|
||||
:class="`${isReturnInvoiceEnabledReturn ? 'py-5' : 'py-6'}`"
|
||||
:disabled="!sinvDoc?.party || !sinvDoc?.items?.length"
|
||||
@@ -259,7 +261,9 @@
|
||||
<Button
|
||||
class="w-full"
|
||||
:style="{
|
||||
backgroundColor: fyo.singles.Defaults?.cancelButtonColour,
|
||||
backgroundColor:
|
||||
profile?.cancelButtonColour ||
|
||||
fyo.singles.Defaults?.cancelButtonColour,
|
||||
}"
|
||||
:class="`${isReturnInvoiceEnabledReturn ? 'py-5' : 'py-6'}`"
|
||||
:disabled="!sinvDoc?.items?.length"
|
||||
@@ -279,7 +283,9 @@
|
||||
<Button
|
||||
class="w-full"
|
||||
:style="{
|
||||
backgroundColor: fyo.singles.Defaults?.heldButtonColour,
|
||||
backgroundColor:
|
||||
profile?.heldButtonColour ||
|
||||
fyo.singles.Defaults?.heldButtonColour,
|
||||
}"
|
||||
:class="`${isReturnInvoiceEnabledReturn ? 'py-5' : 'py-6'}`"
|
||||
@click="emitEvent('toggleModal', 'SavedInvoice', true)"
|
||||
@@ -295,7 +301,9 @@
|
||||
v-if="isReturnInvoiceEnabledReturn"
|
||||
class="w-full py-5"
|
||||
:style="{
|
||||
backgroundColor: fyo.singles.Defaults?.returnButtonColour,
|
||||
backgroundColor:
|
||||
profile?.returnButtonColour ||
|
||||
fyo.singles.Defaults?.returnButtonColour,
|
||||
}"
|
||||
@click="
|
||||
emitEvent('toggleModal', 'ReturnSalesInvoice', true)
|
||||
@@ -311,7 +319,9 @@
|
||||
v-else
|
||||
class="w-full"
|
||||
:style="{
|
||||
backgroundColor: fyo.singles.Defaults?.payButtonColour,
|
||||
backgroundColor:
|
||||
profile?.payButton ||
|
||||
fyo.singles.Defaults?.payButtonColour,
|
||||
}"
|
||||
:class="`${isReturnInvoiceEnabledReturn ? 'py-5' : 'py-6'}`"
|
||||
:disabled="disablePayButton"
|
||||
@@ -328,7 +338,9 @@
|
||||
v-if="isReturnInvoiceEnabledReturn"
|
||||
class="w-full mt-2 py-5"
|
||||
:style="{
|
||||
backgroundColor: fyo.singles.Defaults?.payButtonColour,
|
||||
backgroundColor:
|
||||
profile?.payButtonColour ||
|
||||
fyo.singles.Defaults?.payButtonColour,
|
||||
}"
|
||||
:disabled="disablePayButton"
|
||||
@click="emitEvent('toggleModal', 'Payment', true)"
|
||||
@@ -370,6 +382,7 @@ import { POSItem, ItemQtyMap } from 'src/components/POS/types';
|
||||
import ItemsGrid from 'src/components/POS/Classic/ItemsGrid.vue';
|
||||
import ItemsTable from 'src/components/POS/Classic/ItemsTable.vue';
|
||||
import ReturnSalesInvoiceModal from './ReturnSalesInvoiceModal.vue';
|
||||
import { POSProfile } from 'models/baseModels/POSProfile/PosProfile';
|
||||
import MultiLabelLink from 'src/components/Controls/MultiLabelLink.vue';
|
||||
import { SalesInvoice } from 'models/baseModels/SalesInvoice/SalesInvoice';
|
||||
import SelectedItemTable from 'src/components/POS/Classic/SelectedItemTable.vue';
|
||||
@@ -454,6 +467,11 @@ export default defineComponent({
|
||||
type: Array as PropType<POSItem[] | undefined>,
|
||||
default: () => [],
|
||||
},
|
||||
profile: {
|
||||
type: Object as PropType<POSProfile>,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
emits: [
|
||||
'addItem',
|
||||
|
||||
@@ -180,7 +180,9 @@
|
||||
<Button
|
||||
class="mt-2 w-full py-5"
|
||||
:style="{
|
||||
backgroundColor: fyo.singles.Defaults?.saveButtonColour,
|
||||
backgroundColor:
|
||||
profile?.saveButtonColour ||
|
||||
fyo.singles.Defaults?.saveButtonColour,
|
||||
}"
|
||||
:disabled="!sinvDoc?.party || !sinvDoc?.items?.length"
|
||||
@click="$emit('saveInvoiceAction')"
|
||||
@@ -194,7 +196,9 @@
|
||||
<Button
|
||||
class="w-full mt-2 py-5"
|
||||
:style="{
|
||||
backgroundColor: fyo.singles.Defaults?.heldButtonColour,
|
||||
backgroundColor:
|
||||
profile?.heldButtonColour ||
|
||||
fyo.singles.Defaults?.heldButtonColour,
|
||||
}"
|
||||
@click="emitEvent('toggleModal', 'SavedInvoice', true)"
|
||||
>
|
||||
@@ -209,7 +213,9 @@
|
||||
<Button
|
||||
class="mt-2 w-full py-5"
|
||||
:style="{
|
||||
backgroundColor: fyo.singles.Defaults?.cancelButtonColour,
|
||||
backgroundColor:
|
||||
profile?.cancelButtonColour ||
|
||||
fyo.singles.Defaults?.cancelButtonColour,
|
||||
}"
|
||||
:disabled="!sinvDoc?.items?.length"
|
||||
@click="() => $emit('clearValues')"
|
||||
@@ -224,7 +230,9 @@
|
||||
v-if="isReturnInvoiceEnabledReturn"
|
||||
class="mt-2 w-full py-5"
|
||||
:style="{
|
||||
backgroundColor: fyo.singles.Defaults?.returnButtonColour,
|
||||
backgroundColor:
|
||||
profile?.returnButtonColour ||
|
||||
fyo.singles.Defaults?.returnButtonColour,
|
||||
}"
|
||||
@click="emitEvent('toggleModal', 'ReturnSalesInvoice', true)"
|
||||
>
|
||||
@@ -238,7 +246,9 @@
|
||||
v-else
|
||||
class="mt-2 w-full py-5"
|
||||
:style="{
|
||||
backgroundColor: fyo.singles.Defaults?.buyButtonColour,
|
||||
backgroundColor:
|
||||
profile?.buyButtonColour ||
|
||||
fyo.singles.Defaults?.buyButtonColour,
|
||||
}"
|
||||
:disabled="disablePayButton"
|
||||
@click="emitEvent('toggleModal', 'Payment', true)"
|
||||
@@ -255,7 +265,9 @@
|
||||
v-if="isReturnInvoiceEnabledReturn"
|
||||
class="mt-2 w-full py-5"
|
||||
:style="{
|
||||
backgroundColor: fyo.singles.Defaults?.buyButtonColour,
|
||||
backgroundColor:
|
||||
profile?.buyButtonColour ||
|
||||
fyo.singles.Defaults?.buyButtonColour,
|
||||
}"
|
||||
:disabled="disablePayButton"
|
||||
@click="emitEvent('toggleModal', 'Payment', true)"
|
||||
@@ -380,6 +392,7 @@ import Barcode from 'src/components/Controls/Barcode.vue';
|
||||
import ClosePOSShiftModal from './ClosePOSShiftModal.vue';
|
||||
import LoyaltyProgramModal from './LoyaltyProgramModal.vue';
|
||||
import ReturnSalesInvoiceModal from './ReturnSalesInvoiceModal.vue';
|
||||
import { POSProfile } from 'models/baseModels/POSProfile/PosProfile';
|
||||
import MultiLabelLink from 'src/components/Controls/MultiLabelLink.vue';
|
||||
import { POSItem, PosEmits, ItemQtyMap } from 'src/components/POS/types';
|
||||
import { SalesInvoice } from 'models/baseModels/SalesInvoice/SalesInvoice';
|
||||
@@ -465,6 +478,11 @@ export default defineComponent({
|
||||
type: Array as PropType<POSItem[] | undefined>,
|
||||
default: () => [],
|
||||
},
|
||||
profile: {
|
||||
type: Object as PropType<POSProfile>,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
emits: [
|
||||
'addItem',
|
||||
|
||||
+42
-5
@@ -11,8 +11,12 @@
|
||||
</slot>
|
||||
</PageHeader>
|
||||
<ClassicPOS
|
||||
v-if="fyo.singles.POSSettings?.posUI == 'Classic'"
|
||||
v-if="
|
||||
posProfile?.posUI === 'Classic' ||
|
||||
(!posProfile?.posUI && fyo.singles.POSSettings?.posUI === 'Classic')
|
||||
"
|
||||
:table-view="tableView"
|
||||
:profile="(posProfile as POSProfile)"
|
||||
:total-quantity="totalQuantity"
|
||||
:item-quantity-qap="itemQtyMap"
|
||||
:loyalty-points="loyaltyPoints"
|
||||
@@ -61,6 +65,7 @@
|
||||
<ModernPOS
|
||||
v-else
|
||||
:table-view="tableView"
|
||||
:profile="(posProfile as POSProfile)"
|
||||
:total-quantity="totalQuantity"
|
||||
:item-quantity-qap="itemQtyMap"
|
||||
:loyalty-points="loyaltyPoints"
|
||||
@@ -123,6 +128,7 @@ import PageHeader from 'src/components/PageHeader.vue';
|
||||
import { computed, defineComponent, inject } from 'vue';
|
||||
import { Payment } from 'models/baseModels/Payment/Payment';
|
||||
import { ModalName, modalNames } from 'src/components/POS/types';
|
||||
import { POSProfile } from 'models/baseModels/POSProfile/PosProfile';
|
||||
import { InvoiceItem } from 'models/baseModels/InvoiceItem/InvoiceItem';
|
||||
import { SalesInvoice } from 'models/baseModels/SalesInvoice/SalesInvoice';
|
||||
import { SalesInvoiceItem } from 'models/baseModels/SalesInvoiceItem/SalesInvoiceItem';
|
||||
@@ -224,6 +230,7 @@ export default defineComponent({
|
||||
|
||||
paymentDoc: {} as Payment,
|
||||
sinvDoc: {} as SalesInvoice,
|
||||
posProfile: {} as POSProfile,
|
||||
itemQtyMap: {} as ItemQtyMap,
|
||||
coupons: {} as AppliedCouponCodes,
|
||||
itemSerialNumbers: {} as ItemSerialNumbers,
|
||||
@@ -259,6 +266,7 @@ export default defineComponent({
|
||||
|
||||
async mounted() {
|
||||
await this.setItems();
|
||||
await this.loadPOSProfile();
|
||||
},
|
||||
async activated() {
|
||||
toggleSidebar(false);
|
||||
@@ -293,6 +301,19 @@ export default defineComponent({
|
||||
this.loyaltyPoints = party[0]?.loyaltyPoints as number;
|
||||
},
|
||||
|
||||
async loadPOSProfile() {
|
||||
const posProfileName = fyo.singles.POSSettings?.posProfile;
|
||||
|
||||
if (!posProfileName) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.posProfile = (await fyo.doc.getDoc(
|
||||
ModelNameEnum.POSProfile,
|
||||
posProfileName as string
|
||||
)) as POSProfile;
|
||||
},
|
||||
|
||||
async handleItemSearch(searchTerm: string, addItem?: boolean) {
|
||||
this.itemSearchTerm = searchTerm;
|
||||
if (!addItem) return;
|
||||
@@ -467,8 +488,12 @@ export default defineComponent({
|
||||
},
|
||||
async setItems() {
|
||||
const filters: Record<string, boolean | string> = {};
|
||||
const itemVisibility = this.fyo.singles.POSSettings?.itemVisibility;
|
||||
const itemVisibility =
|
||||
this.posProfile?.itemVisibility ??
|
||||
this.fyo.singles.POSSettings?.itemVisibility;
|
||||
|
||||
const hideUnavailable =
|
||||
this.posProfile?.hideUnavailableItems ??
|
||||
this.fyo.singles.POSSettings?.hideUnavailableItems;
|
||||
|
||||
if (itemVisibility === 'Inventory Items') {
|
||||
@@ -536,7 +561,10 @@ export default defineComponent({
|
||||
this.paymentMethod = method;
|
||||
},
|
||||
setDefaultCustomer() {
|
||||
this.defaultCustomer = this.fyo.singles.Defaults?.posCustomer ?? '';
|
||||
this.defaultCustomer =
|
||||
this.posProfile?.posCustomer ??
|
||||
this.fyo.singles.Defaults?.posCustomer ??
|
||||
'';
|
||||
this.sinvDoc.party = this.defaultCustomer;
|
||||
},
|
||||
setItemDiscounts() {
|
||||
@@ -568,7 +596,11 @@ export default defineComponent({
|
||||
);
|
||||
},
|
||||
ignorePricingRules(): boolean {
|
||||
return !!fyo.singles.POSSettings?.ignorePricingRule;
|
||||
if (this.posProfile) {
|
||||
return this.posProfile.ignorePricingRule as boolean;
|
||||
}
|
||||
|
||||
return !!this.fyo.singles.POSSettings?.ignorePricingRule;
|
||||
},
|
||||
setTotalTaxedAmount() {
|
||||
this.totalTaxedAmount = getTotalTaxedAmount(this.sinvDoc as SalesInvoice);
|
||||
@@ -886,7 +918,12 @@ export default defineComponent({
|
||||
continue;
|
||||
}
|
||||
|
||||
item.location = fyo.singles.POSSettings?.inventory;
|
||||
if (this.posProfile) {
|
||||
item.location = this.posProfile.inventory;
|
||||
} else {
|
||||
item.location = fyo.singles.POSSettings?.inventory;
|
||||
}
|
||||
|
||||
item.serialNumber =
|
||||
this.itemSerialNumbers[item.item as string] ?? undefined;
|
||||
}
|
||||
|
||||
@@ -273,6 +273,20 @@ export default defineComponent({
|
||||
(this.doc as Doc).isPOS
|
||||
) {
|
||||
templateName = this.fyo.singles.Defaults?.posPrintTemplate;
|
||||
|
||||
const posProfileName = this.fyo.singles.POSSettings
|
||||
?.posProfile as string;
|
||||
|
||||
if (posProfileName) {
|
||||
const posProfile = await this.fyo.doc.getDoc(
|
||||
ModelNameEnum.POSProfile,
|
||||
posProfileName
|
||||
);
|
||||
|
||||
if (posProfile.posPrintTemplate) {
|
||||
templateName = posProfile.posPrintTemplate;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
templateName = this.fyo.singles.Defaults?.get(defaultName);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user