PN-27: Add brands filter to POS items#180
Conversation
MohamedAliSmk
commented
Mar 9, 2026
- Add POS Brands Detail child table doctype for POS Profile
- Add custom_brands_table custom field to POS Profile via fixtures
- Add get_brands API and brand parameter to get_items/get_items_count
- Add brand-aware filter handling in itemSearch store
- Update ItemsSelector UI with dynamic brand/item_group tab switching
- Add brand sort option with context-aware sort menu
- Add POS Brands Detail child table doctype for POS Profile - Add custom_brands_table custom field to POS Profile via fixtures - Add get_brands API and brand parameter to get_items/get_items_count - Add brand-aware filter handling in itemSearch store - Update ItemsSelector UI with dynamic brand/item_group tab switching - Add brand sort option with context-aware sort menu
Deep Code Review — PR #180Files changed: 8 | +401 / -32 Critical Issues1. Missing custom field fixture for
2. In pos_profile.append("brands", {"brand": brand_name})But the custom field on POS Profile is named 3. In conditions.append(f"IFNULL(i.brand, '') IN ({placeholders})")
where_params.extend(allowed_brands)This uses Actually, re-reading: this is correct in intent (only show items matching configured brands), but the Logic Concerns4. The bulk fetch function (used for offline background sync) calls 5. Brand filter and item_group filter are mutually exclusive in the frontend but not in the backend The backend 6. if not configured_brands:
result = (
frappe.qb.from_(Brand)
.select(Brand.name.as_("brand"))
.orderby(Brand.name)
.limit(50)
.run(as_dict=True)
)When no brands are configured in the POS Profile, it falls back to returning the first 50 brands from the system. This is inconsistent with how item groups work (which only show configured groups). It also means the allowed-brands filter in 7. cache_key = f"pos_brands:{pos_profile}"
frappe.cache().set_value(cache_key, result, expires_in_sec=300)5-minute TTL, but no cache invalidation when the POS Profile brands are updated via 8. Sort switching triggers data reload but doesn't cancel in-flight requests watch(sortBy, async (newSortBy, oldSortBy) => {
if (newSortBy === 'brand') {
await itemStore.loadBrands()
if (selectedItemGroup.value) {
await itemStore.setSelectedItemGroup(null)
}
}
})Rapidly toggling sort options can stack multiple async operations. No cancellation token or generation counter (unlike other parts of the store that use Performance9. allowed_brands = _get_allowed_profile_brands(pos_profile_doc.name)This executes a DB query ( 10. Offline brand filtering fetches 5000 items then filters in JS const cached = await offlineWorker.searchCachedItems("", 5000, 0)
const filtered = brand
? (cached || []).filter(item => (item.brand || '') === brand)
: (cached || [])Fetches up to 5000 items from IndexedDB just to filter by brand. Should use an IndexedDB index on Code Quality11. Indentation error in brand: undefined,
start: currentOffset.value,The 12. Several places pass brand: undefined,In Frappe's 13. The 14. Both functions query Risk Assessment
VerdictNot ready to merge. The two critical issues (#1 missing fixture, #2 wrong fieldname) mean the entire brands feature is non-functional for POS Profile CRUD. The |
|
no 4: |
- Update brand condition in items API to remove IFNULL check - Change field name from 'brands' to 'custom_brands_table' in POS Profile creation and update methods - Add custom field 'custom_brands_table' to POS Profile via fixtures for better brand management
- Update docstring to clarify filtering behavior for item_group and brand. - Implement validation to enforce mutual exclusivity between item_group and brand filters, raising an error if both are provided in a request.
- Remove unused Brand DocType declaration. - Update logic to return an empty list when no brands are configured in the POS Profile, ensuring consistent behavior with item filtering. - Simplify result assignment for configured brands.
- Add logic to invalidate cached POS filters after updating the POS Profile to ensure immediate reflection of changes in the POS UI. - Log errors during cache invalidation to prevent blocking the update process.
- Modify logic to return all active brands as filter options when no brands are configured in the POS Profile, ensuring the item query remains unrestricted. - Enhance clarity in comments regarding brand filtering behavior.
- Remove unused brand references in item search store state. - Introduce a new method for searching cached items by brand in the offline worker, utilizing a brand index for efficient lookups. - Update the database schema to include a brand index for improved offline search performance. - Modify the API to support brand-based filtering in item queries, ensuring consistent behavior across the application.