2025-11-17 17:36:51 +01:00
|
|
|
import { ICustomer } from '../../types/CustomerTypes';
|
2025-11-18 16:37:33 +01:00
|
|
|
import { EntityType } from '../../types/CalendarTypes';
|
2025-11-17 17:36:51 +01:00
|
|
|
import { CustomerStore } from './CustomerStore';
|
2025-11-18 16:37:33 +01:00
|
|
|
import { BaseEntityService } from '../BaseEntityService';
|
2025-11-17 17:36:51 +01:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* CustomerService - CRUD operations for customers in IndexedDB
|
|
|
|
|
*
|
2025-11-18 16:37:33 +01:00
|
|
|
* ARCHITECTURE:
|
|
|
|
|
* - Extends BaseEntityService for shared CRUD and sync logic
|
|
|
|
|
* - No serialization needed (ICustomer has no Date fields)
|
|
|
|
|
* - Provides customer-specific query methods (by phone, search by name)
|
2025-11-17 17:36:51 +01:00
|
|
|
*
|
2025-11-18 16:37:33 +01:00
|
|
|
* INHERITED METHODS (from BaseEntityService):
|
|
|
|
|
* - get(id), getAll(), save(entity), delete(id)
|
|
|
|
|
* - markAsSynced(id), markAsError(id), getSyncStatus(id), getBySyncStatus(status)
|
|
|
|
|
*
|
|
|
|
|
* CUSTOMER-SPECIFIC METHODS:
|
|
|
|
|
* - getByPhone(phone)
|
|
|
|
|
* - searchByName(searchTerm)
|
2025-11-17 17:36:51 +01:00
|
|
|
*/
|
2025-11-18 16:37:33 +01:00
|
|
|
export class CustomerService extends BaseEntityService<ICustomer> {
|
|
|
|
|
readonly storeName = CustomerStore.STORE_NAME;
|
|
|
|
|
readonly entityType: EntityType = 'Customer';
|
2025-11-17 17:36:51 +01:00
|
|
|
|
2025-11-18 16:37:33 +01:00
|
|
|
// No serialization override needed - ICustomer has no Date fields
|
2025-11-17 17:36:51 +01:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get customers by phone number
|
|
|
|
|
*
|
|
|
|
|
* @param phone - Phone number
|
|
|
|
|
* @returns Array of customers with this phone
|
|
|
|
|
*/
|
|
|
|
|
async getByPhone(phone: string): Promise<ICustomer[]> {
|
|
|
|
|
return new Promise((resolve, reject) => {
|
2025-11-18 16:37:33 +01:00
|
|
|
const transaction = this.db.transaction([this.storeName], 'readonly');
|
|
|
|
|
const store = transaction.objectStore(this.storeName);
|
2025-11-17 17:36:51 +01:00
|
|
|
const index = store.index('phone');
|
|
|
|
|
const request = index.getAll(phone);
|
|
|
|
|
|
|
|
|
|
request.onsuccess = () => {
|
|
|
|
|
resolve(request.result as ICustomer[]);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
request.onerror = () => {
|
|
|
|
|
reject(new Error(`Failed to get customers by phone ${phone}: ${request.error}`));
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Search customers by name (partial match)
|
|
|
|
|
*
|
|
|
|
|
* @param searchTerm - Search term (case insensitive)
|
|
|
|
|
* @returns Array of customers matching search
|
|
|
|
|
*/
|
|
|
|
|
async searchByName(searchTerm: string): Promise<ICustomer[]> {
|
|
|
|
|
const allCustomers = await this.getAll();
|
|
|
|
|
const lowerSearch = searchTerm.toLowerCase();
|
|
|
|
|
|
|
|
|
|
return allCustomers.filter(customer =>
|
|
|
|
|
customer.name.toLowerCase().includes(lowerSearch)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|