Customers
Customers are the people who create orders. A customer object must have an email and channel. All necessary information about customers is kept in customer objects. This includes information about communication permissions accepted by customers for example: email_allowed, sms_allowed etc.
Customer Creation
In order to create a customer record on the Omnitron product, any order from the marketplace must be fetched to Omnitron. When the relevant command runs in marketplace integrations, the order is created in Omnitron. At this stage, if the customer record has not been created before, customer information is created; if the customer record has been created before, the customer information is updated (works with the Upsert logic). Service methods are used in these creation and update processes.
In the integration document, the creation of the order and, accordingly, the creation of the customer will be discussed.
Model
The Customers model has been defined under omnitron.customers.models.Customers. This model is inherited from models StarterModel and Entity. Channel information is kept as Foreign Key to distinguish customers by the marketplace. It is determined by user_type whether a customer is a registered user or not. The omnicore.users.enums.UserType in the Omnicore project may be inspected.
Figure 1: Customer Model
Figure 2: Customer Model Methods and Inheritance
Serializer
Multiple serializers can be used. These are:
- CustomerSerializer
- CustomerDetailedSerializer
CustomerSerializer
Defined as CustomerSerializer under omnitron.customers.resources.serializers.CustomerSerializer
. Allows to serialize/deserialize the following parameters:
- pk
- channel : Allows us to understand from which marketplace the customer comes from.
- first_name
- last_name
- phone_number
- is_active : Determines whether the customer is active. This variable takes the value False for an anonymized customer
- channel_code : Customer’s marketplace-specific code
- erp_code
- extra_field
- modified_date
- created_date
- date_joined
- email_allowed
- sms_allowed
- call_allowed
- gender
- attributes: The field where we store various customer attributes. May contain fields such as:
- logged_ip
- register_client_type
- verified_user
- user_status_description
- anonimizing_user_id
- anonimization_time
- confirm
- has_loyalty
- sso_id
- user_type : Determines the customer type. There are two types of customers; registered customers and guest customers.
- date_of_birth
- attributes_kwargs
- localized_attributes
CustomerDetailedSerializer
Defined as CustomerDetailedSerializer under omnitron.customers.resources.serializers.CustomerDetailedSerializer
. Unlike CustomerSerializer, the channel information is provided openly. In addition, the total order amount, total refund amount, total discount amount and total order count are provided as orders_info information.
Additional fields:
- channel : Serialized
- orders_info:
- total_order_amount : Total order amount of the customer
- total_refund_amount : Total refund amount made to the customer
- total_discount_amount : Total discount amount made to the customer
- total_order_count : Total order count of the customer
Service
Customer service is defined as CustomerService under omnitron.customers.service.CustomerService
. It is responsible for creating and updating the Customer object. The public methods and functions of the class are as follows:
create_customer Method
Received parameters
- channel : Marketplace object registered in the system
- channel_code : Customer’s marketplace-specific code
- kwargs : Other parameters in the Customer model go here. Parameters can be checked under the Serializer heading.
Function
It is responsible for creating the customer object and saving it to the database. In case a customer with the same channel and channel_code
has been registered, this will throw CustomerDuplicatedFieldException
error.
update_customer Method
Received parameters
- customer : Customer to be updated
- audit_context
- It ensures that an audit trail is kept for the update process.
- If the method is called over ViewSet, the audit_context object on the request is used. Otherwise, the AuditContext object is created when the method is called.
- kwargs : Other parameters in the Customer model go here. Parameters can be checked under the Serializer heading.
Function
It is responsible for making the necessary updates on the Customer object and creating the audit trail related to these updates.
Figure 3: CustomerService Structure
ViewSet
CustomerViewSet {omnitron.payments.resources.views.CustomerViewSet}
is located in the endpoint /api/v1/customers/
.
Allows GET, POST, PUT, PATCH and DELETE methods inherited from ModelViewSet. perform_create(), perform_update() and get_queryset() functions are overridden; perform create/update operations on the relevant CustomerService.
Endpoint | omnitron.customers.resources.views.CustomerViewSet |
/api/v1/customers | omnitron_api:customer-list |
/api/v1/customers/detailed/ | omnitron_api:customer-detailed |
/api/v1/customers/{pk}/ | omnitron_api:customer-detail |
/api/v1/customers/{pk}/detailed | omnitron_api:customer-detailed |
Figure 4: CustomerViewSet Structure
Allowed HTTPs Requests
- GET
- POST
- PATCH
- PUT
Potential Responses
- 201 Created
- 400 Bad Request
- 404 Not Found
- 405 Method Not Allowed
- 406 Not Acceptable
GET
Customers
Returns all objects in the Customers table paged.
Path: /api/v1/customers/
Filters
The available filters are as follows.
"filters": {
"created_date": {
"type": "DateFilter",
"lookup_types": [
"exact",
"gt",
"gte",
"lt",
"lte",
"date"
]
},
"modified_date": {
"type": "DateFilter",
"lookup_types": [
"exact",
"gt",
"gte",
"lt",
"lte",
"date"
]
},
"attributes": {
"type": "JsonMethodFilter",
"lookup_types": [
"exact"
]
},
"channel": {
"type": "ModelMultipleChoiceFilter",
"lookup_types": [
"exact"
]
},
"email": {
"type": "CharFilter",
"lookup_types": [
"exact",
"startswith"
]
},
"first_name": {
"type": "CharFilterWithNull",
"lookup_types": [
"exact"
]
},
"last_name": {
"type": "CharFilterWithNull",
"lookup_types": [
"exact"
]
},
"phone_number": {
"type": "CharFilterWithNull",
"lookup_types": [
"exact"
]
},
"is_active": {
"type": "BooleanFilter",
"lookup_types": [
"exact"
]
},
"channel_code": {
"type": "CharFilterWithNull",
"lookup_types": [
"exact"
]
},
"erp_code": {
"type": "CharFilterWithNull",
"lookup_types": [
"exact"
]
},
"extra_field": {
"type": "JsonMethodFilter",
"lookup_types": [
"exact"
]
},
"email_allowed": {
"type": "BooleanFilter",
"lookup_types": [
"exact"
]
},
"sms_allowed": {
"type": "BooleanFilter",
"lookup_types": [
"exact"
]
},
"call_allowed": {
"type": "BooleanFilter",
"lookup_types": [
"exact"
]
},
"date_joined": {
"type": "IsoDateTimeFilter",
"lookup_types": [
"exact"
]
},
"gender": {
"type": "ChoiceFilter",
"lookup_types": [
"exact"
]
},
"user_type": {
"type": "ChoiceFilter",
"lookup_types": [
"exact"
]
},
"date_of_birth": {
"type": "DateFilter",
"lookup_types": [
"exact"
]
},
"id": {
"type": "NumberFilter",
"lookup_types": [
"exact",
"gt",
"gte",
"lt",
"lte"
]
},
"pk": {
"type": "NumberFilter",
"lookup_types": [
"exact",
"gt",
"gte",
"lt",
"lte"
]
},
"mapping": {
"type": "RelatedFilter",
"lookup_types": "See available filters for Integration Mappings"
}
}
Request
import requests
url = "{omnitron}/api/v1/customers/"
payload={}
headers = {
...
}
response = requests.request("GET", url, headers=headers, data=payload)
Response
{
"count": 2,
"next": "http://{customer_omnitron_url}/api/v1/customers/?page=2",
"previous": null,
"results": [
{
"pk": 1103,
"channel": 1,
"email": "test@test.com",
"first_name": "TEST",
"last_name": "denemeler",
"phone_number": null,
"is_active": true,
"channel_code": "7",
"erp_code": "760906",
"extra_field": {},
"modified_date": "2022-12-08T10:49:45.794533Z",
"created_date": "2017-02-02T09:40:28.855012Z",
"date_joined": "2017-01-30T08:21:20.657225Z",
"email_allowed": false,
"sms_allowed": true,
"call_allowed": true,
"gender": null,
"attributes": {},
"user_type": null,
"date_of_birth": null,
"attributes_kwargs": {},
"localized_attributes": {},
"localized_attributes_kwargs": {}
},
{
"pk": 1134,
"channel": 1,
"email": "test@test.com",
"first_name": "",
"last_name": "",
"phone_number": null,
"is_active": false,
"channel_code": "Shop",
"erp_code": null,
"extra_field": {},
"modified_date": "2023-01-17T09:01:27.544053Z",
"created_date": "2023-01-17T09:01:27.544026Z",
"date_joined": null,
"email_allowed": false,
"sms_allowed": false,
"call_allowed": false,
"gender": null,
"attributes": {
"logged_ip": "127.0.0.1"
},
"user_type": null,
"date_of_birth": null,
"attributes_kwargs": {},
"localized_attributes": {},
"localized_attributes_kwargs": {}
"user_type": "registered"
},
]
}
POST
Create a Customer
Records new objects in the Customer table. The CustomerSerializer class defined at omnitron.customers.resources.serializers
is used to validate the data.
Path: /api/v1/customers/
Body
{
"email": "test@test.com",
"channel": 1,
"channel_code": "1231",
"gender": "male",
"user_type": "registered",
"is_active": false,
"erp_code": "er_code",
"email_allowed": true,
"sms_allowed": true,
"call_allowed": true,
"phone_number": "05555555555",
"attributes": {},
"extra_field": {},
"date_of_birth": "2001-01-01"
}
Response
{
"pk": 1117,
"channel": 1,
"email": "test@test.com",
"first_name": "",
"last_name": "",
"phone_number": "05555555555",
"is_active": false,
"channel_code": "1231",
"erp_code": "er_code",
"extra_field": {},
"modified_date": "2021-05-26T13:53:58.585932Z",
"created_date": "2021-05-26T13:53:58.585910Z",
"date_joined": null,
"email_allowed": true,
"sms_allowed": true,
"call_allowed": true,
"gender": "male",
"attributes": {},
"user_type": "registered",
"date_of_birth": "2001-01-01",
"attributes_kwargs": {},
"localized_attributes": {},
"localized_attributes_kwargs": {}
}
Response HTTP 400
{
"non_field_errors": [
"The fields channel, channel_code must make a unique set."
]
}
-- OR
{
"email": [
"This field is required."
],
"channel": [
"This field is required."
],
"channel_code": [
"This field is required."
]
}
-- OR
{
"email": [
"Enter a valid email address."
]
}
GET
Customer Detail
Returns the object specified with the primary key in the Customers table by serializing it with the CustomerSerializer class defined at omnitron.customers.resources.serializers
.
Path: /api/v1/customers/{pk}/
Request
url = "{customer_omnitron_url}/api/v1/customers/1135/"
payload={}
headers = {
'Authorization':...'
}
response = requests.request("GET", url, headers=headers, data=payload)
Successful Response
{
"pk": 1117,
"channel": 1,
"email": "test@test.com",
"first_name": "",
"last_name": "",
"phone_number": "05555555555",
"is_active": false,
"channel_code": "1231",
"erp_code": "er_code",
"extra_field": {},
"modified_date": "2021-05-26T13:53:58.585932Z",
"created_date": "2021-05-26T13:53:58.585910Z",
"date_joined": null,
"email_allowed": true,
"sms_allowed": true,
"call_allowed": true,
"gender": "male",
"attributes": {},
"user_type": "registered",
"date_of_birth": "2001-01-01",
"attributes_kwargs": {},
"localized_attributes": {},
"localized_attributes_kwargs": {}
}
Failed Response
{
"detail": "Not found."
}
PATCH
Update Customer
Updates the object of the relevant primary key in the Customer table with the provided parameters.
Path: /api/v1/customers/{pk}/
{
"is_active": true,
"email_allowed": false,
"sms_allowed": false,
"user_type": "registered"
}
Response
{
"pk": 1117,
"channel": 1,
"email": "test@test.com",
"first_name": "",
"last_name": "",
"phone_number": "05555555555",
"is_active": true,
"channel_code": "1231",
"erp_code": "er_code",
"extra_field": {},
"modified_date": "2021-05-26T14:24:11.776744Z",
"created_date": "2021-05-26T13:53:58.585910Z",
"date_joined": null,
"email_allowed": false,
"sms_allowed": false,
"call_allowed": true,
"gender": "female",
"attributes": {},
"user_type": "registered",
"date_of_birth": "2001-01-01",
"attributes_kwargs": {},
"localized_attributes": {},
"localized_attributes_kwargs": {}
}
HTTP 406
{
"non_field_errors": "channel:channel_name These field cannot be updated",
"error_code": "customer_100_3"
}
PUT
Update Customer
Allows to change the information of the relevant primary key in the Customer table. Mandatory parameters must be sent.
Path: /api/v1/customers/{pk}/
{
"email": "test2@test.com",
"channel": 1,
"channel_code": "1231",
"is_active": true,
"email_allowed": false,
"sms_allowed": false,
"user_type": "registered",
"extra_field": {}
}
Successful Response
{
"pk": 1117,
"channel": 1,
"email": "test2@test.com",
"first_name": "",
"last_name": "",
"phone_number": "05555555555",
"is_active": true,
"channel_code": "1231",
"erp_code": "er_code",
"extra_field": {},
"modified_date": "2021-05-26T14:26:52.809180Z",
"created_date": "2021-05-26T13:53:58.585910Z",
"date_joined": null,
"email_allowed": false,
"sms_allowed": false,
"call_allowed": true,
"gender": "female",
"attributes": {},
"user_type": "registered",
"date_of_birth": "2001-01-01",
"attributes_kwargs": {},
"localized_attributes": {},
"localized_attributes_kwargs": {}
}
Failed Response
If we remove the email data from the body example, the following response will be returned.
HTTP 400
{
"extra_field": [
"This field is required."
],
"channel": [
"This field is required."
],
"channel_code": [
"This field is required."
]
}
Note: When we change the channel information and send a PUT or PATCH request in the body example, the following response will be returned.
HTTP 406
{
"non_field_errors": "channel:channel_name These field cannot be updated",
"error_code": "customer_100_3"
}