trex-model 1.2.19__tar.gz → 1.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of trex-model might be problematic. Click here for more details.
- {trex-model-1.2.19 → trex-model-1.3.1}/PKG-INFO +1 -1
- {trex-model-1.2.19 → trex-model-1.3.1}/setup.py +1 -1
- {trex-model-1.2.19 → trex-model-1.3.1}/trex_model.egg-info/PKG-INFO +1 -1
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/conf.py +5 -2
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/loyalty_models.py +50 -1
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/message_model_helper.py +162 -47
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/message_models.py +7 -3
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/prepaid_models.py +158 -2
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/redeem_models.py +15 -5
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/program_conf.py +2 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/LICENSE +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/MANIFEST.in +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/README.md +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/setup.cfg +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trex_model.egg-info/SOURCES.txt +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trex_model.egg-info/dependency_links.txt +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trex_model.egg-info/requires.txt +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trex_model.egg-info/top_level.txt +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/__init__.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/__init__.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/__init__.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/admin_models.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/analytic_models.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/app_models.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/coporate_models.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/customer_model_helpers.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/customer_models.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/fb_subsriber_models.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/import_models.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/inventory_model.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/lucky_draw_models.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/marketing_models.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/membership_models.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/merchant_models.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/model_decorators.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/ndb_models.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/pos_models.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/product_models.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/program_models.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/rating_models.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/redemption_catalogue_models.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/reward_model_helpers.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/reward_models.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/spending_base_program_model.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/system_models.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/task_models.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/test_models.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/transaction_models.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/user_models.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/voucher_models.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/merchant_helpers.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/model_decorator.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/prepaid_helpers.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/pos_conf.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/utils/__init__.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/utils/gcloud/__init__.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/utils/gcloud/datastore_util.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/utils/model/__init__.py +0 -0
- {trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/utils/model/model_util.py +0 -0
|
@@ -7,7 +7,7 @@ MAX_FETCH_RECORD_FULL_TEXT_SEARCH_PER_PAGE = 10
|
|
|
7
7
|
MAX_FETCH_RECORD = 99999999
|
|
8
8
|
MAX_FETCH_IMAGE_RECORD = 100
|
|
9
9
|
MAX_CHAR_RANDOM_UUID4 = 20
|
|
10
|
-
PAGINATION_SIZE =
|
|
10
|
+
PAGINATION_SIZE = 10
|
|
11
11
|
VISIBLE_PAGE_COUNT = 10
|
|
12
12
|
|
|
13
13
|
DEFAULT_GMT_HOURS = 8
|
|
@@ -34,8 +34,9 @@ MESSAGE_CATEGORY_PROMOTION = 'promotion'
|
|
|
34
34
|
MESSAGE_CATEGORY_SURVEY = 'survey'
|
|
35
35
|
MESSAGE_CATEGORY_SYSTEM = 'system'
|
|
36
36
|
MESSAGE_CATEGORY_REWARD = 'reward'
|
|
37
|
+
MESSAGE_CATEGORY_REDEEM = 'redeem'
|
|
37
38
|
|
|
38
|
-
MESSAGE_CATEGORIES = (MESSAGE_CATEGORY_ANNOUNCEMENT, MESSAGE_CATEGORY_ALERT, MESSAGE_CATEGORY_PROMOTION, MESSAGE_CATEGORY_SURVEY, MESSAGE_CATEGORY_SYSTEM, MESSAGE_CATEGORY_REWARD)
|
|
39
|
+
MESSAGE_CATEGORIES = (MESSAGE_CATEGORY_ANNOUNCEMENT, MESSAGE_CATEGORY_ALERT, MESSAGE_CATEGORY_PROMOTION, MESSAGE_CATEGORY_SURVEY, MESSAGE_CATEGORY_SYSTEM, MESSAGE_CATEGORY_REWARD, MESSAGE_CATEGORY_REDEEM)
|
|
39
40
|
|
|
40
41
|
MESSAGE_STATUS_NEW = 'n'
|
|
41
42
|
MESSAGE_STATUS_READ = 'r'
|
|
@@ -50,3 +51,5 @@ USER_STATUS_SET = (USER_STATUS_REGISTERED, USER_STATUS_ENTER_BIODATA, USER_STATU
|
|
|
50
51
|
|
|
51
52
|
MESSAGE_STATUS_SET = (MESSAGE_STATUS_NEW, MESSAGE_STATUS_READ)
|
|
52
53
|
|
|
54
|
+
PREPAID_REDEEM_URL = os.environ['PREPAID_REDEEM_URL']
|
|
55
|
+
|
|
@@ -28,9 +28,19 @@ class LoyaltyDeviceSetting(BaseNModel,DictModel):
|
|
|
28
28
|
created_datetime = ndb.DateTimeProperty(required=True, auto_now_add=True)
|
|
29
29
|
activated_datetime = ndb.DateTimeProperty(required=False)
|
|
30
30
|
testing = ndb.BooleanProperty(required=False, default=False)
|
|
31
|
+
device_details = ndb.JsonProperty()
|
|
31
32
|
|
|
32
33
|
dict_properties = ['device_name', 'activation_code', 'device_id', 'activated', 'assigned_outlet_key',
|
|
33
|
-
'activated_datetime', 'created_datetime']
|
|
34
|
+
'activated_datetime', 'created_datetime', 'device_details']
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def device_tokens_list(self):
|
|
38
|
+
if self.device_details:
|
|
39
|
+
_tokens_list = []
|
|
40
|
+
for k,v in self.device_details.items():
|
|
41
|
+
for dd in v:
|
|
42
|
+
_tokens_list.append(dd.get('device_token'))
|
|
43
|
+
return _tokens_list
|
|
34
44
|
|
|
35
45
|
@property
|
|
36
46
|
def is_test_setting(self):
|
|
@@ -135,3 +145,42 @@ class LoyaltyDeviceSetting(BaseNModel,DictModel):
|
|
|
135
145
|
return True
|
|
136
146
|
else:
|
|
137
147
|
return False
|
|
148
|
+
|
|
149
|
+
def update_device_details(self, platform, device_token):
|
|
150
|
+
if self.device_details:
|
|
151
|
+
found_device_details_list_by_platform = self.device_details.get(platform)
|
|
152
|
+
if found_device_details_list_by_platform:
|
|
153
|
+
is_found = False
|
|
154
|
+
for device_details_by_platform in found_device_details_list_by_platform:
|
|
155
|
+
device_token_by_platform = device_details_by_platform.get('device_token')
|
|
156
|
+
if device_token_by_platform:
|
|
157
|
+
device_details_by_platform['last_updated_datetime'] = datetime.utcnow().strftime("%d-%m-%Y %H:%M:%S")
|
|
158
|
+
is_found = True
|
|
159
|
+
break
|
|
160
|
+
|
|
161
|
+
if is_found == False:
|
|
162
|
+
found_device_details_list_by_platform.append(
|
|
163
|
+
{
|
|
164
|
+
'device_token' : device_token,
|
|
165
|
+
'last_updated_datetime' : datetime.utcnow().strftime("%d-%m-%Y %H:%M:%S"),
|
|
166
|
+
}
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
else:
|
|
171
|
+
self.device_details[platform] = [
|
|
172
|
+
{
|
|
173
|
+
'device_token' : device_token,
|
|
174
|
+
'last_updated_datetime' : datetime.utcnow().strftime("%d-%m-%Y %H:%M:%S"),
|
|
175
|
+
}
|
|
176
|
+
]
|
|
177
|
+
else:
|
|
178
|
+
self.device_details = {
|
|
179
|
+
platform : [
|
|
180
|
+
{
|
|
181
|
+
'device_token' : device_token,
|
|
182
|
+
'last_updated_datetime' : datetime.utcnow().strftime("%d-%m-%Y %H:%M:%S"),
|
|
183
|
+
}
|
|
184
|
+
]
|
|
185
|
+
}
|
|
186
|
+
self.put()
|
|
@@ -5,11 +5,20 @@ Created on 9 Nov 2023
|
|
|
5
5
|
'''
|
|
6
6
|
from trexmodel.program_conf import REWARD_FORMAT_MAP, REWARD_FORMAT_PREPAID
|
|
7
7
|
from trexmodel.models.datastore.message_models import Message
|
|
8
|
-
from trexmodel.conf import MESSAGE_CATEGORY_REWARD, MESSAGE_STATUS_NEW
|
|
8
|
+
from trexmodel.conf import MESSAGE_CATEGORY_REWARD, MESSAGE_STATUS_NEW,\
|
|
9
|
+
MESSAGE_CATEGORY_REDEEM
|
|
10
|
+
from trexmodel import program_conf
|
|
11
|
+
from babel.numbers import format_currency
|
|
12
|
+
import logging
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger('helper')
|
|
9
16
|
|
|
10
17
|
entitled_reward_message_template = '''{amount} {reward_format}'''
|
|
11
18
|
|
|
12
19
|
entitled_voucher_message_template = '''{amount} voucher - {label}'''
|
|
20
|
+
|
|
21
|
+
redeemed_voucher_message_template = '''{amount} voucher - {label}'''
|
|
13
22
|
|
|
14
23
|
entitled_lucky_draw_message_template = '''{amount} lucky draw ticket(s)'''
|
|
15
24
|
|
|
@@ -131,34 +140,70 @@ message_logo_image_template = '''
|
|
|
131
140
|
|
|
132
141
|
|
|
133
142
|
def create_transaction_message(customer_transaction):
|
|
134
|
-
user_acct
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
143
|
+
user_acct = customer_transaction.transact_user_acct
|
|
144
|
+
source_key = customer_transaction.key_in_str
|
|
145
|
+
message = Message.get_by_source_key(source_key)
|
|
146
|
+
|
|
147
|
+
if message is None:
|
|
148
|
+
message = Message(
|
|
149
|
+
message_to = user_acct.create_ndb_key(),
|
|
150
|
+
title = 'Transaction Reward',
|
|
151
|
+
message_category = MESSAGE_CATEGORY_REWARD,
|
|
152
|
+
message_content = __create_entiled_message_from_customer_transaction(customer_transaction),
|
|
153
|
+
message_data = __create_message_data_from_transaction(customer_transaction),
|
|
154
|
+
status = MESSAGE_STATUS_NEW,
|
|
155
|
+
|
|
156
|
+
)
|
|
157
|
+
message.put()
|
|
158
|
+
user_acct.new_message_count+=1
|
|
159
|
+
user_acct.put()
|
|
160
|
+
|
|
161
|
+
return message
|
|
162
|
+
|
|
163
|
+
def create_redemption_message(customer_redemption):
|
|
164
|
+
user_acct = customer_redemption.redeemed_user_acct
|
|
165
|
+
merchant_acct = customer_redemption.redeemed_merchant_acct
|
|
166
|
+
source_key = customer_redemption.key_in_str
|
|
167
|
+
message = Message.get_by_source_key(source_key)
|
|
168
|
+
|
|
169
|
+
if message is None:
|
|
170
|
+
message = Message(
|
|
171
|
+
source_key = source_key,
|
|
172
|
+
message_to = user_acct.create_ndb_key(),
|
|
173
|
+
title = 'Redemption',
|
|
174
|
+
message_category = MESSAGE_CATEGORY_REDEEM,
|
|
175
|
+
message_content = __create_message_from_redeem_transaction(merchant_acct, customer_redemption),
|
|
176
|
+
message_data = __create_message_data_from_transaction(customer_redemption),
|
|
177
|
+
status = MESSAGE_STATUS_NEW,
|
|
178
|
+
|
|
179
|
+
)
|
|
180
|
+
message.put()
|
|
181
|
+
user_acct.new_message_count+=1
|
|
182
|
+
user_acct.put()
|
|
183
|
+
|
|
184
|
+
return message
|
|
147
185
|
|
|
148
186
|
def create_redeem_catalogue_item_message(customer, entitled_vouchers_summary, redemption_catalogue_transaction):
|
|
149
|
-
user_acct
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
187
|
+
user_acct = customer.registered_user_acct
|
|
188
|
+
source_key = redemption_catalogue_transaction.key_in_str
|
|
189
|
+
message = Message.get_by_source_key(source_key)
|
|
190
|
+
|
|
191
|
+
if message is None:
|
|
192
|
+
message = Message(
|
|
193
|
+
|
|
194
|
+
message_to = user_acct.create_ndb_key(),
|
|
195
|
+
title = 'Redemption Catalogue Reward',
|
|
196
|
+
message_category = MESSAGE_CATEGORY_REWARD,
|
|
197
|
+
message_content = __create_message_from_redeem_catalogue_transaction(customer, entitled_vouchers_summary),
|
|
198
|
+
message_data = __create_message_data_from_redemption_catalogue(redemption_catalogue_transaction),
|
|
199
|
+
status = MESSAGE_STATUS_NEW,
|
|
200
|
+
|
|
201
|
+
)
|
|
202
|
+
message.put()
|
|
203
|
+
user_acct.new_message_count+=1
|
|
204
|
+
user_acct.put()
|
|
205
|
+
|
|
206
|
+
return message
|
|
162
207
|
|
|
163
208
|
def __create_message_data_from_transaction(customer_transaction):
|
|
164
209
|
return {
|
|
@@ -201,23 +246,6 @@ def __create_entiled_message_from_customer_transaction(customer_transaction):
|
|
|
201
246
|
'font-size' : 20,
|
|
202
247
|
})
|
|
203
248
|
|
|
204
|
-
merchant_logo_content = message_logo_image_template.format(merchant_logo= merchant_logo,)
|
|
205
|
-
merchant_name = merchant_acct.company_name
|
|
206
|
-
'''
|
|
207
|
-
html_content = entitled_messages_template.format(
|
|
208
|
-
message_list = ''.join(message_list),
|
|
209
|
-
merchant_logo = merchant_name,
|
|
210
|
-
#message_banner_image = message_banner_image_template,
|
|
211
|
-
message_banner_image = '',
|
|
212
|
-
#message_congrat_image = message_congrat_image_template,
|
|
213
|
-
message_congrat_image = '',
|
|
214
|
-
)
|
|
215
|
-
|
|
216
|
-
return {
|
|
217
|
-
'type' : 'html',
|
|
218
|
-
'content' : html_content,
|
|
219
|
-
}
|
|
220
|
-
'''
|
|
221
249
|
return {
|
|
222
250
|
'type' : 'json',
|
|
223
251
|
'content' : {
|
|
@@ -287,9 +315,6 @@ def __create_message_from_redeem_catalogue_transaction(customer, entitled_vouche
|
|
|
287
315
|
'font-size' : 20,
|
|
288
316
|
})
|
|
289
317
|
|
|
290
|
-
merchant_logo_content = message_logo_image_template.format(merchant_logo= merchant_logo,)
|
|
291
|
-
merchant_name = merchant_acct.company_name
|
|
292
|
-
|
|
293
318
|
return {
|
|
294
319
|
'type' : 'json',
|
|
295
320
|
'content' : {
|
|
@@ -338,7 +363,57 @@ def __create_message_from_redeem_catalogue_transaction(customer, entitled_vouche
|
|
|
338
363
|
]
|
|
339
364
|
}
|
|
340
365
|
}
|
|
366
|
+
|
|
367
|
+
def __create_message_from_redeem_transaction(merchant_acct, customer_redemption):
|
|
368
|
+
|
|
369
|
+
messages_list = []
|
|
370
|
+
|
|
371
|
+
message_list = []
|
|
372
|
+
#merchant_logo = merchant_acct.logo_public_url
|
|
373
|
+
brand_name = merchant_acct.brand_name
|
|
374
|
+
|
|
375
|
+
messages_for_json_list = []
|
|
376
|
+
|
|
377
|
+
messages_list.extend(__create_customer_redemption_message(customer_redemption))
|
|
341
378
|
|
|
379
|
+
for message in messages_list:
|
|
380
|
+
message_list.append('<li class="pt-2">{message}</li>'.format(message=message))
|
|
381
|
+
messages_for_json_list.append({
|
|
382
|
+
'type' : 'text',
|
|
383
|
+
'value' : message,
|
|
384
|
+
'font-size' : 20,
|
|
385
|
+
})
|
|
386
|
+
|
|
387
|
+
return {
|
|
388
|
+
'type' : 'json',
|
|
389
|
+
'content' : {
|
|
390
|
+
'header':[
|
|
391
|
+
{
|
|
392
|
+
'type': 'text',
|
|
393
|
+
'value': 'Redemption'
|
|
394
|
+
|
|
395
|
+
},
|
|
396
|
+
],
|
|
397
|
+
'title':[
|
|
398
|
+
{
|
|
399
|
+
'type':'text',
|
|
400
|
+
'value': __create_customer_redemption_title(customer_redemption),
|
|
401
|
+
'font-size': 25,
|
|
402
|
+
}
|
|
403
|
+
],
|
|
404
|
+
|
|
405
|
+
'body':messages_for_json_list,
|
|
406
|
+
|
|
407
|
+
'footer':[
|
|
408
|
+
|
|
409
|
+
{
|
|
410
|
+
'type':'text',
|
|
411
|
+
'value': 'To %s' % brand_name,
|
|
412
|
+
'font-size': 25,
|
|
413
|
+
}
|
|
414
|
+
]
|
|
415
|
+
}
|
|
416
|
+
}
|
|
342
417
|
|
|
343
418
|
def __create_entitled_reward_message(customer_transaction):
|
|
344
419
|
entitled_reward_summary = customer_transaction.entitled_reward_summary
|
|
@@ -389,6 +464,46 @@ def __create_entitled_voucher_message_from_entitled_voucher_summary(entitled_vou
|
|
|
389
464
|
|
|
390
465
|
return entitled_messages_list
|
|
391
466
|
|
|
467
|
+
def __create_customer_redemption_message(customer_redemption):
|
|
468
|
+
messages_list = []
|
|
469
|
+
if customer_redemption.reward_format == program_conf.FEATURE_CODE_PREPAID_REWARD_FORMAT:
|
|
470
|
+
merchant_acct = customer_redemption.redeemed_merchant_acct
|
|
471
|
+
|
|
472
|
+
logger.debug('redeemed_amount=%d', customer_redemption.redeemed_amount)
|
|
473
|
+
logger.debug('currency_code=%s', merchant_acct.currency_code)
|
|
474
|
+
|
|
475
|
+
formated_redeem_amount = format_currency(customer_redemption.redeemed_amount,
|
|
476
|
+
merchant_acct.currency_code,
|
|
477
|
+
u'#,##0.00',
|
|
478
|
+
locale='en_US',
|
|
479
|
+
currency_digits=False,
|
|
480
|
+
)
|
|
481
|
+
logger.debug('formated_redeem_amount=%s', formated_redeem_amount)
|
|
482
|
+
|
|
483
|
+
messages_list.append("%s prepaid" % (formated_redeem_amount))
|
|
484
|
+
|
|
485
|
+
elif customer_redemption.reward_format == program_conf.FEATURE_CODE_VOUCHER_REWARD_FORMAT:
|
|
486
|
+
redeemed_summary = customer_redemption.redeemed_summary
|
|
487
|
+
redeemed_vouchers_list = redeemed_summary.get('voucher').get('vouchers')
|
|
488
|
+
for voucher_key, voucher_details in redeemed_vouchers_list.items():
|
|
489
|
+
|
|
490
|
+
messages_list.append(
|
|
491
|
+
redeemed_voucher_message_template.format(
|
|
492
|
+
label = voucher_details.get('label'),
|
|
493
|
+
amount = voucher_details.get('amount'),
|
|
494
|
+
)
|
|
495
|
+
)
|
|
496
|
+
|
|
497
|
+
return messages_list
|
|
498
|
+
|
|
499
|
+
def __create_customer_redemption_title(customer_redemption):
|
|
500
|
+
|
|
501
|
+
if customer_redemption.reward_format == program_conf.FEATURE_CODE_PREPAID_REWARD_FORMAT:
|
|
502
|
+
return "You have paid"
|
|
503
|
+
|
|
504
|
+
elif customer_redemption.reward_format == program_conf.FEATURE_CODE_VOUCHER_REWARD_FORMAT:
|
|
505
|
+
return "You have redeemed"
|
|
506
|
+
|
|
392
507
|
def __create_entitled_lucky_draw_ticket_message(customer_transaction):
|
|
393
508
|
entitled_lucky_draw_ticket_summary = customer_transaction.entitled_lucky_draw_ticket_summary
|
|
394
509
|
entitled_messages_list = [
|
|
@@ -34,6 +34,7 @@ content_body=[text in html]
|
|
|
34
34
|
|
|
35
35
|
class Message(BaseNModel, DictModel):
|
|
36
36
|
message_to = ndb.KeyProperty(name="message_to", kind=User)
|
|
37
|
+
source_key = ndb.StringProperty(required=False)
|
|
37
38
|
title = ndb.StringProperty(required=True)
|
|
38
39
|
message_category = ndb.StringProperty(required=True, default=MESSAGE_CATEGORY_SYSTEM, choices=MESSAGE_CATEGORIES)
|
|
39
40
|
message_content = ndb.JsonProperty(required=True, indexed=False)
|
|
@@ -44,7 +45,7 @@ class Message(BaseNModel, DictModel):
|
|
|
44
45
|
email_sent_datetime = ndb.DateTimeProperty(required=False)
|
|
45
46
|
|
|
46
47
|
dict_properties = [
|
|
47
|
-
'message_to', 'title', 'message_category', 'message_content', 'message_data', 'status', 'created_datetime'
|
|
48
|
+
'source_key', 'message_to', 'title', 'message_category', 'message_content', 'message_data', 'status', 'created_datetime'
|
|
48
49
|
]
|
|
49
50
|
|
|
50
51
|
@property
|
|
@@ -59,8 +60,9 @@ class Message(BaseNModel, DictModel):
|
|
|
59
60
|
return CustomerTransaction.fetch(customer_transaction_key)
|
|
60
61
|
|
|
61
62
|
@staticmethod
|
|
62
|
-
def create(message_to=None, title=None, message_type=MESSAGE_CATEGORY_ANNOUNCEMENT,message_content={}):
|
|
63
|
+
def create(source_key=None, message_to=None, title=None, message_type=MESSAGE_CATEGORY_ANNOUNCEMENT,message_content={}):
|
|
63
64
|
Message(
|
|
65
|
+
source_key = source_key,
|
|
64
66
|
message_to = message_to.create_ndb_key(),
|
|
65
67
|
title = title,
|
|
66
68
|
message_type = message_type,
|
|
@@ -99,5 +101,7 @@ class Message(BaseNModel, DictModel):
|
|
|
99
101
|
return Message.list_all_with_condition_query(query, limit=limit, start_cursor=start_cursor, return_with_cursor=True, keys_only=False)
|
|
100
102
|
|
|
101
103
|
|
|
102
|
-
|
|
104
|
+
@staticmethod
|
|
105
|
+
def get_by_source_key(source_key):
|
|
106
|
+
return Message.query(ndb.AND(Message.source_key==source_key)).get()
|
|
103
107
|
|
|
@@ -9,14 +9,16 @@ from trexmodel.models.datastore.user_models import User
|
|
|
9
9
|
from trexmodel.models.datastore.merchant_models import MerchantAcct, Outlet, MerchantUser
|
|
10
10
|
import logging, json
|
|
11
11
|
from trexmodel import conf, program_conf
|
|
12
|
-
from trexlib.utils.string_util import random_string
|
|
12
|
+
from trexlib.utils.string_util import random_string, random_number, is_not_empty
|
|
13
13
|
from datetime import datetime, timedelta
|
|
14
14
|
import trexmodel.conf as model_conf
|
|
15
15
|
from trexlib.utils.common.common_util import sort_dict_list
|
|
16
16
|
from trexmodel.utils.model.model_util import generate_transaction_id
|
|
17
17
|
from dateutil.relativedelta import relativedelta
|
|
18
|
+
from trexmodel.program_conf import PRODUCT_TYPES, LOYALTY_PRODUCT
|
|
19
|
+
from trexlib.utils.crypto_util import encrypt
|
|
18
20
|
|
|
19
|
-
logger = logging.getLogger('
|
|
21
|
+
logger = logging.getLogger('model')
|
|
20
22
|
|
|
21
23
|
class PrepaidSettings(BaseNModel,DictModel):
|
|
22
24
|
'''
|
|
@@ -185,6 +187,160 @@ class PrepaidSettings(BaseNModel,DictModel):
|
|
|
185
187
|
merchant_acct.remove_prepaid_program_configuration(prepaid_settings.key_in_str)
|
|
186
188
|
merchant_acct.put()
|
|
187
189
|
|
|
190
|
+
class PrepaidRedeemSettings(BaseNModel,DictModel):
|
|
191
|
+
'''
|
|
192
|
+
Merchant acct as ancestor
|
|
193
|
+
'''
|
|
194
|
+
label = ndb.StringProperty(required=True)
|
|
195
|
+
device_activation_code = ndb.StringProperty(required=True)
|
|
196
|
+
device_type = ndb.StringProperty(required=False, default=LOYALTY_PRODUCT, choices=set(PRODUCT_TYPES))
|
|
197
|
+
assigned_outlet = ndb.KeyProperty(name="assigned_outlet", kind=Outlet)
|
|
198
|
+
testing = ndb.BooleanProperty(required=False, default=False)
|
|
199
|
+
|
|
200
|
+
redeem_code = ndb.StringProperty(required=True)
|
|
201
|
+
|
|
202
|
+
created_datetime = ndb.DateTimeProperty(required=True, auto_now_add=True)
|
|
203
|
+
modified_datetime = ndb.DateTimeProperty(required=True, auto_now=True)
|
|
204
|
+
|
|
205
|
+
created_by = ndb.KeyProperty(name="created_by", kind=MerchantUser)
|
|
206
|
+
created_by_username = ndb.StringProperty(required=False)
|
|
207
|
+
modified_by = ndb.KeyProperty(name="modified_by", kind=MerchantUser)
|
|
208
|
+
modified_by_username = ndb.StringProperty(required=False)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
dict_properties = [
|
|
212
|
+
'label', 'redeem_code', 'redeem_url', 'device_activation_code', 'device_type', 'assigned_outlet_key', 'created_datetime', 'modified_datetime',
|
|
213
|
+
]
|
|
214
|
+
|
|
215
|
+
@property
|
|
216
|
+
def is_test_setting(self):
|
|
217
|
+
return self.testing
|
|
218
|
+
|
|
219
|
+
@property
|
|
220
|
+
def assigned_outlet_key(self):
|
|
221
|
+
return self.assigned_outlet.urlsafe().decode('utf-8')
|
|
222
|
+
|
|
223
|
+
@property
|
|
224
|
+
def assigned_outlet_entity(self):
|
|
225
|
+
return Outlet.fetch(self.assigned_outlet_key)
|
|
226
|
+
|
|
227
|
+
@property
|
|
228
|
+
def merchant_acct_entity(self):
|
|
229
|
+
return MerchantAcct.fetch(self.key.parent().urlsafe())
|
|
230
|
+
|
|
231
|
+
@property
|
|
232
|
+
def redeem_url(self):
|
|
233
|
+
encrypted_redeem_code = encrypt(self.redeem_code)
|
|
234
|
+
return conf.PREPAID_REDEEM_URL.format(code=encrypted_redeem_code)
|
|
235
|
+
|
|
236
|
+
@property
|
|
237
|
+
def is_loyalty_device(self):
|
|
238
|
+
if self.device_type == program_conf.LOYALTY_PRODUCT:
|
|
239
|
+
return True
|
|
240
|
+
return False
|
|
241
|
+
|
|
242
|
+
@staticmethod
|
|
243
|
+
def create(merchant_acct, label, assigned_outlet, device_activation_code=None, testing=False,
|
|
244
|
+
created_by=None
|
|
245
|
+
):
|
|
246
|
+
|
|
247
|
+
created_by_username = None
|
|
248
|
+
if is_not_empty(created_by):
|
|
249
|
+
if isinstance(created_by, MerchantUser):
|
|
250
|
+
created_by_username = created_by.username
|
|
251
|
+
|
|
252
|
+
redeem_code = random_number(24)
|
|
253
|
+
checking_redeem_setting = PrepaidRedeemSettings.get_by_redeem_code(redeem_code)
|
|
254
|
+
regenerate_redeem_code = False
|
|
255
|
+
|
|
256
|
+
if checking_redeem_setting:
|
|
257
|
+
regenerate_redeem_code = True
|
|
258
|
+
|
|
259
|
+
while(regenerate_redeem_code):
|
|
260
|
+
redeem_code = random_number(24)
|
|
261
|
+
checking_redeem_setting = PrepaidRedeemSettings.get_by_redeem_code(redeem_code)
|
|
262
|
+
if checking_redeem_setting==None:
|
|
263
|
+
regenerate_redeem_code = False
|
|
264
|
+
|
|
265
|
+
prepaid_redeem_settings = PrepaidRedeemSettings(
|
|
266
|
+
parent = merchant_acct.create_ndb_key(),
|
|
267
|
+
assigned_outlet = assigned_outlet.create_ndb_key(),
|
|
268
|
+
label = label,
|
|
269
|
+
redeem_code = redeem_code,
|
|
270
|
+
testing = testing,
|
|
271
|
+
device_activation_code = device_activation_code,
|
|
272
|
+
|
|
273
|
+
created_by = created_by.create_ndb_key(),
|
|
274
|
+
created_by_username = created_by_username,
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
prepaid_redeem_settings.put()
|
|
278
|
+
|
|
279
|
+
return prepaid_redeem_settings
|
|
280
|
+
|
|
281
|
+
@staticmethod
|
|
282
|
+
def update(prepaid_redeem_settings_key, label, assigned_outlet, device_activation_code=None,
|
|
283
|
+
modified_by=None
|
|
284
|
+
):
|
|
285
|
+
|
|
286
|
+
modified_by_username = None
|
|
287
|
+
if is_not_empty(modified_by):
|
|
288
|
+
if isinstance(modified_by, MerchantUser):
|
|
289
|
+
modified_by_username = modified_by.username
|
|
290
|
+
|
|
291
|
+
prepaid_redeem_settings = PrepaidRedeemSettings.fetch(prepaid_redeem_settings_key)
|
|
292
|
+
|
|
293
|
+
prepaid_redeem_settings.label = label
|
|
294
|
+
prepaid_redeem_settings.device_activation_code = device_activation_code
|
|
295
|
+
prepaid_redeem_settings.assigned_outlet = assigned_outlet.create_ndb_key()
|
|
296
|
+
prepaid_redeem_settings.modified_by = modified_by.create_ndb_key()
|
|
297
|
+
prepaid_redeem_settings.modified_by_username = modified_by_username
|
|
298
|
+
|
|
299
|
+
prepaid_redeem_settings.put()
|
|
300
|
+
|
|
301
|
+
return prepaid_redeem_settings
|
|
302
|
+
|
|
303
|
+
@staticmethod
|
|
304
|
+
def remove(prepaid_redeem_settings_key):
|
|
305
|
+
prepaid_redeem_settings = PrepaidRedeemSettings.fetch(prepaid_redeem_settings_key)
|
|
306
|
+
if prepaid_redeem_settings:
|
|
307
|
+
prepaid_redeem_settings.delete()
|
|
308
|
+
|
|
309
|
+
@staticmethod
|
|
310
|
+
def get_by_redeem_code(redeem_code):
|
|
311
|
+
return PrepaidRedeemSettings.query(PrepaidRedeemSettings.redeem_code ==redeem_code).get()
|
|
312
|
+
|
|
313
|
+
@staticmethod
|
|
314
|
+
def list_by_merchant_account_and_assigned_outlet(merchant_acct, assigned_outlet, offset=0, limit=conf.PAGINATION_SIZE, start_cursor=None, return_with_cursor=False):
|
|
315
|
+
query = PrepaidRedeemSettings.query(ndb.AND(
|
|
316
|
+
PrepaidRedeemSettings.assigned_outlet==assigned_outlet.create_ndb_key()
|
|
317
|
+
),ancestor=merchant_acct.create_ndb_key())
|
|
318
|
+
|
|
319
|
+
return PrepaidRedeemSettings.list_all_with_condition_query(query, offset=offset, limit=limit, start_cursor=start_cursor, return_with_cursor=return_with_cursor)
|
|
320
|
+
|
|
321
|
+
@staticmethod
|
|
322
|
+
def count_by_merchant_account_and_assigned_outlet(merchant_acct, assigned_outlet):
|
|
323
|
+
query = PrepaidRedeemSettings.query(ndb.AND(
|
|
324
|
+
PrepaidRedeemSettings.assigned_outlet==assigned_outlet.create_ndb_key()
|
|
325
|
+
),ancestor=merchant_acct.create_ndb_key())
|
|
326
|
+
|
|
327
|
+
return PrepaidRedeemSettings.count_with_condition_query(query)
|
|
328
|
+
|
|
329
|
+
@staticmethod
|
|
330
|
+
def list_by_merchant_account(merchant_acct, offset=0, limit=conf.PAGINATION_SIZE, start_cursor=None, return_with_cursor=False):
|
|
331
|
+
query = PrepaidRedeemSettings.query(ancestor=merchant_acct.create_ndb_key())
|
|
332
|
+
|
|
333
|
+
return PrepaidRedeemSettings.list_all_with_condition_query(query, offset=offset, limit=limit, start_cursor=start_cursor, return_with_cursor=return_with_cursor)
|
|
334
|
+
|
|
335
|
+
@staticmethod
|
|
336
|
+
def count_by_merchant_acct(merchant_acct):
|
|
337
|
+
if merchant_acct:
|
|
338
|
+
query = PrepaidRedeemSettings.query(ancestor=merchant_acct.create_ndb_key())
|
|
339
|
+
else:
|
|
340
|
+
query = PrepaidRedeemSettings.query()
|
|
341
|
+
|
|
342
|
+
return PrepaidRedeemSettings.count_with_condition_query(query)
|
|
343
|
+
|
|
188
344
|
class CustomerPrepaidReward(BaseNModel,DictModel):
|
|
189
345
|
'''
|
|
190
346
|
Customer acct as ancestor
|
|
@@ -62,7 +62,7 @@ class CustomerRedemption(BaseNModel, DictModel):
|
|
|
62
62
|
redeemed_amount = ndb.FloatProperty(required=True, default=1)
|
|
63
63
|
|
|
64
64
|
redeemed_summary = ndb.JsonProperty(required=True)
|
|
65
|
-
|
|
65
|
+
prepaid_redeem_code = ndb.StringProperty(required=False)
|
|
66
66
|
transaction_id = ndb.StringProperty(required=True)
|
|
67
67
|
invoice_id = ndb.StringProperty(required=False)
|
|
68
68
|
remarks = ndb.StringProperty(required=False)
|
|
@@ -85,7 +85,7 @@ class CustomerRedemption(BaseNModel, DictModel):
|
|
|
85
85
|
'redeemed_summary', 'redeemed_customer_acct', 'redeemed_outlet_details', 'redeemed_merchant_acct',
|
|
86
86
|
'redeemed_datetime', 'is_revert', 'allow_to_revert', 'redeemed_outlet',
|
|
87
87
|
'is_system_redemption', 'is_tier_program_redemption', 'tier_program_transaction_id',
|
|
88
|
-
'redeemed_by_username', 'reverted_datetime', 'reverted_by_username',
|
|
88
|
+
'redeemed_by_username', 'reverted_datetime', 'reverted_by_username', 'prepaid_redeem_code',
|
|
89
89
|
]
|
|
90
90
|
|
|
91
91
|
@staticmethod
|
|
@@ -100,6 +100,12 @@ class CustomerRedemption(BaseNModel, DictModel):
|
|
|
100
100
|
def is_system_redemption(self):
|
|
101
101
|
return self.is_tier_program_redemption
|
|
102
102
|
|
|
103
|
+
@property
|
|
104
|
+
def is_redeem_by_user(self):
|
|
105
|
+
if self.reward_format == program_conf.REWARD_FORMAT_PREPAID and is_not_empty(self.prepaid_redeem_code):
|
|
106
|
+
return True
|
|
107
|
+
return False
|
|
108
|
+
|
|
103
109
|
@property
|
|
104
110
|
def allow_to_revert(self):
|
|
105
111
|
return self.is_revert == False and self.is_tier_program_redemption==False
|
|
@@ -128,6 +134,10 @@ class CustomerRedemption(BaseNModel, DictModel):
|
|
|
128
134
|
def redeemed_merchant_acct(self):
|
|
129
135
|
return MerchantAcct.fetch(self.merchant_acct.urlsafe())
|
|
130
136
|
|
|
137
|
+
@property
|
|
138
|
+
def redeemed_user_acct(self):
|
|
139
|
+
return User.fetch(self.user_acct.urlsafe())
|
|
140
|
+
|
|
131
141
|
@property
|
|
132
142
|
def redeemed_merchant_acct_key(self):
|
|
133
143
|
return self.merchant_acct.urlsafe().decode('utf-8')
|
|
@@ -242,7 +252,7 @@ class CustomerRedemption(BaseNModel, DictModel):
|
|
|
242
252
|
@staticmethod
|
|
243
253
|
def create(customer, reward_format, redeemed_outlet=None, transaction_id=None,
|
|
244
254
|
redeemed_amount=1, is_tier_program_redemption=False, tier_program_transaction_id=None,
|
|
245
|
-
redeemed_voucher_keys_list=None, invoice_id=None, remarks=None,
|
|
255
|
+
redeemed_voucher_keys_list=None, invoice_id=None, remarks=None, prepaid_redeem_code=None,
|
|
246
256
|
redeemed_by=None, redeemed_datetime=None, redemption_catalogue_transction_summary=None):
|
|
247
257
|
|
|
248
258
|
|
|
@@ -256,7 +266,7 @@ class CustomerRedemption(BaseNModel, DictModel):
|
|
|
256
266
|
redeemed_by_username = redeemed_by.username
|
|
257
267
|
|
|
258
268
|
|
|
259
|
-
redeem_transaction_id = transaction_id or generate_transaction_id(prefix='
|
|
269
|
+
redeem_transaction_id = transaction_id or generate_transaction_id(prefix='d')
|
|
260
270
|
|
|
261
271
|
if redeemed_datetime is None:
|
|
262
272
|
redeemed_datetime = datetime.utcnow()
|
|
@@ -552,7 +562,7 @@ class CustomerRedemption(BaseNModel, DictModel):
|
|
|
552
562
|
reward_format = reward_format,
|
|
553
563
|
redeemed_amount = redeemed_amount,
|
|
554
564
|
redeemed_summary = redeemed_summary,
|
|
555
|
-
|
|
565
|
+
prepaid_redeem_code = prepaid_redeem_code,
|
|
556
566
|
transaction_id = redeem_transaction_id,
|
|
557
567
|
invoice_id = invoice_id,
|
|
558
568
|
remarks = remarks,
|
|
@@ -13,6 +13,8 @@ IMAGE_BASE_URL = os.environ.get('IMAGE_BASE_URL')
|
|
|
13
13
|
POS_PRODUCT = 'point_of_sales'
|
|
14
14
|
LOYALTY_PRODUCT = 'loyalty'
|
|
15
15
|
|
|
16
|
+
PRODUCT_TYPES = (POS_PRODUCT, LOYALTY_PRODUCT)
|
|
17
|
+
|
|
16
18
|
POS_PACKAGE_DEFAULT = 'lite'
|
|
17
19
|
POS_PACKAGE_STANDARD = 'standard'
|
|
18
20
|
POS_PACKAGE_SCALE = 'scale'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/redemption_catalogue_models.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{trex-model-1.2.19 → trex-model-1.3.1}/trexmodel/models/datastore/spending_base_program_model.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|