Customers Management Deep Dive
Overview
This comprehensive guide covers Customer Management in the Ink platform, including customer lifecycle, profile management, address handling, and integration with external systems like QuickBooks and Salesforce.
Target Audience: Backend developers working with customer data Prerequisites: Service Layer Architecture, Integration Patterns Estimated Time: 45-60 minutes
Prerequisites
- Understanding of CRM concepts
- Knowledge of JPA and Spring Data
- Familiarity with Integration Patterns
- Completed Service Layer Architecture
Customers Lifecycle Architecture
Installation Steps
The Installation Steps section establishes the customers service management capabilities, including the core service, database schema, and external integrations.
What You'll Set Up:
- Customers Dependencies - Core libraries for customer management
- Customers Configuration - Settings for validation and external sync
Why This Matters:
- Centralizes customer data management
- Ensures data consistency across the platform
- Manages integration with billing and CRM systems
- Enforces business rules for customer accounts
When to Use:
- Initial platform setup
- Adding new customer-facing features
- Integrating with new external systems
- Implementing customer data policies
Key Capabilities Enabled:
- Profile Management: Create and update customer details
- Address Management: Handle billing and shipping addresses
- External Sync: Synchronize with QuickBooks and Salesforce
- Lifecycle Tracking: Monitor customer status and history
- Settings Management: Configure per-customer preferences
Configuration Hierarchy:
customer
├── validation
│ ├── requireEmail: true
│ └── requirePhone: false
├── sync
│ ├── quickbooks: true
│ └── salesforce: true
└── lifecycle
├── inactiveDays: 90
└── churnThreshold: 180
1. Customer Dependencies
What Are Customer Dependencies?
The customer module relies on core Spring Boot starters, database drivers, and common internal libraries.
Why Are They Needed?
- Persistence: JPA/Hibernate for data storage
- Web: REST API exposure
- Validation: Bean validation for data integrity
- Internal: Common DTOs and utilities
How/When Are They Used?
- Build Time: Compiled into the
sureink-customerservice - Runtime: Loaded by the Spring container
Dependency Relationships
Code Example (XML)
<!-- filepath: /sureink-customer/pom.xml -->
<dependencies>
<dependency>
<groupId>com.sureink</groupId>
<artifactId>sureink-model</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.sureink</groupId>
<artifactId>sureink-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>
2. Customer Configuration
What Is Customer Configuration?
Configuration settings control the behavior of the customer service, including validation rules and integration toggles.
Why Is It Needed?
- Feature Flags: Enable/disable integrations
- Tuning: Adjust performance and limits
- Policy: Enforce business rules via config
How/When Is It Used?
- Startup: Loaded during application bootstrap
- Runtime: Injected into services via
@Value
Configuration Flow
Code Example (YAML)
# filepath: /sureink-customer/src/main/resources/application.yml
customer:
code:
prefix: CUST
length: 8
sync:
quickbooks:
enabled: true
auto-create: true
salesforce:
enabled: true
validation:
email-domain-blocklist:
- mailinator.com
- tempmail.com
Configuration Section
Main Entity: Customers
What Is the Customers Entity?
The Customer entity is the root aggregate for all customer-related data. It stores core profile information, status, and links to related entities.
Why Is It Needed?
- Identity: Unique identification of customers
- State: Tracks lifecycle status (Lead, Active, etc.)
- Audit: Supports history via Envers
How/When Is It Used?
- CRUD Operations: Created on signup, updated via profile
- References: Linked to Orders, Subscriptions, and Projects
Entity Relationships
Code Example (Java)
// filepath: /sureink-model/src/main/java/com/sureink/customer/model/Customer.java
@Entity
@Table(schema = "customer")
@NoArgsConstructor(access = AccessLevel.PUBLIC)
@Getter
@Setter
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CUSTOMER_SEQUENCE")
@SequenceGenerator(name = "CUSTOMER_SEQUENCE", sequenceName = "customer_sequence", schema = "customer", allocationSize = 25)
Long id;
@Column(name = "name")
String name;
@Column(name = "code")
String code;
@Column(name = "full_name")
String fullName;
@Column(name = "created")
LocalDate created;
@Enumerated(EnumType.STRING)
@Column(name = "type")
CustomerLicenseType type;
@Enumerated(EnumType.STRING)
@Column(name = "source")
CustomerSource source;
@Column(name = "quickbooks_id")
String quickbooksId;
// ... relationships and other fields
}
Service Implementation: CustomerService
What Is the Customer Service?
The CustomerService encapsulates the business logic for managing customers. It handles validation, persistence, and event publication.
Why Is It Needed?
- Abstraction: Hides data access details
- Consistency: Enforces rules before saving
- Events: Triggers side effects (e.g., sync) via events
How/When Is It Used?
- API Calls: Invoked by the Controller layer
- Internal: Used by other services (e.g., OrderService)
Service Operation Flow
Code Example (Java)
// filepath: /sureink-customer/src/main/java/com/sureink/customer/service/CustomerService.java
@Service
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
public class CustomerService extends UserInfoAware {
private final CustomerRepository customerRepository;
private final CustomerChangeEventPublisher customerChangeEventPublisher;
@Transactional
public Customer save(Customer customer) {
Preconditions.checkNotNull(customer, "Cannot save empty customer");
Customer saved = customerRepository.save(customer);
// Event publishing logic would typically go here or in an aspect
return saved;
}
@Transactional
public Optional<Customer> findOne(Long id) {
Preconditions.checkNotNull(id, "Unable to find customer for empty id");
return customerRepository.findById(id);
}
// ... other methods
}
Usage Examples
Creating a New Customer
What Is Customer Creation?
The process of onboarding a new customer into the system.
Code Example (Java)
Customer customer = new Customer();
customer.setName("Acme Corp");
customer.setFullName("Acme Corporation International");
customer.setType(CustomerLicenseType.ENTERPRISE);
customer.setSource(CustomerSource.WEB);
customer.setCreated(LocalDate.now());
Customer saved = customerService.save(customer);
Updating Customer Address
What Is Address Update?
Adding or modifying the billing/shipping address for a customer.
Code Example (Java)
CustomerAddress address = new CustomerAddress();
address.setCustomer(customer);
address.setAddressLine1("123 Tech Blvd");
address.setCity("San Francisco");
address.setState("CA");
address.setZipCode("94105");
address.setType(AddressType.BILLING);
customerService.saveCustomerAddress(address);
Verification
Customer Service Tests
What Are Customer Service Tests?
Unit and integration tests to verify the correctness of customer operations.
Code Example (Java)
@SpringBootTest
class CustomerServiceTest {
@Autowired
private CustomerService customerService;
@Test
void shouldCreateCustomer() {
Customer customer = new Customer();
customer.setName("Test Corp");
Customer saved = customerService.save(customer);
assertNotNull(saved.getId());
assertEquals("Test Corp", saved.getName());
}
}