trex-model 1.2.17__tar.gz → 1.2.19__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.17 → trex-model-1.2.19}/PKG-INFO +1 -1
- {trex-model-1.2.17 → trex-model-1.2.19}/setup.py +1 -1
- {trex-model-1.2.17 → trex-model-1.2.19}/trex_model.egg-info/PKG-INFO +1 -1
- {trex-model-1.2.17 → trex-model-1.2.19}/trex_model.egg-info/SOURCES.txt +1 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/customer_models.py +3 -1
- trex-model-1.2.19/trexmodel/models/datastore/marketing_models.py +226 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/merchant_models.py +12 -6
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/ndb_models.py +2 -1
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/redemption_catalogue_models.py +10 -4
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/system_models.py +19 -4
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/user_models.py +46 -4
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/program_conf.py +12 -3
- {trex-model-1.2.17 → trex-model-1.2.19}/LICENSE +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/MANIFEST.in +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/README.md +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/setup.cfg +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trex_model.egg-info/dependency_links.txt +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trex_model.egg-info/requires.txt +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trex_model.egg-info/top_level.txt +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/__init__.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/conf.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/__init__.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/__init__.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/admin_models.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/analytic_models.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/app_models.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/coporate_models.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/customer_model_helpers.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/fb_subsriber_models.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/import_models.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/inventory_model.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/loyalty_models.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/lucky_draw_models.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/membership_models.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/message_model_helper.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/message_models.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/model_decorators.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/pos_models.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/prepaid_models.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/product_models.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/program_models.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/rating_models.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/redeem_models.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/reward_model_helpers.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/reward_models.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/spending_base_program_model.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/task_models.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/test_models.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/transaction_models.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/voucher_models.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/merchant_helpers.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/model_decorator.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/prepaid_helpers.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/pos_conf.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/utils/__init__.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/utils/gcloud/__init__.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/utils/gcloud/datastore_util.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/utils/model/__init__.py +0 -0
- {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/utils/model/model_util.py +0 -0
|
@@ -28,6 +28,7 @@ trexmodel/models/datastore/import_models.py
|
|
|
28
28
|
trexmodel/models/datastore/inventory_model.py
|
|
29
29
|
trexmodel/models/datastore/loyalty_models.py
|
|
30
30
|
trexmodel/models/datastore/lucky_draw_models.py
|
|
31
|
+
trexmodel/models/datastore/marketing_models.py
|
|
31
32
|
trexmodel/models/datastore/membership_models.py
|
|
32
33
|
trexmodel/models/datastore/merchant_models.py
|
|
33
34
|
trexmodel/models/datastore/message_model_helper.py
|
|
@@ -70,6 +70,8 @@ class Customer(BaseNModel, DictModel, FullTextSearchable):
|
|
|
70
70
|
|
|
71
71
|
kpi_summary = ndb.JsonProperty()
|
|
72
72
|
|
|
73
|
+
device_details = ndb.JsonProperty()
|
|
74
|
+
|
|
73
75
|
fulltextsearch_field_name = 'name'
|
|
74
76
|
|
|
75
77
|
dict_properties = ['name', 'mobile_phone', 'email', 'gender', 'birth_date', 'reference_code', 'merchant_reference_code',
|
|
@@ -77,7 +79,7 @@ class Customer(BaseNModel, DictModel, FullTextSearchable):
|
|
|
77
79
|
'reward_summary', 'entitled_voucher_summary', 'prepaid_summary', 'kpi_summary', 'entitled_lucky_draw_ticket_summary',
|
|
78
80
|
'entitled_birthday_reward_summary', 'tier_membership_key',
|
|
79
81
|
'registered_outlet_key', 'registered_merchant_acct_key', 'registered_datetime', 'modified_datetime',
|
|
80
|
-
|
|
82
|
+
'registered_user_acct',
|
|
81
83
|
|
|
82
84
|
]
|
|
83
85
|
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
'''
|
|
2
|
+
Created on 8 Jan 2024
|
|
3
|
+
|
|
4
|
+
@author: jacklok
|
|
5
|
+
'''
|
|
6
|
+
from trexmodel.models.datastore.ndb_models import BaseNModel, DictModel
|
|
7
|
+
from google.cloud import ndb
|
|
8
|
+
from trexmodel.models.datastore.merchant_models import MerchantUser,\
|
|
9
|
+
MerchantAcct
|
|
10
|
+
from trexlib.utils.string_util import is_not_empty, random_string
|
|
11
|
+
from datetime import datetime
|
|
12
|
+
from trexmodel import program_conf, conf
|
|
13
|
+
import trexmodel.conf as model_conf
|
|
14
|
+
import logging
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger('model')
|
|
17
|
+
|
|
18
|
+
class PushNotificationSetup(BaseNModel, DictModel):
|
|
19
|
+
'''
|
|
20
|
+
Merchant Acct as ancestor
|
|
21
|
+
|
|
22
|
+
'''
|
|
23
|
+
|
|
24
|
+
title = ndb.StringProperty(required=True)
|
|
25
|
+
desc = ndb.StringProperty(required=True)
|
|
26
|
+
send_mode = ndb.StringProperty(required=True, default="send_now", choices=set(['send_now','send_schedule']))
|
|
27
|
+
schedule_datetime = ndb.DateTimeProperty(required=False)
|
|
28
|
+
|
|
29
|
+
content_settings = ndb.JsonProperty()
|
|
30
|
+
|
|
31
|
+
is_archived = ndb.BooleanProperty(required=True)
|
|
32
|
+
|
|
33
|
+
created_datetime = ndb.DateTimeProperty(required=True, auto_now_add=True)
|
|
34
|
+
archived_datetime = ndb.DateTimeProperty(required=False)
|
|
35
|
+
|
|
36
|
+
created_by = ndb.KeyProperty(name="created_by", kind=MerchantUser)
|
|
37
|
+
created_by_username = ndb.StringProperty(required=False)
|
|
38
|
+
|
|
39
|
+
archived_by = ndb.KeyProperty(name="created_by", kind=MerchantUser)
|
|
40
|
+
archived_by_username = ndb.StringProperty(required=False)
|
|
41
|
+
|
|
42
|
+
send = ndb.BooleanProperty(required=True, default=False)
|
|
43
|
+
sent_datetime = ndb.DateTimeProperty(required=False)
|
|
44
|
+
|
|
45
|
+
dict_properties = [
|
|
46
|
+
'title', 'desc', 'send_mode', 'schedule_datetime',
|
|
47
|
+
'content_type', 'content_value', 'content_settings',
|
|
48
|
+
'created_datetime', 'send', 'sent_datetime',
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def merchant_acct_entity(self):
|
|
53
|
+
return MerchantAcct.fetch(self.key.parent().urlsafe())
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def content_type(self):
|
|
57
|
+
if self.content_settings:
|
|
58
|
+
return self.content_settings.get('content_type')
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def content_value(self):
|
|
62
|
+
if self.content_settings:
|
|
63
|
+
return self.content_settings.get('content_value')
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def image_url(self):
|
|
67
|
+
if self.content_settings:
|
|
68
|
+
if self.content_settings.get('content_type')=='image':
|
|
69
|
+
return self.content_settings.get('content_value')
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def text_data(self):
|
|
73
|
+
if self.content_settings:
|
|
74
|
+
if self.content_settings.get('content_type')=='text':
|
|
75
|
+
return self.content_settings.get('content_value')
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def action_link(self):
|
|
79
|
+
if self.content_settings:
|
|
80
|
+
if self.content_settings.get('content_type')=='action_link':
|
|
81
|
+
return self.content_settings.get('content_value')
|
|
82
|
+
|
|
83
|
+
@staticmethod
|
|
84
|
+
def create(merchant_acct, title=None, desc=None, send_mode=None, schedule_datetime=None, content_settings={},
|
|
85
|
+
created_by=None):
|
|
86
|
+
|
|
87
|
+
created_by_username = None
|
|
88
|
+
if is_not_empty(created_by):
|
|
89
|
+
if isinstance(created_by, MerchantUser):
|
|
90
|
+
created_by_username = created_by.username
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
push_notification_setup = PushNotificationSetup(
|
|
94
|
+
parent = merchant_acct.create_ndb_key(),
|
|
95
|
+
title = title,
|
|
96
|
+
desc = desc,
|
|
97
|
+
send_mode = send_mode,
|
|
98
|
+
schedule_datetime = schedule_datetime,
|
|
99
|
+
content_settings = content_settings,
|
|
100
|
+
is_archived = False,
|
|
101
|
+
created_by = created_by.create_ndb_key(),
|
|
102
|
+
created_by_username = created_by_username,
|
|
103
|
+
)
|
|
104
|
+
push_notification_setup.put()
|
|
105
|
+
|
|
106
|
+
return push_notification_setup
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def to_configuration(self):
|
|
110
|
+
return {
|
|
111
|
+
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
def archived(self, archived_by=None):
|
|
115
|
+
|
|
116
|
+
archived_by_username = None
|
|
117
|
+
if is_not_empty(archived_by):
|
|
118
|
+
if isinstance(archived_by, MerchantUser):
|
|
119
|
+
archived_by_username = archived_by.username
|
|
120
|
+
|
|
121
|
+
self.is_archived = True
|
|
122
|
+
self.archived_datetime = datetime.utcnow()
|
|
123
|
+
self.archived_by = archived_by.create_ndb_key()
|
|
124
|
+
self.archived_by_username = archived_by_username
|
|
125
|
+
self.put()
|
|
126
|
+
|
|
127
|
+
def update_as_send(self):
|
|
128
|
+
self.send = True
|
|
129
|
+
self.sent_datetime = datetime.utcnow()
|
|
130
|
+
self.put()
|
|
131
|
+
|
|
132
|
+
@staticmethod
|
|
133
|
+
def list_by_merchant_acct(merchant_acct):
|
|
134
|
+
return PushNotificationSetup.query(ndb.AND(PushNotificationSetup.is_archived!=True), ancestor=merchant_acct.create_ndb_key()).fetch(limit=model_conf.MAX_FETCH_RECORD)
|
|
135
|
+
|
|
136
|
+
@staticmethod
|
|
137
|
+
def list_archived_by_merchant_acct(merchant_acct):
|
|
138
|
+
return PushNotificationSetup.query(ndb.AND(PushNotificationSetup.is_archived==True), ancestor=merchant_acct.create_ndb_key()).fetch(limit=model_conf.MAX_FETCH_RECORD)
|
|
139
|
+
|
|
140
|
+
@staticmethod
|
|
141
|
+
def list(schedule_datetime=datetime.utcnow()):
|
|
142
|
+
result = PushNotificationSetup.query(
|
|
143
|
+
ndb.AND(
|
|
144
|
+
PushNotificationSetup.send==False,
|
|
145
|
+
PushNotificationSetup.schedule_datetime<=schedule_datetime)).fetch(offset=0, limit=conf.MAX_FETCH_RECORD)
|
|
146
|
+
return result
|
|
147
|
+
|
|
148
|
+
class MarketingImage(BaseNModel, DictModel):
|
|
149
|
+
'''
|
|
150
|
+
Merchant Account as ancestor
|
|
151
|
+
'''
|
|
152
|
+
image_label = ndb.StringProperty(required=True)
|
|
153
|
+
image_file_type = ndb.StringProperty(required=True)
|
|
154
|
+
image_file_public_url = ndb.StringProperty(required=True)
|
|
155
|
+
image_file_storage_filename = ndb.StringProperty(required=True)
|
|
156
|
+
|
|
157
|
+
dict_properties = ['image_label', 'image_file_public_url', 'image_file_storage_filename', 'image_file_type']
|
|
158
|
+
|
|
159
|
+
@staticmethod
|
|
160
|
+
def list_by_merchant_acct(merchant_acct):
|
|
161
|
+
result = MarketingImage.query(ancestor=merchant_acct.create_ndb_key()).fetch(limit=conf.MAX_FETCH_RECORD)
|
|
162
|
+
return result
|
|
163
|
+
|
|
164
|
+
@staticmethod
|
|
165
|
+
def upload_file(uploading_file, image_label, merchant_acct, bucket, image_file_type=None):
|
|
166
|
+
file_prefix = random_string(8)
|
|
167
|
+
image_file_storage_filename = 'merchant/'+merchant_acct.key_in_str+'/marketing/'+file_prefix+'-'+uploading_file.filename
|
|
168
|
+
blob = bucket.blob(image_file_storage_filename)
|
|
169
|
+
|
|
170
|
+
logger.debug('image_label=%s', image_label)
|
|
171
|
+
logger.debug('image_file_storage_filename=%s', image_file_storage_filename)
|
|
172
|
+
|
|
173
|
+
blob.upload_from_string(
|
|
174
|
+
uploading_file.read(),
|
|
175
|
+
content_type=uploading_file.content_type
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
uploaded_url = blob.public_url
|
|
179
|
+
|
|
180
|
+
logger.debug('image_file_type=%s', image_file_type)
|
|
181
|
+
|
|
182
|
+
image_file = MarketingImage(
|
|
183
|
+
parent = merchant_acct.create_ndb_key(),
|
|
184
|
+
image_label = image_label,
|
|
185
|
+
image_file_public_url = uploaded_url,
|
|
186
|
+
image_file_storage_filename = image_file_storage_filename,
|
|
187
|
+
image_file_type = image_file_type,
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
image_file.put()
|
|
191
|
+
|
|
192
|
+
return image_file
|
|
193
|
+
|
|
194
|
+
@staticmethod
|
|
195
|
+
def remove_file(image_file, bucket):
|
|
196
|
+
|
|
197
|
+
old_logo_blob = bucket.get_blob(image_file.image_file_storage_filename)
|
|
198
|
+
if old_logo_blob:
|
|
199
|
+
old_logo_blob.delete()
|
|
200
|
+
image_file.delete()
|
|
201
|
+
|
|
202
|
+
class ScheduledPushNotificationHistory(BaseNModel, DictModel):
|
|
203
|
+
push_notification_setup = ndb.KeyProperty(name="push_notification_setup", kind=PushNotificationSetup)
|
|
204
|
+
created_datetime = ndb.DateTimeProperty(required=True, auto_now_add=True)
|
|
205
|
+
send = ndb.BooleanProperty(required=True, default=False)
|
|
206
|
+
scheduled_datetime = ndb.DateTimeProperty(required=True)
|
|
207
|
+
sent_datetime = ndb.DateTimeProperty(required=False)
|
|
208
|
+
|
|
209
|
+
@staticmethod
|
|
210
|
+
def create(push_notification_setup, scheduled_datetime=None):
|
|
211
|
+
if scheduled_datetime is None:
|
|
212
|
+
scheduled_datetime = datetime.utcnow()
|
|
213
|
+
ScheduledPushNotificationHistory(
|
|
214
|
+
push_notification_setup = push_notification_setup.create_ndb_key(),
|
|
215
|
+
scheduled_datetime = scheduled_datetime,
|
|
216
|
+
).put()
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
@staticmethod
|
|
220
|
+
def list(scheduled_datetime=datetime.utcnow()):
|
|
221
|
+
result = ScheduledPushNotificationHistory.query(
|
|
222
|
+
ndb.AND(
|
|
223
|
+
ScheduledPushNotificationHistory.send==False,
|
|
224
|
+
ScheduledPushNotificationHistory.scheduled_datetime<=scheduled_datetime)).fetch(offset=0, limit=conf.MAX_FETCH_RECORD)
|
|
225
|
+
return result
|
|
226
|
+
|
|
@@ -60,6 +60,7 @@ class MerchantAcct(MerchantMin):
|
|
|
60
60
|
dashboard_stat_figure = ndb.JsonProperty()
|
|
61
61
|
currency_code = ndb.StringProperty(required=False, default='MYR')
|
|
62
62
|
locale = ndb.StringProperty(required=False, default='en_MY')
|
|
63
|
+
timezone = ndb.StringProperty(required=False, default='Asia/Kuala_Lumpur')
|
|
63
64
|
api_key = ndb.StringProperty(required=False)
|
|
64
65
|
|
|
65
66
|
account_plan = ndb.JsonProperty()
|
|
@@ -85,8 +86,10 @@ class MerchantAcct(MerchantMin):
|
|
|
85
86
|
stat_figure_update_interval_in_minutes = conf.MERCHANT_STAT_FIGURE_UPDATE_INTERVAL_IN_MINUTES
|
|
86
87
|
stat_figure_update_datetime_format = '%d-%m-%Y %H:%M:%S'
|
|
87
88
|
|
|
88
|
-
dict_properties = ['company_name', 'brand_name', 'contact_name', 'business_reg_no', 'mobile_phone',
|
|
89
|
+
dict_properties = ['company_name', 'brand_name', 'contact_name', 'business_reg_no', 'mobile_phone',
|
|
90
|
+
'office_phone', 'fax_phone', 'email', 'account_code', 'country',
|
|
89
91
|
'registered_datetime', 'modified_datetime', 'plan_start_date', 'plan_end_date', 'currency_code',
|
|
92
|
+
'timezone',
|
|
90
93
|
'published_program_configuration', 'published_voucher_configuration', 'membership_configuration',
|
|
91
94
|
'tier_membership_configuration', 'prepaid_configuration', 'lucky_draw_configuration', 'product_modifier_configuration',
|
|
92
95
|
'dashboard_stat_figure', 'program_settings', 'is_tier_membership_configured', 'website',
|
|
@@ -224,8 +227,7 @@ class MerchantAcct(MerchantMin):
|
|
|
224
227
|
@staticmethod
|
|
225
228
|
def update_details(merchant_acct, company_name=None, brand_name=None, business_reg_no=None, contact_name=None,
|
|
226
229
|
email=None, mobile_phone=None, office_phone=None, currency_code=None,
|
|
227
|
-
|
|
228
|
-
country=None, website=None):
|
|
230
|
+
country=None, timezone=None, website=None):
|
|
229
231
|
|
|
230
232
|
|
|
231
233
|
|
|
@@ -238,7 +240,9 @@ class MerchantAcct(MerchantMin):
|
|
|
238
240
|
merchant_acct.office_phone = office_phone
|
|
239
241
|
merchant_acct.currency_code = currency_code
|
|
240
242
|
merchant_acct.country = country
|
|
243
|
+
merchant_acct.timezone = timezone
|
|
241
244
|
merchant_acct.website = website
|
|
245
|
+
|
|
242
246
|
merchant_acct.put()
|
|
243
247
|
|
|
244
248
|
@staticmethod
|
|
@@ -882,7 +886,7 @@ class MerchantAcct(MerchantMin):
|
|
|
882
886
|
@staticmethod
|
|
883
887
|
def create(company_name=None, brand_name=None, contact_name=None, email=None, mobile_phone=None, office_phone=None,
|
|
884
888
|
plan_start_date=None, plan_end_date=None,
|
|
885
|
-
account_code=None, currency_code=None, country=None, website=None,
|
|
889
|
+
account_code=None, currency_code=None, country=None, timezone=None, website=None,
|
|
886
890
|
product_package=None,loyalty_package=None, outlet_limit=1
|
|
887
891
|
):
|
|
888
892
|
|
|
@@ -906,7 +910,8 @@ class MerchantAcct(MerchantMin):
|
|
|
906
910
|
plan_start_date = plan_start_date,
|
|
907
911
|
plan_end_date = plan_end_date,
|
|
908
912
|
currency_code = currency_code,
|
|
909
|
-
country = country,
|
|
913
|
+
country = country,
|
|
914
|
+
timezone = timezone,
|
|
910
915
|
website = website,
|
|
911
916
|
api_key = random_string(24),
|
|
912
917
|
program_settings = MerchantAcct.default_program_settings(),
|
|
@@ -925,7 +930,7 @@ class MerchantAcct(MerchantMin):
|
|
|
925
930
|
@staticmethod
|
|
926
931
|
def update(merchant_acct, company_name=None, brand_name=None, contact_name=None, email=None, mobile_phone=None, office_phone=None,
|
|
927
932
|
plan_start_date=None, plan_end_date=None,
|
|
928
|
-
currency_code=None, country=None, website=None,
|
|
933
|
+
currency_code=None, country=None, timezone=None, website=None,
|
|
929
934
|
product_package=None,loyalty_package=None, outlet_limit=1,
|
|
930
935
|
):
|
|
931
936
|
|
|
@@ -945,6 +950,7 @@ class MerchantAcct(MerchantMin):
|
|
|
945
950
|
merchant_acct.plan_end_date = plan_end_date
|
|
946
951
|
merchant_acct.currency_code = currency_code
|
|
947
952
|
merchant_acct.country = country
|
|
953
|
+
merchant_acct.timezone = timezone
|
|
948
954
|
merchant_acct.website = website
|
|
949
955
|
merchant_acct.account_plan = account_plan
|
|
950
956
|
|
|
@@ -327,7 +327,8 @@ class BaseNModel(DictModel, NDBModel):
|
|
|
327
327
|
if more:
|
|
328
328
|
return search_results, next_cursor.to_websafe_string().decode('utf-8')
|
|
329
329
|
else:
|
|
330
|
-
return search_results, 'None'
|
|
330
|
+
#return search_results, 'None'
|
|
331
|
+
return search_results, None
|
|
331
332
|
|
|
332
333
|
else:
|
|
333
334
|
search_results = query.fetch(limit=limit, offset=offset, keys_only=keys_only)
|
{trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/redemption_catalogue_models.py
RENAMED
|
@@ -43,12 +43,14 @@ class RedemptionCatalogue(BaseNModel, DictModel):
|
|
|
43
43
|
image_storage_filename = ndb.StringProperty(required=False)
|
|
44
44
|
image_public_url = ndb.StringProperty(required=False)
|
|
45
45
|
|
|
46
|
+
loyalty_package = ndb.StringProperty(required=False, default=program_conf.LOYALTY_PACKAGE_SCALE)
|
|
47
|
+
|
|
46
48
|
dict_properties = [
|
|
47
49
|
"label","desc","completed_status","start_date","end_date","created_datetime",
|
|
48
50
|
"redeem_reward_format","catalogue_settings", "image_storage_filename", "image_public_url",
|
|
49
51
|
"exclusive_tags_list", "exclusive_memberships_list", "exclusive_tier_memberships_list",
|
|
50
52
|
"completed_prograss_in_percentage","completed_status_index", "catalogue_items",
|
|
51
|
-
"is_enabled", "is_disabled", "is_archived", "is_published",
|
|
53
|
+
"is_enabled", "is_disabled", "is_archived", "is_published", "loyalty_package",
|
|
52
54
|
]
|
|
53
55
|
|
|
54
56
|
@property
|
|
@@ -92,14 +94,15 @@ class RedemptionCatalogue(BaseNModel, DictModel):
|
|
|
92
94
|
|
|
93
95
|
@property
|
|
94
96
|
def completed_prograss_in_percentage(self):
|
|
95
|
-
return program_conf.redemption_catalogue_completed_progress_percentage(self.completed_status)
|
|
97
|
+
return program_conf.redemption_catalogue_completed_progress_percentage(self.completed_status, self.loyalty_package)
|
|
96
98
|
|
|
97
99
|
@property
|
|
98
100
|
def completed_status_index(self):
|
|
99
101
|
return program_conf.get_redemption_catalogue_completed_status_index(self.completed_status)
|
|
100
102
|
|
|
101
103
|
@staticmethod
|
|
102
|
-
def create(merchant_acct, label=None, desc=None, start_date=None, end_date=None, redeem_reward_format=None,
|
|
104
|
+
def create(merchant_acct, label=None, desc=None, start_date=None, end_date=None, redeem_reward_format=None,
|
|
105
|
+
created_by=None, loyalty_package=program_conf.LOYALTY_PACKAGE_SCALE):
|
|
103
106
|
|
|
104
107
|
created_by_username = None
|
|
105
108
|
if is_not_empty(created_by):
|
|
@@ -117,6 +120,7 @@ class RedemptionCatalogue(BaseNModel, DictModel):
|
|
|
117
120
|
created_by_username = created_by_username,
|
|
118
121
|
completed_status = program_conf.REDEMPTION_CATALOGUE_STATUS_DEFINED_CATALOGUE,
|
|
119
122
|
catalogue_settings = {},
|
|
123
|
+
loyalty_package = loyalty_package,
|
|
120
124
|
)
|
|
121
125
|
|
|
122
126
|
redemption_catalogue.put()
|
|
@@ -124,7 +128,8 @@ class RedemptionCatalogue(BaseNModel, DictModel):
|
|
|
124
128
|
return redemption_catalogue
|
|
125
129
|
|
|
126
130
|
@staticmethod
|
|
127
|
-
def update(redemption_catalogue, label=None, desc=None, start_date=None, end_date=None,
|
|
131
|
+
def update(redemption_catalogue, label=None, desc=None, start_date=None, end_date=None,
|
|
132
|
+
redeem_reward_format=None, modified_by=None, loyalty_package=program_conf.LOYALTY_PACKAGE_SCALE):
|
|
128
133
|
|
|
129
134
|
modified_by_username = None
|
|
130
135
|
if is_not_empty(modified_by):
|
|
@@ -140,6 +145,7 @@ class RedemptionCatalogue(BaseNModel, DictModel):
|
|
|
140
145
|
|
|
141
146
|
redemption_catalogue.modified_by = modified_by.create_ndb_key()
|
|
142
147
|
redemption_catalogue.modified_by_username = modified_by_username
|
|
148
|
+
redemption_catalogue.loyalty_package = loyalty_package
|
|
143
149
|
|
|
144
150
|
redemption_catalogue.put()
|
|
145
151
|
|
|
@@ -3,10 +3,9 @@ Created on 20 Apr 2020
|
|
|
3
3
|
|
|
4
4
|
@author: jacklok
|
|
5
5
|
'''
|
|
6
|
-
from trexmodel import conf as model_conf
|
|
6
|
+
from trexmodel import conf as model_conf, conf
|
|
7
7
|
from google.cloud import ndb
|
|
8
8
|
from trexmodel.models.datastore.ndb_models import BaseNModel, DictModel
|
|
9
|
-
|
|
10
9
|
|
|
11
10
|
class Country(BaseNModel, DictModel):
|
|
12
11
|
cnty_id = ndb.IntegerProperty(required=True)
|
|
@@ -158,9 +157,25 @@ class Tagging(BaseNModel, DictModel):
|
|
|
158
157
|
@classmethod
|
|
159
158
|
def get_by_label(cls, parent, label):
|
|
160
159
|
return cls.query(ndb.AND(cls.label==label), ancestor=parent).fetch(limit=1)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
'''
|
|
164
|
+
class ScheduledProjectExecutionHistory(BaseNModel, DictModel):
|
|
165
|
+
merchant_acct = ndb.KeyProperty(name="merchant_acct", kind=MerchantAcct)
|
|
166
|
+
merchant_program = ndb.KeyProperty(name="merchant_program", kind=MerchantProgram)
|
|
167
|
+
created_datetime = ndb.DateTimeProperty(required=True, auto_now_add=True)
|
|
161
168
|
|
|
162
|
-
|
|
163
|
-
|
|
169
|
+
@staticmethod
|
|
170
|
+
def create(merchant_acct, merchant_program):
|
|
171
|
+
ScheduledProjectExecutionHistory(
|
|
172
|
+
merchant_acct = merchant_acct.create_ndb_key(),
|
|
173
|
+
merchant_program = merchant_program.create_ndb_key(),
|
|
174
|
+
).put()
|
|
175
|
+
|
|
176
|
+
'''
|
|
177
|
+
|
|
178
|
+
|
|
164
179
|
|
|
165
180
|
|
|
166
181
|
|
|
@@ -45,6 +45,8 @@ class UserMin(BaseNModel, DictModel, UserMixin):
|
|
|
45
45
|
demo_account = ndb.BooleanProperty(required=False, default=False)
|
|
46
46
|
deleted = ndb.BooleanProperty(required=False, default=False)
|
|
47
47
|
|
|
48
|
+
|
|
49
|
+
|
|
48
50
|
dict_properties = ['user_id', 'name', 'email', 'gravatar_url', 'active', 'locked', 'lock_expiry_datetime']
|
|
49
51
|
|
|
50
52
|
@classmethod
|
|
@@ -352,11 +354,13 @@ class User(UserBase):
|
|
|
352
354
|
redeem_pin = ndb.StringProperty(required=False)
|
|
353
355
|
status = ndb.StringProperty(required=False, default=USER_STATUS_ANONYMOUS)
|
|
354
356
|
new_message_count = ndb.IntegerProperty(required=False, default=0)
|
|
357
|
+
device_details = ndb.JsonProperty()
|
|
358
|
+
|
|
355
359
|
dict_properties = [
|
|
356
360
|
'mobile_phone', 'email', 'password', 'name', 'birth_date', 'gender',
|
|
357
361
|
'reference_code', 'country', 'state', 'city', 'postcode',
|
|
358
|
-
'address', 'redeem_pin', 'new_message_count', 'status'
|
|
359
|
-
|
|
362
|
+
'address', 'redeem_pin', 'new_message_count', 'status',
|
|
363
|
+
'device_details',
|
|
360
364
|
]
|
|
361
365
|
|
|
362
366
|
#unique_attributes = 'email,username'
|
|
@@ -364,7 +368,7 @@ class User(UserBase):
|
|
|
364
368
|
audit_properties = [
|
|
365
369
|
'mobile_phone', 'email', 'password', 'name', 'birth_date', 'gender',
|
|
366
370
|
'reference_code', 'country', 'state', 'city', 'postcode',
|
|
367
|
-
'address', 'redeem_pin', 'status'
|
|
371
|
+
'address', 'redeem_pin', 'status', 'device_details',
|
|
368
372
|
|
|
369
373
|
]
|
|
370
374
|
|
|
@@ -405,7 +409,45 @@ class User(UserBase):
|
|
|
405
409
|
"""Returns `True` if the user is active."""
|
|
406
410
|
logger.info('calling is_active')
|
|
407
411
|
return self.active
|
|
408
|
-
|
|
412
|
+
|
|
413
|
+
def update_device_details(self, platform, device_token):
|
|
414
|
+
if self.device_details:
|
|
415
|
+
found_device_details_list_by_platform = self.device_details.get(platform)
|
|
416
|
+
if found_device_details_list_by_platform:
|
|
417
|
+
is_found = False
|
|
418
|
+
for device_details_by_platform in found_device_details_list_by_platform:
|
|
419
|
+
device_token_by_platform = device_details_by_platform.get('device_token')
|
|
420
|
+
if device_token_by_platform:
|
|
421
|
+
device_details_by_platform['last_updated_datetime'] = datetime.utcnow().strftime("%d-%m-%Y %H:%M:%S")
|
|
422
|
+
is_found = True
|
|
423
|
+
break
|
|
424
|
+
|
|
425
|
+
if is_found == False:
|
|
426
|
+
found_device_details_list_by_platform.append(
|
|
427
|
+
{
|
|
428
|
+
'device_token' : device_token,
|
|
429
|
+
'last_updated_datetime' : datetime.utcnow().strftime("%d-%m-%Y %H:%M:%S"),
|
|
430
|
+
}
|
|
431
|
+
)
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
else:
|
|
435
|
+
self.device_details[platform] = [
|
|
436
|
+
{
|
|
437
|
+
'device_token' : device_token,
|
|
438
|
+
'last_updated_datetime' : datetime.utcnow().strftime("%d-%m-%Y %H:%M:%S"),
|
|
439
|
+
}
|
|
440
|
+
]
|
|
441
|
+
else:
|
|
442
|
+
self.device_details = {
|
|
443
|
+
platform : [
|
|
444
|
+
{
|
|
445
|
+
'device_token' : device_token,
|
|
446
|
+
'last_updated_datetime' : datetime.utcnow().strftime("%d-%m-%Y %H:%M:%S"),
|
|
447
|
+
}
|
|
448
|
+
]
|
|
449
|
+
}
|
|
450
|
+
self.put()
|
|
409
451
|
|
|
410
452
|
class DeletedUser(User):
|
|
411
453
|
deleted_datetime = ndb.DateTimeProperty(required=False, auto_now_add=True)
|
|
@@ -291,7 +291,13 @@ REDEMPTION_CATALOGUE_STATUS = (
|
|
|
291
291
|
REDEMPTION_CATALOGUE_STATUS_PUBLISH
|
|
292
292
|
)
|
|
293
293
|
|
|
294
|
-
|
|
294
|
+
LITE_REDEMPTION_CATALOGUE_STATUS = (
|
|
295
|
+
REDEMPTION_CATALOGUE_STATUS_DEFINED_CATALOGUE,
|
|
296
|
+
REDEMPTION_CATALOGUE_STATUS_DEFINE_ITEM,
|
|
297
|
+
REDEMPTION_CATALOGUE_STATUS_UPLOAD_MATERIAL,
|
|
298
|
+
REDEMPTION_CATALOGUE_STATUS_REVIEW,
|
|
299
|
+
REDEMPTION_CATALOGUE_STATUS_PUBLISH
|
|
300
|
+
)
|
|
295
301
|
|
|
296
302
|
|
|
297
303
|
|
|
@@ -544,7 +550,10 @@ def lucky_draw_program_completed_progress_percentage(completed_status):
|
|
|
544
550
|
print('lucky_draw_program_completed_progress_percentage: completed_status_index(%s)=%s'% (completed_status,completed_status_index))
|
|
545
551
|
return int((completed_status_index+1)/len(LUCKY_DRAW_PROGRAM_STATUS) * 100)
|
|
546
552
|
|
|
547
|
-
def redemption_catalogue_completed_progress_percentage(completed_status):
|
|
553
|
+
def redemption_catalogue_completed_progress_percentage(completed_status, loyalty_package):
|
|
548
554
|
completed_status_index = get_redemption_catalogue_completed_status_index(completed_status)
|
|
549
555
|
print('redemption_catalogue_completed_progress_percentage: completed_status_index(%s)=%s'% (completed_status,completed_status_index))
|
|
550
|
-
|
|
556
|
+
if loyalty_package == LOYALTY_PACKAGE_LITE:
|
|
557
|
+
return int((completed_status_index+1)/len(LITE_REDEMPTION_CATALOGUE_STATUS) * 100)
|
|
558
|
+
else:
|
|
559
|
+
return int((completed_status_index+1)/len(REDEMPTION_CATALOGUE_STATUS) * 100)
|
|
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.17 → trex-model-1.2.19}/trexmodel/models/datastore/customer_model_helpers.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
|
|
File without changes
|
|
File without changes
|
{trex-model-1.2.17 → trex-model-1.2.19}/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
|