2
0
mirror of https://github.com/frappe/books.git synced 2024-12-22 10:58:59 +00:00

Merge pull request #1037 from AbleKSaju/fix-pricingRule

fix: apply pricing rule in POS
This commit is contained in:
Akshay 2024-11-29 10:39:12 +05:30 committed by GitHub
commit f830b109c1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 96 additions and 165 deletions

View File

@ -18,9 +18,9 @@ import {
createLoyaltyPointEntry, createLoyaltyPointEntry,
filterPricingRules, filterPricingRules,
getAddedLPWithGrandTotal, getAddedLPWithGrandTotal,
getApplicableCouponCodesName,
getExchangeRate, getExchangeRate,
getNumberSeries, getNumberSeries,
removeUnusedCoupons,
getPricingRulesConflicts, getPricingRulesConflicts,
removeLoyaltyPoint, removeLoyaltyPoint,
roundFreeItemQty, roundFreeItemQty,
@ -41,7 +41,7 @@ import { TaxSummary } from '../TaxSummary/TaxSummary';
import { ReturnDocItem } from 'models/inventory/types'; import { ReturnDocItem } from 'models/inventory/types';
import { AccountFieldEnum, PaymentTypeEnum } from '../Payment/types'; import { AccountFieldEnum, PaymentTypeEnum } from '../Payment/types';
import { PricingRule } from '../PricingRule/PricingRule'; import { PricingRule } from '../PricingRule/PricingRule';
import { ApplicableCouponCodes, ApplicablePricingRules } from './types'; import { ApplicablePricingRules } from './types';
import { PricingRuleDetail } from '../PricingRuleDetail/PricingRuleDetail'; import { PricingRuleDetail } from '../PricingRuleDetail/PricingRuleDetail';
import { LoyaltyProgram } from '../LoyaltyProgram/LoyaltyProgram'; import { LoyaltyProgram } from '../LoyaltyProgram/LoyaltyProgram';
import { AppliedCouponCodes } from '../AppliedCouponCodes/AppliedCouponCodes'; import { AppliedCouponCodes } from '../AppliedCouponCodes/AppliedCouponCodes';
@ -758,7 +758,8 @@ export abstract class Invoice extends Transactional {
} }
const pricingRule = await this.getPricingRule(); const pricingRule = await this.getPricingRule();
if (!pricingRule) {
if (!pricingRule || !pricingRule.length) {
return false; return false;
} }
@ -1074,30 +1075,7 @@ export abstract class Invoice extends Transactional {
this.clearFreeItems(); this.clearFreeItems();
} }
if (!this.coupons?.length) { await removeUnusedCoupons(this as SalesInvoice);
return;
}
const applicableCouponCodes = await Promise.all(
this.coupons?.map(async (coupon) => {
return await getApplicableCouponCodesName(
coupon.coupons as string,
this as SalesInvoice
);
})
);
const flattedApplicableCouponCodes = applicableCouponCodes?.flat();
const couponCodeDoc = (await this.fyo.doc.getDoc(
ModelNameEnum.CouponCode,
this.coupons[0].coupons
)) as CouponCode;
couponCodeDoc.removeUnusedCoupons(
flattedApplicableCouponCodes as ApplicableCouponCodes[],
this as SalesInvoice
);
} }
async beforeCancel(): Promise<void> { async beforeCancel(): Promise<void> {

View File

@ -157,7 +157,7 @@ test('disabled coupon codes is not applied', async (t) => {
await sinv.runFormulas(); await sinv.runFormulas();
t.equal(sinv.pricingRuleDetail?.length, undefined); t.equal(sinv.pricingRuleDetail?.length, 0);
}); });
test('Coupon code not created: coupons min amount must be lesser than coupons max.', async (t) => { test('Coupon code not created: coupons min amount must be lesser than coupons max.', async (t) => {

View File

@ -146,7 +146,7 @@ test('pricing rule is not applied when item qty is < min qty', async (t) => {
await sinv.append('items', { item: itemMap.Jacket.name, quantity: 3 }); await sinv.append('items', { item: itemMap.Jacket.name, quantity: 3 });
await sinv.runFormulas(); await sinv.runFormulas();
t.equal(sinv.pricingRuleDetail?.length, undefined); t.equal(sinv.pricingRuleDetail?.length, 0);
}); });
test('pricing rule is not applied when item qty is > max qty', async (t) => { test('pricing rule is not applied when item qty is > max qty', async (t) => {
@ -158,7 +158,7 @@ test('pricing rule is not applied when item qty is > max qty', async (t) => {
await sinv.append('items', { item: itemMap.Jacket.name, quantity: 10 }); await sinv.append('items', { item: itemMap.Jacket.name, quantity: 10 });
await sinv.runFormulas(); await sinv.runFormulas();
t.equal(sinv.pricingRuleDetail?.length, undefined); t.equal(sinv.pricingRuleDetail?.length, 0);
}); });
test('pricing rule is applied when filtered by min and max amount', async (t) => { test('pricing rule is applied when filtered by min and max amount', async (t) => {
@ -200,11 +200,7 @@ test('Pricing Rule is not applied when item amount is < min amount', async (t)
}); });
await sinv.runFormulas(); await sinv.runFormulas();
t.equal( t.equal(sinv.pricingRuleDetail?.length, 0, 'Pricing Rule is not applied');
sinv.pricingRuleDetail?.length,
undefined,
'Pricing Rule is not applied'
);
}); });
test('Pricing Rule is not applied when item amount is > max amount', async (t) => { test('Pricing Rule is not applied when item amount is > max amount', async (t) => {
@ -220,11 +216,7 @@ test('Pricing Rule is not applied when item amount is > max amount', async (t) =
}); });
await sinv.runFormulas(); await sinv.runFormulas();
t.equal( t.equal(sinv.pricingRuleDetail?.length, 0, 'Pricing Rule is not applied');
sinv.pricingRuleDetail?.length,
undefined,
'Pricing Rule is not applied'
);
}); });
test('Pricing Rule is not applied when sinvDate < validFrom date', async (t) => { test('Pricing Rule is not applied when sinvDate < validFrom date', async (t) => {
@ -240,11 +232,7 @@ test('Pricing Rule is not applied when sinvDate < validFrom date', async (t) =>
}); });
await sinv.runFormulas(); await sinv.runFormulas();
t.equal( t.equal(sinv.pricingRuleDetail?.length, 0, 'Pricing Rule is not applied');
sinv.pricingRuleDetail?.length,
undefined,
'Pricing Rule is not applied'
);
}); });
test('Pricing Rule is not applied when sinvDate > validFrom date', async (t) => { test('Pricing Rule is not applied when sinvDate > validFrom date', async (t) => {
@ -260,11 +248,7 @@ test('Pricing Rule is not applied when sinvDate > validFrom date', async (t) =>
}); });
await sinv.runFormulas(); await sinv.runFormulas();
t.equal( t.equal(sinv.pricingRuleDetail?.length, 0, 'Pricing Rule is not applied');
sinv.pricingRuleDetail?.length,
undefined,
'Pricing Rule is not applied'
);
}); });
test('Pricing Rule is applied when filtered by qty, amount and dates', async (t) => { test('Pricing Rule is applied when filtered by qty, amount and dates', async (t) => {
@ -320,11 +304,7 @@ test('Pricing Rule is not applied when qty condition is false, rest is true', as
}); });
await sinv.runFormulas(); await sinv.runFormulas();
t.equal( t.equal(sinv.pricingRuleDetail?.length, 0, 'Pricing Rule is not applied');
sinv.pricingRuleDetail?.length,
undefined,
'Pricing Rule is not applied'
);
}); });
test('Pricing Rule is not applied when amount condition is false, rest is true', async (t) => { test('Pricing Rule is not applied when amount condition is false, rest is true', async (t) => {
@ -340,11 +320,7 @@ test('Pricing Rule is not applied when amount condition is false, rest is true',
}); });
await sinv.runFormulas(); await sinv.runFormulas();
t.equal( t.equal(sinv.pricingRuleDetail?.length, 0, 'Pricing Rule is not applied');
sinv.pricingRuleDetail?.length,
undefined,
'Pricing Rule is not applied'
);
}); });
test('Pricing Rule is not applied when validity condition is false, rest is true', async (t) => { test('Pricing Rule is not applied when validity condition is false, rest is true', async (t) => {
@ -360,11 +336,7 @@ test('Pricing Rule is not applied when validity condition is false, rest is true
}); });
await sinv.runFormulas(); await sinv.runFormulas();
t.equal( t.equal(sinv.pricingRuleDetail?.length, 0, 'Pricing Rule is not applied');
sinv.pricingRuleDetail?.length,
undefined,
'Pricing Rule is not applied'
);
}); });
test('create two pricing rules, Highest priority pricing rule is applied', async (t) => { test('create two pricing rules, Highest priority pricing rule is applied', async (t) => {

View File

@ -12,7 +12,10 @@ import {
import { Fyo, t } from 'fyo'; import { Fyo, t } from 'fyo';
import { InvoiceStatus, ModelNameEnum } from './types'; import { InvoiceStatus, ModelNameEnum } from './types';
import { ApplicablePricingRules } from './baseModels/Invoice/types'; import {
ApplicableCouponCodes,
ApplicablePricingRules,
} from './baseModels/Invoice/types';
import { AppliedCouponCodes } from './baseModels/AppliedCouponCodes/AppliedCouponCodes'; import { AppliedCouponCodes } from './baseModels/AppliedCouponCodes/AppliedCouponCodes';
import { CollectionRulesItems } from './baseModels/CollectionRulesItems/CollectionRulesItems'; import { CollectionRulesItems } from './baseModels/CollectionRulesItems/CollectionRulesItems';
import { CouponCode } from './baseModels/CouponCode/CouponCode'; import { CouponCode } from './baseModels/CouponCode/CouponCode';
@ -767,19 +770,6 @@ export function getLoyaltyProgramTier(
return loyaltyProgramTier; return loyaltyProgramTier;
} }
export async function updatePricingRuleItem(doc: SalesInvoice) {
const pricingRule = (await getPricingRule(doc)) as ApplicablePricingRules[];
let appliedPricingRuleCount = doc?.pricingRuleDetail?.length;
if (appliedPricingRuleCount !== pricingRule?.length) {
appliedPricingRuleCount = pricingRule?.length;
await doc?.appendPricingRuleDetail(pricingRule);
await doc?.applyProductDiscount();
}
}
export async function removeLoyaltyPoint(doc: Doc) { export async function removeLoyaltyPoint(doc: Doc) {
if (!doc.loyaltyProgram) { if (!doc.loyaltyProgram) {
return; return;
@ -1098,6 +1088,33 @@ export function canApplyCouponCode(
return true; return true;
} }
export async function removeUnusedCoupons(sinvDoc: SalesInvoice) {
if (!sinvDoc.coupons?.length) {
return;
}
const applicableCouponCodes = await Promise.all(
sinvDoc.coupons?.map(async (coupon) => {
return await getApplicableCouponCodesName(
coupon.coupons as string,
sinvDoc
);
})
);
const flattedApplicableCouponCodes = applicableCouponCodes?.flat();
const couponCodeDoc = (await sinvDoc.fyo.doc.getDoc(
ModelNameEnum.CouponCode,
sinvDoc.coupons[0].coupons
)) as CouponCode;
couponCodeDoc.removeUnusedCoupons(
flattedApplicableCouponCodes as ApplicableCouponCodes[],
sinvDoc
);
}
export async function getApplicableCouponCodesName( export async function getApplicableCouponCodesName(
couponName: string, couponName: string,
sinvDoc: SalesInvoice sinvDoc: SalesInvoice
@ -1240,30 +1257,6 @@ export function removeFreeItems(sinvDoc: SalesInvoice) {
} }
} }
export async function updatePricingRule(sinvDoc: SalesInvoice) {
const applicablePricingRuleNames = await getPricingRule(sinvDoc);
if (!applicablePricingRuleNames || !applicablePricingRuleNames.length) {
sinvDoc.pricingRuleDetail = undefined;
sinvDoc.isPricingRuleApplied = false;
removeFreeItems(sinvDoc);
return;
}
const appliedPricingRuleCount = sinvDoc?.items?.filter(
(val) => val.isFreeItem
).length;
setTimeout(() => {
void (async () => {
if (appliedPricingRuleCount !== applicablePricingRuleNames?.length) {
await sinvDoc.appendPricingRuleDetail(applicablePricingRuleNames);
await sinvDoc.applyProductDiscount();
}
})();
}, 1);
}
export function getPricingRulesConflicts( export function getPricingRulesConflicts(
pricingRules: PricingRule[] pricingRules: PricingRule[]
): undefined | boolean { ): undefined | boolean {

View File

@ -275,9 +275,6 @@ import { SalesInvoiceItem } from 'models/baseModels/SalesInvoiceItem/SalesInvoic
import { Money } from 'pesa'; import { Money } from 'pesa';
import { DiscountType } from '../types'; import { DiscountType } from '../types';
import { validateSerialNumberCount } from 'src/utils/pos'; import { validateSerialNumberCount } from 'src/utils/pos';
import { getPricingRule } from 'models/helpers';
import { SalesInvoice } from 'models/baseModels/SalesInvoice/SalesInvoice';
import { ApplicablePricingRules } from 'models/baseModels/Invoice/types';
export default defineComponent({ export default defineComponent({
name: 'SelectedItemRow', name: 'SelectedItemRow',
@ -285,7 +282,7 @@ export default defineComponent({
props: { props: {
row: { type: SalesInvoiceItem, required: true }, row: { type: SalesInvoiceItem, required: true },
}, },
emits: ['runSinvFormulas', 'setItemSerialNumbers', 'addItem'], emits: ['runSinvFormulas', 'applyPricingRule'],
setup() { setup() {
return { return {
isDiscountingEnabled: inject('isDiscountingEnabled') as boolean, isDiscountingEnabled: inject('isDiscountingEnabled') as boolean,
@ -363,7 +360,7 @@ export default defineComponent({
this.row.set('quantity', quantity); this.row.set('quantity', quantity);
if (!this.row.isFreeItem) { if (!this.row.isFreeItem) {
await this.updatePricingRuleItem(); this.$emit('applyPricingRule');
this.$emit('runSinvFormulas'); this.$emit('runSinvFormulas');
} }
}, },
@ -371,22 +368,7 @@ export default defineComponent({
this.row.parentdoc?.remove('items', row?.idx as number); this.row.parentdoc?.remove('items', row?.idx as number);
if (!row.isFreeItem) { if (!row.isFreeItem) {
await this.updatePricingRuleItem(); this.$emit('applyPricingRule');
}
},
async updatePricingRuleItem() {
const pricingRule = (await getPricingRule(
this.row.parentdoc as SalesInvoice
)) as ApplicablePricingRules[];
let appliedPricingRuleCount =
this.row.parentdoc?.pricingRuleDetail?.length;
if (appliedPricingRuleCount !== pricingRule?.length) {
appliedPricingRuleCount = pricingRule?.length;
await this.row.parentdoc?.appendPricingRuleDetail(pricingRule);
await this.row.parentdoc?.applyProductDiscount();
} }
}, },
}, },

View File

@ -54,6 +54,7 @@
<SelectedItemRow <SelectedItemRow
:row="(row as SalesInvoiceItem)" :row="(row as SalesInvoiceItem)"
@run-sinv-formulas="runSinvFormulas" @run-sinv-formulas="runSinvFormulas"
@apply-pricing-rule="$emit('applyPricingRule')"
/> />
</Row> </Row>
</div> </div>
@ -93,6 +94,7 @@ export default defineComponent({
isExapanded: false, isExapanded: false,
}; };
}, },
emits: ['applyPricingRule'],
computed: { computed: {
ratio() { ratio() {
return [0.1, 1, 0.8, 0.8, 0.8, 0.8, 0.2]; return [0.1, 1, 0.8, 0.8, 0.8, 0.8, 0.2];

View File

@ -248,8 +248,6 @@ import { defineComponent } from 'vue';
import { SalesInvoiceItem } from 'models/baseModels/SalesInvoiceItem/SalesInvoiceItem'; import { SalesInvoiceItem } from 'models/baseModels/SalesInvoiceItem/SalesInvoiceItem';
import { Money } from 'pesa'; import { Money } from 'pesa';
import { validateSerialNumberCount } from 'src/utils/pos'; import { validateSerialNumberCount } from 'src/utils/pos';
import { updatePricingRuleItem } from 'models/helpers';
import { SalesInvoice } from 'models/baseModels/SalesInvoice/SalesInvoice';
export default defineComponent({ export default defineComponent({
name: 'ModernPOSSelectedItemRow', name: 'ModernPOSSelectedItemRow',
@ -257,7 +255,7 @@ export default defineComponent({
props: { props: {
row: { type: SalesInvoiceItem, required: true }, row: { type: SalesInvoiceItem, required: true },
}, },
emits: ['toggleModal', 'runSinvFormulas', 'selectedRow'], emits: ['toggleModal', 'runSinvFormulas', 'selectedRow', 'applyPricingRule'],
setup() { setup() {
return { return {
@ -331,7 +329,7 @@ export default defineComponent({
this.row.parentdoc?.remove('items', row?.idx as number); this.row.parentdoc?.remove('items', row?.idx as number);
if (!row.isFreeItem) { if (!row.isFreeItem) {
await updatePricingRuleItem(this.row.parentdoc as SalesInvoice); this.$emit('applyPricingRule');
} }
}, },
}, },

View File

@ -82,7 +82,7 @@ export default defineComponent({
isExapanded: false, isExapanded: false,
}; };
}, },
emits: ['toggleModal', 'selectedRow'], emits: ['toggleModal', 'selectedRow', 'applyPricingRule'],
computed: { computed: {
ratio() { ratio() {
return [0.1, 0.8, 0.4, 0.8, 0.8, 0.3]; return [0.1, 0.8, 0.4, 0.8, 0.8, 0.3];
@ -141,6 +141,9 @@ export default defineComponent({
selectedItemRow(row: SalesInvoiceItem, field: string) { selectedItemRow(row: SalesInvoiceItem, field: string) {
this.$emit('selectedRow', row, field); this.$emit('selectedRow', row, field);
}, },
emitApplyPricingRule() {
this.$emit('applyPricingRule');
},
isNumeric, isNumeric,
}, },
}); });

View File

@ -25,6 +25,7 @@ export type PosEmits =
| 'setCashAmount' | 'setCashAmount'
| 'setCouponsCount' | 'setCouponsCount'
| 'routeToSinvList' | 'routeToSinvList'
| 'applyPricingRule'
| 'setTransferRefNo' | 'setTransferRefNo'
| 'setLoyaltyPoints' | 'setLoyaltyPoints'
| 'setTransferAmount' | 'setTransferAmount'

View File

@ -30,6 +30,7 @@
<CouponCodeModal <CouponCodeModal
:open-modal="openCouponCodeModal" :open-modal="openCouponCodeModal"
@apply-pricing-rule="emitEvent('applyPricingRule')"
@toggle-modal="emitEvent('toggleModal', 'CouponCode')" @toggle-modal="emitEvent('toggleModal', 'CouponCode')"
@set-coupons-count="(count) => emitEvent('setCouponsCount', count)" @set-coupons-count="(count) => emitEvent('setCouponsCount', count)"
/> />
@ -44,7 +45,6 @@
@toggle-modal="emitEvent('toggleModal', 'Payment')" @toggle-modal="emitEvent('toggleModal', 'Payment')"
@set-cash-amount="(amount) => emitEvent('setCashAmount', amount)" @set-cash-amount="(amount) => emitEvent('setCashAmount', amount)"
@set-transfer-ref-no="(ref) => emitEvent('setTransferRefNo', ref)" @set-transfer-ref-no="(ref) => emitEvent('setTransferRefNo', ref)"
@set-coupons-count="(count) => emitEvent('setCouponsCount', count)"
@set-transfer-amount="(amount) => emitEvent('setTransferAmount', amount)" @set-transfer-amount="(amount) => emitEvent('setTransferAmount', amount)"
@set-transfer-clearance-date=" @set-transfer-clearance-date="
(date) => emitEvent('setTransferClearanceDate', date) (date) => emitEvent('setTransferClearanceDate', date)
@ -158,7 +158,9 @@
@change="(value:string) => $emit('setCustomer',value)" @change="(value:string) => $emit('setCustomer',value)"
/> />
<SelectedItemTable /> <SelectedItemTable
@apply-pricing-rule="emitEvent('applyPricingRule')"
/>
</div> </div>
<div <div
@ -393,6 +395,7 @@ export default defineComponent({
'routeToSinvList', 'routeToSinvList',
'setTransferRefNo', 'setTransferRefNo',
'setLoyaltyPoints', 'setLoyaltyPoints',
'applyPricingRule',
'saveInvoiceAction', 'saveInvoiceAction',
'createTransaction', 'createTransaction',
'setTransferAmount', 'setTransferAmount',

View File

@ -12,7 +12,7 @@
:style="{ height: appliedCoupons.length >= 2 ? '11vh' : '8vh' }" :style="{ height: appliedCoupons.length >= 2 ? '11vh' : '8vh' }"
> >
<Row <Row
v-for="(coupon,index) in appliedCoupons as any" v-for="(coupon,index) in appliedCoupons as AppliedCouponCodes[]"
:key="index" :key="index"
:ratio="ratio" :ratio="ratio"
:border="true" :border="true"
@ -115,10 +115,11 @@ import { showToast } from 'src/utils/interactive';
import { AppliedCouponCodes } from 'models/baseModels/AppliedCouponCodes/AppliedCouponCodes'; import { AppliedCouponCodes } from 'models/baseModels/AppliedCouponCodes/AppliedCouponCodes';
import Link from 'src/components/Controls/Link.vue'; import Link from 'src/components/Controls/Link.vue';
import { ModelNameEnum } from 'models/types'; import { ModelNameEnum } from 'models/types';
import { updatePricingRule, validateCouponCode } from 'models/helpers'; import { validateCouponCode } from 'models/helpers';
import { Field } from 'schemas/types'; import { Field } from 'schemas/types';
import FormControl from 'src/components/Controls/FormControl.vue'; import FormControl from 'src/components/Controls/FormControl.vue';
import Row from 'src/components/Row.vue'; import Row from 'src/components/Row.vue';
import { InvoiceItem } from 'models/baseModels/InvoiceItem/InvoiceItem';
export default defineComponent({ export default defineComponent({
name: 'CouponCodeModal', name: 'CouponCodeModal',
@ -129,7 +130,7 @@ export default defineComponent({
FormControl, FormControl,
Row, Row,
}, },
emits: ['setCouponsCount', 'toggleModal'], emits: ['setCouponsCount', 'toggleModal', 'applyPricingRule'],
setup() { setup() {
return { return {
@ -181,13 +182,11 @@ export default defineComponent({
await this.sinvDoc.append('coupons', { coupons: this.couponCode }); await this.sinvDoc.append('coupons', { coupons: this.couponCode });
await updatePricingRule(this.sinvDoc); this.$emit('applyPricingRule');
this.$emit('toggleModal', 'CouponCode'); this.$emit('toggleModal', 'CouponCode');
this.couponCode = ''; this.couponCode = '';
this.validationError = false; this.validationError = false;
this.$emit('setCouponsCount', this.sinvDoc.coupons?.length);
} catch (error) { } catch (error) {
this.validationError = true; this.validationError = true;
@ -198,12 +197,16 @@ export default defineComponent({
} }
}, },
async removeAppliedCoupon(coupon: AppliedCouponCodes) { async removeAppliedCoupon(coupon: AppliedCouponCodes) {
this.sinvDoc.coupons = this.sinvDoc.coupons?.filter( this.sinvDoc?.items?.map((item: InvoiceItem) => {
(coup) => coup.coupons !== coupon?.coupons item.itemDiscountAmount = this.fyo.pesa(0);
); item.itemDiscountPercent = 0;
item.setItemDiscountAmount = false;
});
await updatePricingRule(this.sinvDoc); await coupon?.parentdoc?.remove('coupons', coupon.idx as number);
this.$emit('setCouponsCount', this.sinvDoc.coupons?.length);
this.$emit('applyPricingRule');
this.$emit('setCouponsCount', this.coupons?.length);
}, },
cancelApplyCouponCode() { cancelApplyCouponCode() {
this.couponCode = ''; this.couponCode = '';

View File

@ -316,7 +316,6 @@ import { defineComponent, inject } from 'vue';
import Button from 'src/components/Button.vue'; import Button from 'src/components/Button.vue';
import Float from 'src/components/Controls/Float.vue'; import Float from 'src/components/Controls/Float.vue';
import Currency from 'src/components/Controls/Currency.vue'; import Currency from 'src/components/Controls/Currency.vue';
import { updatePricingRuleItem } from 'models/helpers';
import { SalesInvoice } from 'models/baseModels/SalesInvoice/SalesInvoice'; import { SalesInvoice } from 'models/baseModels/SalesInvoice/SalesInvoice';
import { SalesInvoiceItem } from 'models/baseModels/SalesInvoiceItem/SalesInvoiceItem'; import { SalesInvoiceItem } from 'models/baseModels/SalesInvoiceItem/SalesInvoiceItem';
import { ValidationError } from 'fyo/utils/errors'; import { ValidationError } from 'fyo/utils/errors';
@ -338,7 +337,7 @@ export default defineComponent({
default: '', default: '',
}, },
}, },
emits: ['toggleModal'], emits: ['toggleModal', 'applyPricingRule'],
setup() { setup() {
return { return {
sinvDoc: inject('sinvDoc') as SalesInvoice, sinvDoc: inject('sinvDoc') as SalesInvoice,
@ -460,7 +459,7 @@ export default defineComponent({
} }
if (this.selectedItemField === 'quantity') { if (this.selectedItemField === 'quantity') {
await updatePricingRuleItem(this.sinvDoc); this.$emit('applyPricingRule');
} }
} }
@ -471,6 +470,10 @@ export default defineComponent({
type: 'error', type: 'error',
message: this.t`${error as string}`, message: this.t`${error as string}`,
}); });
if (this.selectedItemField === 'quantity') {
this.$emit('applyPricingRule');
}
} }
}, },
async deleteLast() { async deleteLast() {

View File

@ -30,6 +30,7 @@
<CouponCodeModal <CouponCodeModal
:open-modal="openCouponCodeModal" :open-modal="openCouponCodeModal"
@apply-pricing-rule="emitEvent('applyPricingRule')"
@toggle-modal="emitEvent('toggleModal', 'CouponCode')" @toggle-modal="emitEvent('toggleModal', 'CouponCode')"
@set-coupons-count="(count) => emitEvent('setCouponsCount', count)" @set-coupons-count="(count) => emitEvent('setCouponsCount', count)"
/> />
@ -44,7 +45,6 @@
@toggle-modal="emitEvent('toggleModal', 'Payment')" @toggle-modal="emitEvent('toggleModal', 'Payment')"
@set-cash-amount="(amount) => emitEvent('setCashAmount', amount)" @set-cash-amount="(amount) => emitEvent('setCashAmount', amount)"
@set-transfer-ref-no="(ref) => emitEvent('setTransferRefNo', ref)" @set-transfer-ref-no="(ref) => emitEvent('setTransferRefNo', ref)"
@set-coupons-count="(count) => emitEvent('setCouponsCount', count)"
@set-transfer-amount="(amount) => emitEvent('setTransferAmount', amount)" @set-transfer-amount="(amount) => emitEvent('setTransferAmount', amount)"
@set-transfer-clearance-date=" @set-transfer-clearance-date="
(date) => emitEvent('setTransferClearanceDate', date) (date) => emitEvent('setTransferClearanceDate', date)
@ -66,6 +66,7 @@
:selected-item-field="selectedItemField" :selected-item-field="selectedItemField"
:selected-item-row="(selectedItemRow as SalesInvoiceItem)" :selected-item-row="(selectedItemRow as SalesInvoiceItem)"
@toggle-modal="emitEvent('toggleModal', 'Keyboard')" @toggle-modal="emitEvent('toggleModal', 'Keyboard')"
@apply-pricing-rule="emitEvent('applyPricingRule')"
/> />
<div class="bg-gray-25 dark:bg-gray-875 grid grid-cols-9 gap-3 p-4"> <div class="bg-gray-25 dark:bg-gray-875 grid grid-cols-9 gap-3 p-4">
@ -96,6 +97,7 @@
<ModernPOSSelectedItemTable <ModernPOSSelectedItemTable
@selected-row="selectedRow" @selected-row="selectedRow"
@apply-pricing-rule="emitEvent('applyPricingRule')"
@toggle-modal="emitEvent('toggleModal', 'Keyboard')" @toggle-modal="emitEvent('toggleModal', 'Keyboard')"
/> />
</div> </div>
@ -405,6 +407,7 @@ export default defineComponent({
'routeToSinvList', 'routeToSinvList',
'setLoyaltyPoints', 'setLoyaltyPoints',
'setTransferRefNo', 'setTransferRefNo',
'applyPricingRule',
'saveInvoiceAction', 'saveInvoiceAction',
'createTransaction', 'createTransaction',
'setTransferAmount', 'setTransferAmount',

View File

@ -44,6 +44,7 @@
@route-to-sinv-list="routeToSinvList" @route-to-sinv-list="routeToSinvList"
@set-loyalty-points="setLoyaltyPoints" @set-loyalty-points="setLoyaltyPoints"
@set-transfer-ref-no="setTransferRefNo" @set-transfer-ref-no="setTransferRefNo"
@apply-pricing-rule="applyPricingRule"
@create-transaction="createTransaction" @create-transaction="createTransaction"
@save-invoice-action="saveInvoiceAction" @save-invoice-action="saveInvoiceAction"
@set-transfer-amount="setTransferAmount" @set-transfer-amount="setTransferAmount"
@ -83,6 +84,7 @@
@set-cash-amount="setCashAmount" @set-cash-amount="setCashAmount"
@set-coupons-count="setCouponsCount" @set-coupons-count="setCouponsCount"
@route-to-sinv-list="routeToSinvList" @route-to-sinv-list="routeToSinvList"
@apply-pricing-rule="applyPricingRule"
@set-loyalty-points="setLoyaltyPoints" @set-loyalty-points="setLoyaltyPoints"
@set-transfer-ref-no="setTransferRefNo" @set-transfer-ref-no="setTransferRefNo"
@create-transaction="createTransaction" @create-transaction="createTransaction"
@ -219,6 +221,10 @@ export default defineComponent({
watch: { watch: {
sinvDoc: { sinvDoc: {
handler() { handler() {
if (this.sinvDoc.coupons?.length) {
this.setCouponsCount(this.sinvDoc.coupons?.length);
}
this.updateValues(); this.updateValues();
}, },
deep: true, deep: true,
@ -635,26 +641,12 @@ export default defineComponent({
this.sinvDoc.isPricingRuleApplied = false; this.sinvDoc.isPricingRuleApplied = false;
removeFreeItems(this.sinvDoc as SalesInvoice); removeFreeItems(this.sinvDoc as SalesInvoice);
await this.sinvDoc.applyProductDiscount();
return; return;
} }
const appliedPricingRuleCount = this.sinvDoc?.items?.filter( await this.sinvDoc.appendPricingRuleDetail(hasPricingRules);
(val) => val.isFreeItem await this.sinvDoc.applyProductDiscount();
).length;
const recursivePricingRules = hasPricingRules?.filter(
(val) => val.pricingRule.isRecursive
);
setTimeout(async () => {
if (
appliedPricingRuleCount !== hasPricingRules?.length ||
recursivePricingRules
) {
await this.sinvDoc.appendPricingRuleDetail(hasPricingRules);
await this.sinvDoc.applyProductDiscount();
}
}, 1);
}, },
async routeToSinvList() { async routeToSinvList() {
if (!this.sinvDoc.items?.length) { if (!this.sinvDoc.items?.length) {

View File

@ -224,7 +224,6 @@ export default defineComponent({
'setTransferClearanceDate', 'setTransferClearanceDate',
'setTransferRefNo', 'setTransferRefNo',
'toggleModal', 'toggleModal',
'setCouponsCount',
], ],
setup() { setup() {
return { return {
@ -323,7 +322,6 @@ export default defineComponent({
}, },
submitTransaction() { submitTransaction() {
this.$emit('createTransaction'); this.$emit('createTransaction');
this.$emit('setCouponsCount', 0);
}, },
}, },
}); });