refactor: improve loyalty program filtering and optimize partner list search performance in POS
This commit is contained in:
parent
f7a8e1451d
commit
b8218d83a9
@ -63,7 +63,7 @@ class ResPartner(models.Model):
|
|||||||
|
|
||||||
# Find the lowest membership program level (Membership Silver)
|
# Find the lowest membership program level (Membership Silver)
|
||||||
lowest_program = self.env['loyalty.program'].sudo().search(
|
lowest_program = self.env['loyalty.program'].sudo().search(
|
||||||
[('multi_level_membership', '=', True), ('name', '=ilike', 'Membership Silver')],
|
[('multi_level_membership', '=', True), ('manual_membership', '=', False), ('name', '=ilike', 'Membership Silver')],
|
||||||
limit=1
|
limit=1
|
||||||
)
|
)
|
||||||
if not lowest_program:
|
if not lowest_program:
|
||||||
|
|||||||
@ -2,11 +2,55 @@
|
|||||||
|
|
||||||
import { PartnerList } from "@point_of_sale/app/screens/partner_list/partner_list";
|
import { PartnerList } from "@point_of_sale/app/screens/partner_list/partner_list";
|
||||||
import { patch } from "@web/core/utils/patch";
|
import { patch } from "@web/core/utils/patch";
|
||||||
|
import { normalize } from "@web/core/l10n/utils";
|
||||||
|
|
||||||
patch(PartnerList.prototype, {
|
patch(PartnerList.prototype, {
|
||||||
getPartners(partners) {
|
getPartners(partners) {
|
||||||
// Filter the partner list to strictly only display partners who are loyalty members
|
// Filter the partner list to strictly only display partners who are loyalty members
|
||||||
const filteredPartners = partners.filter((p) => p.is_loyalty_member);
|
const filteredPartners = partners.filter((p) => p.is_loyalty_member);
|
||||||
return super.getPartners(filteredPartners);
|
|
||||||
|
const searchWord = normalize(this.state.query?.trim() ?? "");
|
||||||
|
if (!searchWord) {
|
||||||
|
// When query is empty, slice and sort following standard POS behavior
|
||||||
|
return filteredPartners
|
||||||
|
.slice(0, 1000)
|
||||||
|
.toSorted((a, b) =>
|
||||||
|
this.props.partner?.id === a.id
|
||||||
|
? -1
|
||||||
|
: this.props.partner?.id === b.id
|
||||||
|
? 1
|
||||||
|
: (a.name || "").localeCompare(b.name || "")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// When query is present, optimize search filtering
|
||||||
|
const exactMatches = filteredPartners.filter((partner) => partner.exactMatch(searchWord));
|
||||||
|
if (exactMatches.length > 0) {
|
||||||
|
return exactMatches;
|
||||||
|
}
|
||||||
|
|
||||||
|
const numberString = searchWord.replace(/[+\s()-]/g, "");
|
||||||
|
const isSearchWordNumber = /^[0-9]+$/.test(numberString);
|
||||||
|
const patternBase = isSearchWordNumber ? numberString : searchWord;
|
||||||
|
const regex = new RegExp(
|
||||||
|
patternBase
|
||||||
|
.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
|
||||||
|
.replace(/%/g, ".*")
|
||||||
|
);
|
||||||
|
|
||||||
|
// Pre-normalize and cache p.searchString, then filter and limit to 200 items to avoid rendering lag
|
||||||
|
const matches = [];
|
||||||
|
for (const p of filteredPartners) {
|
||||||
|
if (!p._normalizedSearchString) {
|
||||||
|
p._normalizedSearchString = normalize(p.searchString || "");
|
||||||
|
}
|
||||||
|
if (regex.test(p._normalizedSearchString)) {
|
||||||
|
matches.push(p);
|
||||||
|
if (matches.length >= 200) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matches;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user