trex-model 1.4.4__tar.gz → 1.4.6__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.4.4 → trex-model-1.4.6}/PKG-INFO +1 -1
- {trex-model-1.4.4 → trex-model-1.4.6}/setup.py +1 -1
- {trex-model-1.4.4 → trex-model-1.4.6}/trex_model.egg-info/PKG-INFO +1 -1
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/conf.py +8 -7
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/marketing_models.py +244 -2
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/merchant_models.py +49 -74
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/message_model_helper.py +32 -19
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/message_models.py +38 -4
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/product_models.py +7 -6
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/user_models.py +21 -8
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/voucher_models.py +4 -1
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/merchant_helpers.py +7 -1
- {trex-model-1.4.4 → trex-model-1.4.6}/LICENSE +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/MANIFEST.in +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/README.md +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/setup.cfg +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trex_model.egg-info/SOURCES.txt +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trex_model.egg-info/dependency_links.txt +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trex_model.egg-info/requires.txt +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trex_model.egg-info/top_level.txt +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/__init__.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/__init__.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/__init__.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/admin_models.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/analytic_models.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/app_models.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/coporate_models.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/customer_model_helpers.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/customer_models.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/fb_subsriber_models.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/import_models.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/inventory_model.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/loyalty_models.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/lucky_draw_models.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/membership_models.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/model_decorators.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/ndb_models.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/pos_models.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/prepaid_models.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/program_models.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/rating_models.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/recruit_models.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/redeem_models.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/redemption_catalogue_models.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/referral_program_model.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/reward_model_helpers.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/reward_models.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/spending_base_program_model.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/system_models.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/task_models.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/test_models.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/transaction_models.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/model_decorator.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/prepaid_helpers.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/pos_conf.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/program_conf.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/utils/__init__.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/utils/gcloud/__init__.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/utils/gcloud/datastore_util.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/utils/model/__init__.py +0 -0
- {trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/utils/model/model_util.py +0 -0
|
@@ -28,13 +28,14 @@ DATASTORE_CREDENTIAL_PATH = os.path.abspath(os.path.dirnam
|
|
|
28
28
|
|
|
29
29
|
MERCHANT_STAT_FIGURE_UPDATE_INTERVAL_IN_MINUTES = os.environ.get('MERCHANT_STAT_FIGURE_UPDATE_INTERVAL_IN_MINUTES') or 60
|
|
30
30
|
|
|
31
|
-
MESSAGE_CATEGORY_ANNOUNCEMENT
|
|
32
|
-
MESSAGE_CATEGORY_ALERT
|
|
33
|
-
MESSAGE_CATEGORY_PROMOTION
|
|
34
|
-
MESSAGE_CATEGORY_SURVEY
|
|
35
|
-
MESSAGE_CATEGORY_SYSTEM
|
|
36
|
-
MESSAGE_CATEGORY_REWARD
|
|
37
|
-
MESSAGE_CATEGORY_REDEEM
|
|
31
|
+
MESSAGE_CATEGORY_ANNOUNCEMENT = 'announcement'
|
|
32
|
+
MESSAGE_CATEGORY_ALERT = 'alert'
|
|
33
|
+
MESSAGE_CATEGORY_PROMOTION = 'promotion'
|
|
34
|
+
MESSAGE_CATEGORY_SURVEY = 'survey'
|
|
35
|
+
MESSAGE_CATEGORY_SYSTEM = 'system'
|
|
36
|
+
MESSAGE_CATEGORY_REWARD = 'reward'
|
|
37
|
+
MESSAGE_CATEGORY_REDEEM = 'redeem'
|
|
38
|
+
MESSAGE_CATEGORY_REDEMPTION_CATALOGUE = 'redemption_catalogue'
|
|
38
39
|
|
|
39
40
|
MESSAGE_CATEGORIES = (MESSAGE_CATEGORY_ANNOUNCEMENT, MESSAGE_CATEGORY_ALERT, MESSAGE_CATEGORY_PROMOTION, MESSAGE_CATEGORY_SURVEY, MESSAGE_CATEGORY_SYSTEM, MESSAGE_CATEGORY_REWARD, MESSAGE_CATEGORY_REDEEM)
|
|
40
41
|
|
|
@@ -9,9 +9,11 @@ from trexmodel.models.datastore.merchant_models import MerchantUser,\
|
|
|
9
9
|
MerchantAcct
|
|
10
10
|
from trexlib.utils.string_util import is_not_empty, random_string
|
|
11
11
|
from datetime import datetime
|
|
12
|
-
from trexconf import conf
|
|
12
|
+
from trexconf import conf, program_conf
|
|
13
13
|
import trexmodel.conf as model_conf
|
|
14
14
|
import logging
|
|
15
|
+
from _datetime import timedelta
|
|
16
|
+
from trexconf.program_conf import MERCHANT_NEWS_STATUS_PUBLISH
|
|
15
17
|
|
|
16
18
|
logger = logging.getLogger('model')
|
|
17
19
|
|
|
@@ -271,4 +273,244 @@ class ScheduledPushNotificationHistory(BaseNModel, DictModel):
|
|
|
271
273
|
ndb.AND(
|
|
272
274
|
ScheduledPushNotificationHistory.scheduled_datetime<=scheduled_datetime)).count(limit=conf.MAX_FETCH_RECORD)
|
|
273
275
|
|
|
274
|
-
|
|
276
|
+
class MerchantNewsFile(BaseNModel, DictModel):
|
|
277
|
+
'''
|
|
278
|
+
Merchant Account as ancestor
|
|
279
|
+
'''
|
|
280
|
+
label = ndb.StringProperty(required=True)
|
|
281
|
+
desc = ndb.StringProperty(required=False)
|
|
282
|
+
news_text = ndb.StringProperty(required=False)
|
|
283
|
+
|
|
284
|
+
news_file_type = ndb.StringProperty(required=False)
|
|
285
|
+
news_file_public_url = ndb.StringProperty(required=False)
|
|
286
|
+
news_file_storage_filename = ndb.StringProperty(required=False)
|
|
287
|
+
|
|
288
|
+
completed_status = ndb.StringProperty(required=True, choices=set(program_conf.MERCHANT_NEWS_STATUS))
|
|
289
|
+
|
|
290
|
+
start_date = ndb.DateProperty(required=True)
|
|
291
|
+
end_date = ndb.DateProperty(required=True)
|
|
292
|
+
|
|
293
|
+
enabled = ndb.BooleanProperty(default=True)
|
|
294
|
+
|
|
295
|
+
is_archived = ndb.BooleanProperty(default=False)
|
|
296
|
+
|
|
297
|
+
created_datetime = ndb.DateTimeProperty(required=True, auto_now_add=True)
|
|
298
|
+
modified_datetime = ndb.DateTimeProperty(required=False)
|
|
299
|
+
published_datetime = ndb.DateTimeProperty(required=False)
|
|
300
|
+
archived_datetime = ndb.DateTimeProperty(required=False)
|
|
301
|
+
|
|
302
|
+
created_by = ndb.KeyProperty(name="created_by", kind=MerchantUser)
|
|
303
|
+
created_by_username = ndb.StringProperty(required=False)
|
|
304
|
+
|
|
305
|
+
modified_by = ndb.KeyProperty(name="modified_by", kind=MerchantUser)
|
|
306
|
+
modified_by_username = ndb.StringProperty(required=False)
|
|
307
|
+
|
|
308
|
+
published_by = ndb.KeyProperty(name="published_by", kind=MerchantUser)
|
|
309
|
+
published_by_username = ndb.StringProperty(required=False)
|
|
310
|
+
|
|
311
|
+
archived_by = ndb.KeyProperty(name="archived_by", kind=MerchantUser)
|
|
312
|
+
archived_by_username = ndb.StringProperty(required=False)
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
dict_properties = ['image_url', 'completed_progress_in_percentage','is_published', 'is_enabled',
|
|
316
|
+
'label', 'desc', 'news_text', 'start_date', 'end_date', 'enabled', 'is_archived',
|
|
317
|
+
'completed_status']
|
|
318
|
+
|
|
319
|
+
@property
|
|
320
|
+
def merchant_acct(self):
|
|
321
|
+
return MerchantAcct.fetch(self.key.parent().urlsafe())
|
|
322
|
+
|
|
323
|
+
@property
|
|
324
|
+
def image_url(self):
|
|
325
|
+
if self.news_file_public_url:
|
|
326
|
+
return self.news_file_public_url
|
|
327
|
+
else:
|
|
328
|
+
return conf.MERCHANT_NEWS_DEFAULT_IMAGE
|
|
329
|
+
|
|
330
|
+
@property
|
|
331
|
+
def completed_progress_in_percentage(self):
|
|
332
|
+
|
|
333
|
+
return program_conf.merchant_news_completed_progress_percentage(self.completed_status)
|
|
334
|
+
|
|
335
|
+
@property
|
|
336
|
+
def is_published(self):
|
|
337
|
+
return self.completed_status == MERCHANT_NEWS_STATUS_PUBLISH
|
|
338
|
+
|
|
339
|
+
@property
|
|
340
|
+
def is_enabled(self):
|
|
341
|
+
return self.enabled
|
|
342
|
+
|
|
343
|
+
@staticmethod
|
|
344
|
+
def list_by_merchant_acct(merchant_acct):
|
|
345
|
+
result = MerchantNewsFile.query(ndb.AND(MerchantNewsFile.is_archived==False), ancestor=merchant_acct.create_ndb_key()).fetch(limit=conf.MAX_FETCH_RECORD)
|
|
346
|
+
return result
|
|
347
|
+
|
|
348
|
+
@staticmethod
|
|
349
|
+
def list_archived_by_merchant_acct(merchant_acct):
|
|
350
|
+
return MerchantNewsFile.query(ndb.AND(MerchantNewsFile.is_archived==True), ancestor=merchant_acct.create_ndb_key()).fetch(limit=model_conf.MAX_FETCH_RECORD)
|
|
351
|
+
|
|
352
|
+
@staticmethod
|
|
353
|
+
def create(merchant_acct, label=None, desc=None, news_text=None,
|
|
354
|
+
start_date=None, end_date=None, created_by=None):
|
|
355
|
+
|
|
356
|
+
created_by_username = None
|
|
357
|
+
if is_not_empty(created_by):
|
|
358
|
+
if isinstance(created_by, MerchantUser):
|
|
359
|
+
created_by_username = created_by.username
|
|
360
|
+
|
|
361
|
+
news_file = MerchantNewsFile(
|
|
362
|
+
parent = merchant_acct.create_ndb_key(),
|
|
363
|
+
label = label,
|
|
364
|
+
desc = desc,
|
|
365
|
+
news_text = news_text,
|
|
366
|
+
start_date = start_date,
|
|
367
|
+
end_date = end_date,
|
|
368
|
+
created_by = created_by.create_ndb_key(),
|
|
369
|
+
created_by_username = created_by_username,
|
|
370
|
+
created_datetime = datetime.utcnow(),
|
|
371
|
+
completed_status = program_conf.MERCHANT_NEWS_STATUS_BASE,
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
news_file.put()
|
|
375
|
+
|
|
376
|
+
return news_file
|
|
377
|
+
|
|
378
|
+
@staticmethod
|
|
379
|
+
def update(merchant_news, label=None, desc=None, news_text=None,
|
|
380
|
+
start_date=None, end_date=None, modified_by=None):
|
|
381
|
+
|
|
382
|
+
modified_by_username = None
|
|
383
|
+
if is_not_empty(modified_by):
|
|
384
|
+
if isinstance(modified_by, MerchantUser):
|
|
385
|
+
modified_by_username = modified_by.username
|
|
386
|
+
|
|
387
|
+
merchant_news.label = label
|
|
388
|
+
merchant_news.desc = desc
|
|
389
|
+
merchant_news.news_text = news_text
|
|
390
|
+
merchant_news.start_date = start_date
|
|
391
|
+
merchant_news.end_date = end_date
|
|
392
|
+
merchant_news.completed_status = program_conf.MERCHANT_NEWS_STATUS_BASE
|
|
393
|
+
merchant_news.modified_by = modified_by
|
|
394
|
+
merchant_news.modified_by_username = modified_by_username
|
|
395
|
+
merchant_news.modified_datetime = datetime.utcnow()
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
merchant_news.put()
|
|
399
|
+
|
|
400
|
+
@staticmethod
|
|
401
|
+
def upload_file(merchant_news, uploading_file, merchant_acct, bucket, news_file_type=None):
|
|
402
|
+
file_prefix = random_string(8)
|
|
403
|
+
news_file_storage_filename = 'merchant/'+merchant_acct.key_in_str+'/news/'+file_prefix+'-'+uploading_file.filename
|
|
404
|
+
blob = bucket.blob(news_file_storage_filename)
|
|
405
|
+
|
|
406
|
+
logger.debug('news_file_storage_filename=%s', news_file_storage_filename)
|
|
407
|
+
|
|
408
|
+
blob.upload_from_string(
|
|
409
|
+
uploading_file.read(),
|
|
410
|
+
content_type=uploading_file.content_type
|
|
411
|
+
)
|
|
412
|
+
|
|
413
|
+
uploaded_url = blob.public_url
|
|
414
|
+
|
|
415
|
+
logger.debug('uploaded_url=%s', uploaded_url)
|
|
416
|
+
logger.debug('news_file_type=%s', news_file_type)
|
|
417
|
+
|
|
418
|
+
if is_not_empty(merchant_news.news_file_storage_filename):
|
|
419
|
+
old_logo_blob = bucket.get_blob(merchant_news.news_file_storage_filename)
|
|
420
|
+
if old_logo_blob:
|
|
421
|
+
old_logo_blob.delete()
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
merchant_news.news_file_public_url = uploaded_url
|
|
425
|
+
merchant_news.news_file_storage_filename = news_file_storage_filename
|
|
426
|
+
merchant_news.news_file_type = news_file_type
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
merchant_news.put()
|
|
430
|
+
|
|
431
|
+
return merchant_news
|
|
432
|
+
|
|
433
|
+
@staticmethod
|
|
434
|
+
def update_news_material_uploaded(merchant_news, modified_by=None):
|
|
435
|
+
|
|
436
|
+
modified_by_username = None
|
|
437
|
+
|
|
438
|
+
if is_not_empty(modified_by):
|
|
439
|
+
if isinstance(modified_by, MerchantUser):
|
|
440
|
+
modified_by_username = modified_by.username
|
|
441
|
+
|
|
442
|
+
merchant_news.completed_status = program_conf.MERCHANT_NEWS_STATUS_UPLOAD_MATERIAL
|
|
443
|
+
merchant_news.modified_by = modified_by.create_ndb_key()
|
|
444
|
+
merchant_news.modified_by_username = modified_by_username
|
|
445
|
+
merchant_news.modified_datetime = datetime.utcnow()
|
|
446
|
+
|
|
447
|
+
merchant_news.put()
|
|
448
|
+
|
|
449
|
+
return merchant_news
|
|
450
|
+
|
|
451
|
+
@staticmethod
|
|
452
|
+
def remove_file(news_file, bucket):
|
|
453
|
+
|
|
454
|
+
old_logo_blob = bucket.get_blob(news_file.news_file_storage_filename)
|
|
455
|
+
if old_logo_blob:
|
|
456
|
+
old_logo_blob.delete()
|
|
457
|
+
news_file.delete()
|
|
458
|
+
|
|
459
|
+
def archived(self, archived_by=None):
|
|
460
|
+
|
|
461
|
+
archived_by_username = None
|
|
462
|
+
if is_not_empty(archived_by):
|
|
463
|
+
if isinstance(archived_by, MerchantUser):
|
|
464
|
+
archived_by_username = archived_by.username
|
|
465
|
+
|
|
466
|
+
self.is_archived = True
|
|
467
|
+
self.archived_datetime = datetime.utcnow()
|
|
468
|
+
self.archived_by = archived_by.create_ndb_key()
|
|
469
|
+
self.archived_by_username = archived_by_username
|
|
470
|
+
self.put()
|
|
471
|
+
|
|
472
|
+
merchant_acct = self.merchant_acct
|
|
473
|
+
merchant_acct.remove_merchant_news(self.key_in_str)
|
|
474
|
+
|
|
475
|
+
def to_configuration(self):
|
|
476
|
+
return {
|
|
477
|
+
'merchant_news_key' : self.key_in_str,
|
|
478
|
+
'image_url' : self.image_url,
|
|
479
|
+
'label' : self.label,
|
|
480
|
+
'content' : self.news_text,
|
|
481
|
+
'start_datetime' : self.start_date.strftime('%d-%m-%Y %H:%M:%S'),
|
|
482
|
+
'end_datetime' : self.end_date.strftime('%d-%m-%Y %H:%M:%S'),
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
def publish(self, published_by=None):
|
|
486
|
+
|
|
487
|
+
published_by_username = None
|
|
488
|
+
if is_not_empty(published_by):
|
|
489
|
+
if isinstance(published_by, MerchantUser):
|
|
490
|
+
published_by_username = published_by.username
|
|
491
|
+
|
|
492
|
+
self.completed_status = program_conf.MERCHANT_NEWS_STATUS_PUBLISH
|
|
493
|
+
self.published_by = published_by.create_ndb_key()
|
|
494
|
+
self.published_by_username = published_by_username
|
|
495
|
+
self.published_datetime = datetime.utcnow()
|
|
496
|
+
self.put()
|
|
497
|
+
|
|
498
|
+
merchant_acct = self.merchant_acct
|
|
499
|
+
merchant_acct.add_merchant_news(self.to_configuration())
|
|
500
|
+
|
|
501
|
+
@staticmethod
|
|
502
|
+
def disable_news(merchant_news):
|
|
503
|
+
merchant_news.enabled = False
|
|
504
|
+
merchant_news.put()
|
|
505
|
+
|
|
506
|
+
merchant_acct = merchant_news.merchant_acct
|
|
507
|
+
merchant_acct.remove_merchant_news(merchant_news.key_in_str)
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
@staticmethod
|
|
511
|
+
def enable_news(merchant_news):
|
|
512
|
+
merchant_news.enabled = True
|
|
513
|
+
merchant_news.put()
|
|
514
|
+
|
|
515
|
+
merchant_acct = merchant_news.merchant_acct
|
|
516
|
+
merchant_acct.add_merchant_news(merchant_news.to_configuration())
|
|
@@ -69,6 +69,7 @@ class MerchantAcct(MerchantMin):
|
|
|
69
69
|
published_referral_program_configuration = ndb.JsonProperty()
|
|
70
70
|
published_voucher_configuration = ndb.JsonProperty()
|
|
71
71
|
published_redemption_catalogue_configuration = ndb.JsonProperty()
|
|
72
|
+
published_news_configuration = ndb.JsonProperty()
|
|
72
73
|
|
|
73
74
|
membership_configuration = ndb.JsonProperty()
|
|
74
75
|
tier_membership_configuration = ndb.JsonProperty()
|
|
@@ -91,11 +92,11 @@ class MerchantAcct(MerchantMin):
|
|
|
91
92
|
'registered_datetime', 'modified_datetime', 'plan_start_date', 'plan_end_date', 'currency_code',
|
|
92
93
|
'timezone', 'effective_referral_program_count',
|
|
93
94
|
'published_program_configuration', 'published_referral_program_configuration',
|
|
94
|
-
'published_voucher_configuration', 'membership_configuration',
|
|
95
|
+
'published_voucher_configuration', 'published_news_configuration', 'membership_configuration',
|
|
95
96
|
'tier_membership_configuration', 'prepaid_configuration', 'lucky_draw_configuration', 'product_modifier_configuration',
|
|
96
97
|
'dashboard_stat_figure', 'program_settings', 'is_tier_membership_configured', 'website',
|
|
97
98
|
'product_package', 'loyalty_package','account_plan','outlet_count', 'outlet_limit',
|
|
98
|
-
'published_redemption_catalogue_configuration',
|
|
99
|
+
'published_redemption_catalogue_configuration','logo_public_url'
|
|
99
100
|
]
|
|
100
101
|
|
|
101
102
|
|
|
@@ -636,7 +637,51 @@ class MerchantAcct(MerchantMin):
|
|
|
636
637
|
self.published_voucher_configuration['vouchers'] = new_vouchers_list
|
|
637
638
|
self.published_voucher_configuration['count'] = len(new_vouchers_list)
|
|
638
639
|
|
|
639
|
-
self.put()
|
|
640
|
+
self.put()
|
|
641
|
+
|
|
642
|
+
def add_merchant_news(self, merchant_news_configuration):
|
|
643
|
+
if is_empty(self.published_news_configuration):
|
|
644
|
+
self.published_news_configuration = {
|
|
645
|
+
'news' :[merchant_news_configuration],
|
|
646
|
+
'count' : 1,
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
else:
|
|
650
|
+
existing_merchant_news_list = self.published_news_configuration.get('news')
|
|
651
|
+
|
|
652
|
+
merchant_news_key = merchant_news_configuration.get('merchant_news_key')
|
|
653
|
+
|
|
654
|
+
if len(existing_merchant_news_list)>0:
|
|
655
|
+
index = 0
|
|
656
|
+
for v in existing_merchant_news_list:
|
|
657
|
+
if v.get('merchant_news_key') == merchant_news_key:
|
|
658
|
+
existing_merchant_news_list.pop(index)
|
|
659
|
+
|
|
660
|
+
index = index+1
|
|
661
|
+
|
|
662
|
+
existing_merchant_news_list.append(merchant_news_configuration)
|
|
663
|
+
|
|
664
|
+
self.published_news_configuration['news'] = existing_merchant_news_list
|
|
665
|
+
self.published_news_configuration['count'] = len(existing_merchant_news_list)
|
|
666
|
+
|
|
667
|
+
self.put()
|
|
668
|
+
|
|
669
|
+
def remove_merchant_news(self, merchant_news_key):
|
|
670
|
+
existing_merchant_news_list = self.published_news_configuration['news']
|
|
671
|
+
|
|
672
|
+
latest_news_list = []
|
|
673
|
+
#now = datetime.now()
|
|
674
|
+
for merchant_news in existing_merchant_news_list:
|
|
675
|
+
if merchant_news.get('merchant_news_key') != merchant_news_key:
|
|
676
|
+
#end_datetime = datetime.strptime('%d-%m-%Y %H:%m:%S', merchant_news.ge('end_datetime'))
|
|
677
|
+
#if end_datetime >
|
|
678
|
+
latest_news_list.append(merchant_news)
|
|
679
|
+
|
|
680
|
+
|
|
681
|
+
self.published_news_configuration['news'] = latest_news_list
|
|
682
|
+
self.published_news_configuration['count'] = len(latest_news_list)
|
|
683
|
+
|
|
684
|
+
self.put()
|
|
640
685
|
|
|
641
686
|
def update_prepaid_program(self, prepaid_configuration):
|
|
642
687
|
if self.prepaid_configuration is None or len(self.prepaid_configuration)==0:
|
|
@@ -1895,74 +1940,4 @@ class BannerFile(BaseNModel, DictModel):
|
|
|
1895
1940
|
old_logo_blob.delete()
|
|
1896
1941
|
banner_file.delete()
|
|
1897
1942
|
|
|
1898
|
-
|
|
1899
|
-
'''
|
|
1900
|
-
Merchant Account as ancestor
|
|
1901
|
-
'''
|
|
1902
|
-
label = ndb.StringProperty(required=False)
|
|
1903
|
-
desc = ndb.StringProperty(required=False)
|
|
1904
|
-
news_text = ndb.StringProperty(required=False)
|
|
1905
|
-
|
|
1906
|
-
news_file_type = ndb.StringProperty(required=True)
|
|
1907
|
-
news_file_public_url = ndb.StringProperty(required=True)
|
|
1908
|
-
news_file_storage_filename = ndb.StringProperty(required=True)
|
|
1909
|
-
start_date = ndb.DateProperty(required=True)
|
|
1910
|
-
end_date = ndb.DateProperty(required=True)
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
dict_properties = ['news_file_public_url', 'news_file_storage_filename', 'news_file_type', 'label', 'desc', 'news_text', 'start_date', 'end_date']
|
|
1914
|
-
|
|
1915
|
-
@staticmethod
|
|
1916
|
-
def list_by_merchant_acct(merchant_acct):
|
|
1917
|
-
result = MerchantNewsFile.query(ancestor=merchant_acct.create_ndb_key()).fetch(limit=conf.MAX_FETCH_RECORD)
|
|
1918
|
-
return result
|
|
1919
|
-
|
|
1920
|
-
@staticmethod
|
|
1921
|
-
def create(merchant_acct, label=None, desc=None, news_text=None):
|
|
1922
|
-
news_file = MerchantNewsFile(
|
|
1923
|
-
parent = merchant_acct.create_ndb_key(),
|
|
1924
|
-
label = label,
|
|
1925
|
-
desc = desc,
|
|
1926
|
-
news_text = news_text,
|
|
1927
|
-
)
|
|
1928
|
-
|
|
1929
|
-
news_file.put()
|
|
1930
|
-
|
|
1931
|
-
@staticmethod
|
|
1932
|
-
def upload_file(merchant_news, uploading_file, merchant_acct, bucket, news_file_type=None):
|
|
1933
|
-
file_prefix = random_string(8)
|
|
1934
|
-
news_file_storage_filename = 'merchant/'+merchant_acct.key_in_str+'/news/'+file_prefix+'-'+uploading_file.filename
|
|
1935
|
-
blob = bucket.blob(news_file_storage_filename)
|
|
1936
|
-
|
|
1937
|
-
logger.debug('news_file_storage_filename=%s', news_file_storage_filename)
|
|
1938
|
-
|
|
1939
|
-
blob.upload_from_string(
|
|
1940
|
-
uploading_file.read(),
|
|
1941
|
-
content_type=uploading_file.content_type
|
|
1942
|
-
)
|
|
1943
|
-
|
|
1944
|
-
uploaded_url = blob.public_url
|
|
1945
|
-
|
|
1946
|
-
logger.debug('uploaded_url=%s', uploaded_url)
|
|
1947
|
-
logger.debug('news_file_type=%s', news_file_type)
|
|
1948
|
-
|
|
1949
|
-
if is_not_empty(merchant_news.news_file_storage_filename):
|
|
1950
|
-
old_logo_blob = bucket.get_blob(merchant_news.news_file_storage_filename)
|
|
1951
|
-
if old_logo_blob:
|
|
1952
|
-
old_logo_blob.delete()
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
merchant_news.news_file_public_url = uploaded_url
|
|
1956
|
-
merchant_news.news_file_storage_filename = news_file_storage_filename
|
|
1957
|
-
merchant_news.news_file_type = news_file_type
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
merchant_news.put()
|
|
1961
|
-
|
|
1962
|
-
@staticmethod
|
|
1963
|
-
def remove_file(news_file, bucket):
|
|
1964
|
-
|
|
1965
|
-
old_logo_blob = bucket.get_blob(news_file.news_file_storage_filename)
|
|
1966
|
-
if old_logo_blob:
|
|
1967
|
-
old_logo_blob.delete()
|
|
1968
|
-
news_file.delete()
|
|
1943
|
+
|
|
@@ -6,7 +6,7 @@ Created on 9 Nov 2023
|
|
|
6
6
|
from trexmodel.program_conf import REWARD_FORMAT_MAP, REWARD_FORMAT_PREPAID
|
|
7
7
|
from trexmodel.models.datastore.message_models import Message
|
|
8
8
|
from trexmodel.conf import MESSAGE_CATEGORY_REWARD, MESSAGE_STATUS_NEW,\
|
|
9
|
-
MESSAGE_CATEGORY_REDEEM
|
|
9
|
+
MESSAGE_CATEGORY_REDEEM, MESSAGE_CATEGORY_REDEMPTION_CATALOGUE
|
|
10
10
|
from trexconf import program_conf
|
|
11
11
|
from babel.numbers import format_currency
|
|
12
12
|
import logging
|
|
@@ -140,23 +140,26 @@ message_logo_image_template = '''
|
|
|
140
140
|
|
|
141
141
|
|
|
142
142
|
def create_transaction_message(customer_transaction):
|
|
143
|
-
user_acct
|
|
144
|
-
source_key
|
|
143
|
+
user_acct = customer_transaction.transact_user_acct
|
|
144
|
+
source_key = customer_transaction.key_in_str
|
|
145
|
+
customer = customer_transaction.transact_customer_acct
|
|
146
|
+
merchant_acct = customer.registered_merchant_acct
|
|
145
147
|
message = Message.get_by_source_key(source_key)
|
|
146
148
|
|
|
147
149
|
if message is None:
|
|
148
150
|
message = Message(
|
|
151
|
+
parent = user_acct.create_ndb_key(),
|
|
149
152
|
message_to = user_acct.create_ndb_key(),
|
|
150
153
|
title = 'Transaction Reward',
|
|
151
154
|
message_category = MESSAGE_CATEGORY_REWARD,
|
|
152
155
|
message_content = __create_entiled_message_from_customer_transaction(customer_transaction),
|
|
153
156
|
message_data = __create_message_data_from_transaction(customer_transaction),
|
|
154
157
|
status = MESSAGE_STATUS_NEW,
|
|
155
|
-
|
|
158
|
+
message_from = merchant_acct.brand_name,
|
|
156
159
|
)
|
|
157
160
|
message.put()
|
|
158
|
-
user_acct.new_message_count+=1
|
|
159
|
-
user_acct.put()
|
|
161
|
+
#user_acct.new_message_count+=1
|
|
162
|
+
#user_acct.put()
|
|
160
163
|
|
|
161
164
|
return message
|
|
162
165
|
|
|
@@ -168,46 +171,50 @@ def create_redemption_message(customer_redemption):
|
|
|
168
171
|
|
|
169
172
|
if message is None:
|
|
170
173
|
message = Message(
|
|
174
|
+
parent = user_acct.create_ndb_key(),
|
|
171
175
|
source_key = source_key,
|
|
172
176
|
message_to = user_acct.create_ndb_key(),
|
|
173
177
|
title = 'Redemption',
|
|
174
178
|
message_category = MESSAGE_CATEGORY_REDEEM,
|
|
175
179
|
message_content = __create_message_from_redeem_transaction(merchant_acct, customer_redemption),
|
|
176
|
-
message_data =
|
|
180
|
+
message_data = __create_message_data_from_redemption(customer_redemption),
|
|
177
181
|
status = MESSAGE_STATUS_NEW,
|
|
178
|
-
|
|
182
|
+
message_from = merchant_acct.brand_name,
|
|
179
183
|
)
|
|
180
184
|
message.put()
|
|
181
|
-
user_acct.new_message_count+=1
|
|
182
|
-
user_acct.put()
|
|
185
|
+
#user_acct.new_message_count+=1
|
|
186
|
+
#user_acct.put()
|
|
183
187
|
|
|
184
188
|
return message
|
|
189
|
+
|
|
185
190
|
|
|
186
191
|
def create_redeem_catalogue_item_message(customer, entitled_vouchers_summary, redemption_catalogue_transaction):
|
|
187
|
-
user_acct
|
|
188
|
-
|
|
189
|
-
|
|
192
|
+
user_acct = customer.registered_user_acct
|
|
193
|
+
merchant_acct = customer.registered_merchant_acct
|
|
194
|
+
source_key = redemption_catalogue_transaction.key_in_str
|
|
195
|
+
message = Message.get_by_source_key(source_key)
|
|
190
196
|
|
|
191
197
|
if message is None:
|
|
192
198
|
message = Message(
|
|
193
|
-
|
|
199
|
+
parent = user_acct.create_ndb_key(),
|
|
194
200
|
message_to = user_acct.create_ndb_key(),
|
|
195
201
|
title = 'Redemption Catalogue Reward',
|
|
196
|
-
message_category =
|
|
202
|
+
message_category = MESSAGE_CATEGORY_REDEMPTION_CATALOGUE,
|
|
197
203
|
message_content = __create_message_from_redeem_catalogue_transaction(customer, entitled_vouchers_summary),
|
|
198
204
|
message_data = __create_message_data_from_redemption_catalogue(redemption_catalogue_transaction),
|
|
199
205
|
status = MESSAGE_STATUS_NEW,
|
|
206
|
+
message_from = merchant_acct.brand_name,
|
|
200
207
|
|
|
201
208
|
)
|
|
202
209
|
message.put()
|
|
203
|
-
user_acct.new_message_count+=1
|
|
204
|
-
user_acct.put()
|
|
210
|
+
#user_acct.new_message_count+=1
|
|
211
|
+
#user_acct.put()
|
|
205
212
|
|
|
206
213
|
return message
|
|
207
214
|
|
|
208
215
|
def __create_message_data_from_transaction(customer_transaction):
|
|
209
216
|
return {
|
|
210
|
-
'
|
|
217
|
+
'reward_transaction_key' : customer_transaction.key_in_str,
|
|
211
218
|
|
|
212
219
|
}
|
|
213
220
|
|
|
@@ -215,7 +222,13 @@ def __create_message_data_from_redemption_catalogue(redemption_catalogue_transac
|
|
|
215
222
|
return {
|
|
216
223
|
'redemption_catalogue_transaction_key' : redemption_catalogue_transaction.key_in_str,
|
|
217
224
|
|
|
218
|
-
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
def __create_message_data_from_redemption(redemption_transaction):
|
|
228
|
+
return {
|
|
229
|
+
'redemption_transaction_key' : redemption_transaction.key_in_str,
|
|
230
|
+
|
|
231
|
+
}
|
|
219
232
|
|
|
220
233
|
def __create_entiled_message_from_customer_transaction(customer_transaction):
|
|
221
234
|
|
|
@@ -13,6 +13,9 @@ from trexmodel import conf
|
|
|
13
13
|
from trexmodel.conf import MESSAGE_STATUS_SET, MESSAGE_STATUS_NEW, MESSAGE_CATEGORY_SYSTEM,\
|
|
14
14
|
MESSAGE_STATUS_READ, MESSAGE_CATEGORIES, MESSAGE_CATEGORY_ANNOUNCEMENT
|
|
15
15
|
from trexmodel.models.datastore.transaction_models import CustomerTransaction
|
|
16
|
+
from trexmodel.models.datastore.redeem_models import RedemptionCatalogueTransaction,\
|
|
17
|
+
CustomerRedemption
|
|
18
|
+
from trexmodel.models.datastore.customer_models import Customer
|
|
16
19
|
|
|
17
20
|
|
|
18
21
|
logger = logging.getLogger('model')
|
|
@@ -29,12 +32,16 @@ content_body=[text in html]
|
|
|
29
32
|
'''
|
|
30
33
|
|
|
31
34
|
class Message(BaseNModel, DictModel):
|
|
35
|
+
'''
|
|
36
|
+
User as ancestor
|
|
37
|
+
'''
|
|
32
38
|
message_to = ndb.KeyProperty(name="message_to", kind=User)
|
|
33
39
|
source_key = ndb.StringProperty(required=False)
|
|
34
40
|
title = ndb.StringProperty(required=True)
|
|
35
41
|
message_category = ndb.StringProperty(required=True, default=MESSAGE_CATEGORY_SYSTEM, choices=MESSAGE_CATEGORIES)
|
|
36
42
|
message_content = ndb.JsonProperty(required=True, indexed=False)
|
|
37
43
|
message_data = ndb.JsonProperty(required=True, indexed=False)
|
|
44
|
+
message_from = ndb.StringProperty(required=False)
|
|
38
45
|
status = ndb.StringProperty(required=True, default=MESSAGE_STATUS_NEW, choices=MESSAGE_STATUS_SET)
|
|
39
46
|
created_datetime = ndb.DateTimeProperty(required=True, auto_now_add=True)
|
|
40
47
|
read_datetime = ndb.DateTimeProperty(required=False)
|
|
@@ -51,13 +58,27 @@ class Message(BaseNModel, DictModel):
|
|
|
51
58
|
|
|
52
59
|
@property
|
|
53
60
|
def customer_transaction_entity(self):
|
|
54
|
-
customer_transaction_key = self.message_data.get('
|
|
61
|
+
customer_transaction_key = self.message_data.get('reward_transaction_key')
|
|
55
62
|
if customer_transaction_key:
|
|
56
|
-
return CustomerTransaction.fetch(customer_transaction_key)
|
|
63
|
+
return CustomerTransaction.fetch(customer_transaction_key)
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def customer_redemption_catalogue_entity(self):
|
|
67
|
+
customer_redemption_key = self.message_data.get('redemption_catalogue_transaction_key')
|
|
68
|
+
if customer_redemption_key:
|
|
69
|
+
return RedemptionCatalogueTransaction.fetch(customer_redemption_key)
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def customer_redemption_entity(self):
|
|
73
|
+
customer_redemption_key = self.message_data.get('redemption_transaction_key')
|
|
74
|
+
if customer_redemption_key:
|
|
75
|
+
return CustomerRedemption.fetch(customer_redemption_key)
|
|
76
|
+
|
|
57
77
|
|
|
58
78
|
@staticmethod
|
|
59
|
-
def create(source_key=None, message_to=None, title=None, message_type=MESSAGE_CATEGORY_ANNOUNCEMENT,message_content={}):
|
|
79
|
+
def create(user_acct, source_key=None, message_to=None, title=None, message_type=MESSAGE_CATEGORY_ANNOUNCEMENT,message_content={}):
|
|
60
80
|
Message(
|
|
81
|
+
parent = user_acct.create_ndb_key(),
|
|
61
82
|
source_key = source_key,
|
|
62
83
|
message_to = message_to.create_ndb_key(),
|
|
63
84
|
title = title,
|
|
@@ -75,12 +96,13 @@ class Message(BaseNModel, DictModel):
|
|
|
75
96
|
message.status = MESSAGE_STATUS_READ
|
|
76
97
|
message.read_datetime = datetime.utcnow()
|
|
77
98
|
message.put()
|
|
78
|
-
|
|
99
|
+
'''
|
|
79
100
|
user_acct.new_message_count-=1
|
|
80
101
|
if user_acct.new_message_count<0:
|
|
81
102
|
user_acct.new_message_count=0
|
|
82
103
|
|
|
83
104
|
user_acct.put()
|
|
105
|
+
'''
|
|
84
106
|
|
|
85
107
|
@staticmethod
|
|
86
108
|
def update_delete(message_key):
|
|
@@ -92,10 +114,22 @@ class Message(BaseNModel, DictModel):
|
|
|
92
114
|
|
|
93
115
|
@staticmethod
|
|
94
116
|
def list_paginated_by_user_account(user_acct, limit=conf.MAX_FETCH_RECORD, start_cursor=None):
|
|
117
|
+
#query = Message.query(ancestor=user_acct.create_ndb_key()).order(-Message.created_datetime)
|
|
95
118
|
query = Message.query(ndb.AND(Message.message_to==user_acct.create_ndb_key())).order(-Message.created_datetime)
|
|
96
119
|
|
|
97
120
|
return Message.list_all_with_condition_query(query, limit=limit, start_cursor=start_cursor, return_with_cursor=True, keys_only=False)
|
|
98
121
|
|
|
122
|
+
|
|
123
|
+
@staticmethod
|
|
124
|
+
def count_new_message(user_acct):
|
|
125
|
+
return Message.count_by_status(user_acct, status=conf.MESSAGE_STATUS_NEW)
|
|
126
|
+
|
|
127
|
+
@staticmethod
|
|
128
|
+
def count_by_status(user_acct, status=conf.MESSAGE_STATUS_NEW):
|
|
129
|
+
query = Message.query(ndb.AND(Message.status==status), ancestor=user_acct.create_ndb_key()).order(-Message.created_datetime)
|
|
130
|
+
|
|
131
|
+
return Message.count_with_condition_query(query, limit=conf.MAX_FETCH_RECORD)
|
|
132
|
+
|
|
99
133
|
|
|
100
134
|
@staticmethod
|
|
101
135
|
def get_by_source_key(source_key):
|
|
@@ -382,7 +382,7 @@ class Product(ProductBase, FullTextSearchable):
|
|
|
382
382
|
product_sku = ndb.StringProperty(required=True)
|
|
383
383
|
product_name = ndb.StringProperty(required=True)
|
|
384
384
|
product_desc = ndb.StringProperty(required=False)
|
|
385
|
-
category_key = ndb.StringProperty(required=False)
|
|
385
|
+
category_key = ndb.StringProperty(required=False)
|
|
386
386
|
|
|
387
387
|
barcode = ndb.StringProperty(required=False)
|
|
388
388
|
|
|
@@ -408,7 +408,8 @@ class Product(ProductBase, FullTextSearchable):
|
|
|
408
408
|
|
|
409
409
|
fulltextsearch_field_name = 'product_name'
|
|
410
410
|
|
|
411
|
-
dict_properties = ['product_sku', 'product_name', 'category_key', 'price', 'cost',
|
|
411
|
+
dict_properties = ['product_sku', 'product_name', 'category_key', 'price', 'cost',
|
|
412
|
+
'product_desc', 'barcode', 'pos_settings', 'tax_details', 'product_modifier']
|
|
412
413
|
|
|
413
414
|
@property
|
|
414
415
|
def product_default_image(self):
|
|
@@ -434,6 +435,7 @@ class Product(ProductBase, FullTextSearchable):
|
|
|
434
435
|
'label' : self.product_name,
|
|
435
436
|
'desc' : self.product_desc,
|
|
436
437
|
'price' : self.price,
|
|
438
|
+
'category_key' : self.category_key,
|
|
437
439
|
'barcode' : self.barcode,
|
|
438
440
|
'modifiers' : modifier_setting_list_for_pos,
|
|
439
441
|
'representation_on_pos' : self.pos_settings,
|
|
@@ -780,10 +782,9 @@ class ProductCatalogue(ProductBase):
|
|
|
780
782
|
return total_count
|
|
781
783
|
|
|
782
784
|
def publish(self):
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
self.put()
|
|
785
|
+
self.published_menu_settings = self.setting_details_for_pos
|
|
786
|
+
self.is_publish = True
|
|
787
|
+
self.put()
|
|
787
788
|
|
|
788
789
|
def unpublish(self):
|
|
789
790
|
self.is_publish = False
|
|
@@ -6,7 +6,7 @@ Created on 10 Apr 2020
|
|
|
6
6
|
from google.cloud import ndb
|
|
7
7
|
from trexmodel.models.datastore.ndb_models import BaseNModel, DictModel
|
|
8
8
|
from trexlib.utils.string_util import random_number, random_string,\
|
|
9
|
-
is_empty
|
|
9
|
+
is_empty, is_not_empty
|
|
10
10
|
from flask_login import UserMixin
|
|
11
11
|
import logging
|
|
12
12
|
from trexlib.utils.security_util import generate_user_id, hash_password
|
|
@@ -37,14 +37,14 @@ class UserMin(BaseNModel, DictModel, UserMixin):
|
|
|
37
37
|
|
|
38
38
|
locked = ndb.BooleanProperty(required=False, default=False)
|
|
39
39
|
lock_expiry_datetime = ndb.DateTimeProperty(required=False)
|
|
40
|
-
active = ndb.BooleanProperty(required=True, default=True)
|
|
40
|
+
active = ndb.BooleanProperty(required=True, default=True)
|
|
41
41
|
try_count = ndb.IntegerProperty(required=False)
|
|
42
42
|
demo_account = ndb.BooleanProperty(required=False, default=False)
|
|
43
43
|
deleted = ndb.BooleanProperty(required=False, default=False)
|
|
44
|
+
signin_device_session = ndb.JsonProperty()
|
|
44
45
|
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
dict_properties = ['user_id', 'name', 'email', 'gravatar_url', 'active', 'locked', 'lock_expiry_datetime']
|
|
47
|
+
dict_properties = ['user_id', 'name', 'email', 'signin_device_session', 'gravatar_url', 'active', 'locked', 'lock_expiry_datetime']
|
|
48
48
|
|
|
49
49
|
@classmethod
|
|
50
50
|
#@cache.memoize(timeout=60)
|
|
@@ -63,6 +63,18 @@ class UserMin(BaseNModel, DictModel, UserMixin):
|
|
|
63
63
|
def is_admin_user(self):
|
|
64
64
|
return False
|
|
65
65
|
|
|
66
|
+
@property
|
|
67
|
+
def signin_device_id(self):
|
|
68
|
+
if is_not_empty(self.signin_device_session):
|
|
69
|
+
return self.signin_device_session.get('device_id')
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def signin_expiry_datetime(self):
|
|
73
|
+
if is_not_empty(self.signin_device_session):
|
|
74
|
+
expiry_datetime_str = self.signin_device_session.get('expiry_datetime')
|
|
75
|
+
if is_not_empty(expiry_datetime_str):
|
|
76
|
+
return datetime.strptime(expiry_datetime_str, '%d-%m-%Y %H:%M:%S')
|
|
77
|
+
|
|
66
78
|
def is_valid_password(self, checking_password):
|
|
67
79
|
hashed_signin_password = hash_password(self.user_id, checking_password)
|
|
68
80
|
|
|
@@ -266,11 +278,11 @@ class UserBase(UserMin):
|
|
|
266
278
|
|
|
267
279
|
if is_email_verified==False:
|
|
268
280
|
created_user.email_vc = random_number(6)
|
|
269
|
-
created_user.email_vc_expiry_datetime = datetime.
|
|
281
|
+
created_user.email_vc_expiry_datetime = datetime.utcnow()() + timedelta(minutes=10)
|
|
270
282
|
|
|
271
283
|
if is_mobile_phone_verified==False:
|
|
272
284
|
created_user.mobile_phone_vc = random_number(6)
|
|
273
|
-
created_user.mobile_phone_vc_expiry_datetime = datetime.
|
|
285
|
+
created_user.mobile_phone_vc_expiry_datetime = datetime.utcnow() + timedelta(minutes=10)
|
|
274
286
|
|
|
275
287
|
created_user.put()
|
|
276
288
|
|
|
@@ -379,7 +391,8 @@ class User(UserBase):
|
|
|
379
391
|
'mobile_phone', 'email', 'password', 'name', 'birth_date', 'gender',
|
|
380
392
|
'reference_code', 'country', 'state', 'city', 'postcode',
|
|
381
393
|
'address', 'redeem_pin', 'new_message_count', 'status',
|
|
382
|
-
'device_details',
|
|
394
|
+
'device_details', 'signin_device_session', 'referral_code',
|
|
395
|
+
'last_login_datetime',
|
|
383
396
|
]
|
|
384
397
|
|
|
385
398
|
#unique_attributes = 'email,username'
|
|
@@ -387,7 +400,7 @@ class User(UserBase):
|
|
|
387
400
|
audit_properties = [
|
|
388
401
|
'mobile_phone', 'email', 'password', 'name', 'birth_date', 'gender',
|
|
389
402
|
'reference_code', 'country', 'state', 'city', 'postcode',
|
|
390
|
-
'address', 'redeem_pin', 'status', 'device_details',
|
|
403
|
+
'address', 'redeem_pin', 'status', 'device_details',
|
|
391
404
|
|
|
392
405
|
]
|
|
393
406
|
|
|
@@ -258,10 +258,13 @@ class MerchantVoucher(VoucherBase):
|
|
|
258
258
|
merchant_voucher.terms_and_conditions = terms_and_conditions
|
|
259
259
|
merchant_voucher.redeem_limit_type = redeem_limit_type
|
|
260
260
|
merchant_voucher.redeem_limit_count = redeem_limit_count
|
|
261
|
-
|
|
261
|
+
|
|
262
262
|
merchant_voucher.modified_by = modified_by.create_ndb_key()
|
|
263
263
|
merchant_voucher.modified_by_username = modified_by_username
|
|
264
264
|
|
|
265
|
+
if merchant_voucher.completed_status!=program_conf.VOUCHER_STATUS_BASE:
|
|
266
|
+
merchant_voucher.completed_status = program_conf.VOUCHER_STATUS_PUBLISH
|
|
267
|
+
|
|
265
268
|
merchant_voucher.put()
|
|
266
269
|
|
|
267
270
|
return merchant_voucher
|
|
@@ -36,6 +36,8 @@ def construct_merchant_acct_info(merchant_acct):
|
|
|
36
36
|
referral_program_settings = merchant_acct.program_settings.get('referral_program', {})
|
|
37
37
|
|
|
38
38
|
|
|
39
|
+
|
|
40
|
+
'''
|
|
39
41
|
merchant_news_list = [
|
|
40
42
|
{
|
|
41
43
|
'image_url': 'https://scontent.cdninstagram.com/v/t39.30808-6/395358935_817823987014226_84933362912055577_n.jpg?stp=dst-jpg_e35&efg=eyJ2ZW5jb2RlX3RhZyI6ImltYWdlX3VybGdlbi42NTF4NjUwLnNkci5mMzA4MDgifQ&_nc_ht=scontent.cdninstagram.com&_nc_cat=102&_nc_ohc=v_kSSi1t6JgQ7kNvgERj6Vi&edm=APs17CUAAAAA&ccb=7-5&ig_cache_key=MzIyMjUxMzQ0MzI0ODIyMzYzMg%3D%3D.2-ccb7-5&oh=00_AfAUoP1jFeskadyDc4xrwkZb1PuH9t5JSajL6Q5tKAwCew&oe=663DAE72&_nc_sid=10d13b',
|
|
@@ -51,8 +53,12 @@ def construct_merchant_acct_info(merchant_acct):
|
|
|
51
53
|
}
|
|
52
54
|
|
|
53
55
|
]
|
|
54
|
-
|
|
56
|
+
'''
|
|
55
57
|
merchant_news_list=[]
|
|
58
|
+
|
|
59
|
+
if merchant_acct.published_news_configuration:
|
|
60
|
+
merchant_news_list = merchant_acct.published_news_configuration['news']
|
|
61
|
+
|
|
56
62
|
info = {
|
|
57
63
|
'key' : merchant_acct.key_in_str,
|
|
58
64
|
'company_name' : merchant_acct.company_name,
|
|
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
|
|
File without changes
|
{trex-model-1.4.4 → trex-model-1.4.6}/trexmodel/models/datastore/redemption_catalogue_models.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{trex-model-1.4.4 → trex-model-1.4.6}/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
|