trex-model 1.4.5__tar.gz → 1.5.0__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.5 → trex-model-1.5.0}/PKG-INFO +1 -1
- {trex-model-1.4.5 → trex-model-1.5.0}/setup.py +1 -1
- {trex-model-1.4.5 → trex-model-1.5.0}/trex_model.egg-info/PKG-INFO +1 -1
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/conf.py +19 -9
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/marketing_models.py +244 -2
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/merchant_models.py +120 -75
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/message_model_helper.py +34 -20
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/message_models.py +38 -4
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/program_models.py +100 -7
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/voucher_models.py +4 -1
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/merchant_helpers.py +7 -1
- {trex-model-1.4.5 → trex-model-1.5.0}/LICENSE +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/MANIFEST.in +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/README.md +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/setup.cfg +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trex_model.egg-info/SOURCES.txt +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trex_model.egg-info/dependency_links.txt +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trex_model.egg-info/requires.txt +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trex_model.egg-info/top_level.txt +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/__init__.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/__init__.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/__init__.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/admin_models.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/analytic_models.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/app_models.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/coporate_models.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/customer_model_helpers.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/customer_models.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/fb_subsriber_models.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/import_models.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/inventory_model.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/loyalty_models.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/lucky_draw_models.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/membership_models.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/model_decorators.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/ndb_models.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/pos_models.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/prepaid_models.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/product_models.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/rating_models.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/recruit_models.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/redeem_models.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/redemption_catalogue_models.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/referral_program_model.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/reward_model_helpers.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/reward_models.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/spending_base_program_model.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/system_models.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/task_models.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/test_models.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/transaction_models.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/datastore/user_models.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/model_decorator.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/models/prepaid_helpers.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/pos_conf.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/program_conf.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/utils/__init__.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/utils/gcloud/__init__.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/utils/gcloud/datastore_util.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/utils/model/__init__.py +0 -0
- {trex-model-1.4.5 → trex-model-1.5.0}/trexmodel/utils/model/model_util.py +0 -0
|
@@ -28,15 +28,25 @@ 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
|
|
38
|
-
|
|
39
|
-
|
|
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'
|
|
39
|
+
|
|
40
|
+
MESSAGE_CATEGORIES = (
|
|
41
|
+
MESSAGE_CATEGORY_ANNOUNCEMENT,
|
|
42
|
+
MESSAGE_CATEGORY_ALERT,
|
|
43
|
+
MESSAGE_CATEGORY_PROMOTION,
|
|
44
|
+
MESSAGE_CATEGORY_SURVEY,
|
|
45
|
+
MESSAGE_CATEGORY_SYSTEM,
|
|
46
|
+
MESSAGE_CATEGORY_REWARD,
|
|
47
|
+
MESSAGE_CATEGORY_REDEEM,
|
|
48
|
+
MESSAGE_CATEGORY_REDEMPTION_CATALOGUE,
|
|
49
|
+
)
|
|
40
50
|
|
|
41
51
|
MESSAGE_STATUS_NEW = 'n'
|
|
42
52
|
MESSAGE_STATUS_READ = 'r'
|
|
@@ -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,8 @@ 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()
|
|
73
|
+
published_tier_program_configuration = ndb.JsonProperty()
|
|
72
74
|
|
|
73
75
|
membership_configuration = ndb.JsonProperty()
|
|
74
76
|
tier_membership_configuration = ndb.JsonProperty()
|
|
@@ -90,12 +92,12 @@ class MerchantAcct(MerchantMin):
|
|
|
90
92
|
'office_phone', 'fax_phone', 'email', 'account_code', 'country',
|
|
91
93
|
'registered_datetime', 'modified_datetime', 'plan_start_date', 'plan_end_date', 'currency_code',
|
|
92
94
|
'timezone', 'effective_referral_program_count',
|
|
93
|
-
'published_program_configuration', 'published_referral_program_configuration',
|
|
94
|
-
'published_voucher_configuration', 'membership_configuration',
|
|
95
|
+
'published_program_configuration', 'published_tier_program_configuration', 'published_referral_program_configuration',
|
|
96
|
+
'published_voucher_configuration', 'published_news_configuration', 'membership_configuration',
|
|
95
97
|
'tier_membership_configuration', 'prepaid_configuration', 'lucky_draw_configuration', 'product_modifier_configuration',
|
|
96
98
|
'dashboard_stat_figure', 'program_settings', 'is_tier_membership_configured', 'website',
|
|
97
99
|
'product_package', 'loyalty_package','account_plan','outlet_count', 'outlet_limit',
|
|
98
|
-
'published_redemption_catalogue_configuration',
|
|
100
|
+
'published_redemption_catalogue_configuration','logo_public_url'
|
|
99
101
|
]
|
|
100
102
|
|
|
101
103
|
|
|
@@ -572,6 +574,32 @@ class MerchantAcct(MerchantMin):
|
|
|
572
574
|
|
|
573
575
|
self.put()
|
|
574
576
|
|
|
577
|
+
def update_published_tier_program(self, program_configuration):
|
|
578
|
+
if is_empty(self.published_tier_program_configuration):
|
|
579
|
+
self.published_program_configuration = {
|
|
580
|
+
'programs' :[program_configuration],
|
|
581
|
+
'count' : 1,
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
else:
|
|
585
|
+
self.flush_dirty_program_configuration()
|
|
586
|
+
existing_programs_list = self.published_tier_program_configuration.get('programs')
|
|
587
|
+
|
|
588
|
+
program_key = program_configuration.get('program_key')
|
|
589
|
+
index = 0
|
|
590
|
+
for p in existing_programs_list:
|
|
591
|
+
if p.get('program_key') == program_key:
|
|
592
|
+
existing_programs_list.pop(index)
|
|
593
|
+
|
|
594
|
+
index = index+1
|
|
595
|
+
|
|
596
|
+
existing_programs_list.append(program_configuration)
|
|
597
|
+
|
|
598
|
+
self.published_tier_program_configuration['programs'] = existing_programs_list
|
|
599
|
+
self.published_tier_program_configuration['count'] = len(existing_programs_list)
|
|
600
|
+
|
|
601
|
+
self.put()
|
|
602
|
+
|
|
575
603
|
def update_published_referral_program(self, program_configuration):
|
|
576
604
|
if is_empty(self.published_referral_program_configuration):
|
|
577
605
|
self.published_referral_program_configuration = {
|
|
@@ -636,7 +664,51 @@ class MerchantAcct(MerchantMin):
|
|
|
636
664
|
self.published_voucher_configuration['vouchers'] = new_vouchers_list
|
|
637
665
|
self.published_voucher_configuration['count'] = len(new_vouchers_list)
|
|
638
666
|
|
|
639
|
-
self.put()
|
|
667
|
+
self.put()
|
|
668
|
+
|
|
669
|
+
def add_merchant_news(self, merchant_news_configuration):
|
|
670
|
+
if is_empty(self.published_news_configuration):
|
|
671
|
+
self.published_news_configuration = {
|
|
672
|
+
'news' :[merchant_news_configuration],
|
|
673
|
+
'count' : 1,
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
else:
|
|
677
|
+
existing_merchant_news_list = self.published_news_configuration.get('news')
|
|
678
|
+
|
|
679
|
+
merchant_news_key = merchant_news_configuration.get('merchant_news_key')
|
|
680
|
+
|
|
681
|
+
if len(existing_merchant_news_list)>0:
|
|
682
|
+
index = 0
|
|
683
|
+
for v in existing_merchant_news_list:
|
|
684
|
+
if v.get('merchant_news_key') == merchant_news_key:
|
|
685
|
+
existing_merchant_news_list.pop(index)
|
|
686
|
+
|
|
687
|
+
index = index+1
|
|
688
|
+
|
|
689
|
+
existing_merchant_news_list.append(merchant_news_configuration)
|
|
690
|
+
|
|
691
|
+
self.published_news_configuration['news'] = existing_merchant_news_list
|
|
692
|
+
self.published_news_configuration['count'] = len(existing_merchant_news_list)
|
|
693
|
+
|
|
694
|
+
self.put()
|
|
695
|
+
|
|
696
|
+
def remove_merchant_news(self, merchant_news_key):
|
|
697
|
+
existing_merchant_news_list = self.published_news_configuration['news']
|
|
698
|
+
|
|
699
|
+
latest_news_list = []
|
|
700
|
+
#now = datetime.now()
|
|
701
|
+
for merchant_news in existing_merchant_news_list:
|
|
702
|
+
if merchant_news.get('merchant_news_key') != merchant_news_key:
|
|
703
|
+
#end_datetime = datetime.strptime('%d-%m-%Y %H:%m:%S', merchant_news.ge('end_datetime'))
|
|
704
|
+
#if end_datetime >
|
|
705
|
+
latest_news_list.append(merchant_news)
|
|
706
|
+
|
|
707
|
+
|
|
708
|
+
self.published_news_configuration['news'] = latest_news_list
|
|
709
|
+
self.published_news_configuration['count'] = len(latest_news_list)
|
|
710
|
+
|
|
711
|
+
self.put()
|
|
640
712
|
|
|
641
713
|
def update_prepaid_program(self, prepaid_configuration):
|
|
642
714
|
if self.prepaid_configuration is None or len(self.prepaid_configuration)==0:
|
|
@@ -867,6 +939,49 @@ class MerchantAcct(MerchantMin):
|
|
|
867
939
|
self.published_program_configuration['count'] = program_count
|
|
868
940
|
|
|
869
941
|
self.put()
|
|
942
|
+
|
|
943
|
+
def remove_tier_program_from_published_tier_program_configuration(self, program_key_to_remove):
|
|
944
|
+
|
|
945
|
+
logger.debug('remove_tier_program_from_published_tier_program_configuration: program_key_to_remove=%s', program_key_to_remove)
|
|
946
|
+
|
|
947
|
+
#self.flush_dirty_program_configuration()
|
|
948
|
+
if self.published_tier_program_configuration:
|
|
949
|
+
existing_programs_list = self.published_tier_program_configuration['programs']
|
|
950
|
+
program_count = len(existing_programs_list)
|
|
951
|
+
|
|
952
|
+
else:
|
|
953
|
+
self.published_tier_program_configuration = {}
|
|
954
|
+
existing_programs_list = []
|
|
955
|
+
program_count = 0
|
|
956
|
+
|
|
957
|
+
|
|
958
|
+
logger.debug('program_count before remove=%s', program_count)
|
|
959
|
+
|
|
960
|
+
index = 0
|
|
961
|
+
|
|
962
|
+
for program in existing_programs_list:
|
|
963
|
+
|
|
964
|
+
logger.debug('program_key=%s', program.get('program_key'))
|
|
965
|
+
|
|
966
|
+
is_same_program_key = program.get('program_key') == program_key_to_remove
|
|
967
|
+
|
|
968
|
+
logger.debug('is_same_program_key=%s', is_same_program_key)
|
|
969
|
+
|
|
970
|
+
if is_same_program_key:
|
|
971
|
+
existing_programs_list.pop(index)
|
|
972
|
+
|
|
973
|
+
logger.debug('Found program to be remove')
|
|
974
|
+
|
|
975
|
+
index = index+1
|
|
976
|
+
|
|
977
|
+
program_count = len(existing_programs_list)
|
|
978
|
+
|
|
979
|
+
logger.debug('program_count after remove=%s', program_count)
|
|
980
|
+
|
|
981
|
+
self.published_tier_program_configuration['programs'] = existing_programs_list
|
|
982
|
+
self.published_tier_program_configuration['count'] = program_count
|
|
983
|
+
|
|
984
|
+
self.put()
|
|
870
985
|
|
|
871
986
|
def remove_program_from_published_referral_program_configuration(self, program_key_to_remove):
|
|
872
987
|
|
|
@@ -1895,74 +2010,4 @@ class BannerFile(BaseNModel, DictModel):
|
|
|
1895
2010
|
old_logo_blob.delete()
|
|
1896
2011
|
banner_file.delete()
|
|
1897
2012
|
|
|
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()
|
|
2013
|
+
|
|
@@ -6,10 +6,11 @@ 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
|
|
13
|
+
from flask_babel import gettext
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
logger = logging.getLogger('helper')
|
|
@@ -140,23 +141,26 @@ message_logo_image_template = '''
|
|
|
140
141
|
|
|
141
142
|
|
|
142
143
|
def create_transaction_message(customer_transaction):
|
|
143
|
-
user_acct
|
|
144
|
-
source_key
|
|
144
|
+
user_acct = customer_transaction.transact_user_acct
|
|
145
|
+
source_key = customer_transaction.key_in_str
|
|
146
|
+
customer = customer_transaction.transact_customer_acct
|
|
147
|
+
merchant_acct = customer.registered_merchant_acct
|
|
145
148
|
message = Message.get_by_source_key(source_key)
|
|
146
149
|
|
|
147
150
|
if message is None:
|
|
148
151
|
message = Message(
|
|
152
|
+
parent = user_acct.create_ndb_key(),
|
|
149
153
|
message_to = user_acct.create_ndb_key(),
|
|
150
154
|
title = 'Transaction Reward',
|
|
151
155
|
message_category = MESSAGE_CATEGORY_REWARD,
|
|
152
156
|
message_content = __create_entiled_message_from_customer_transaction(customer_transaction),
|
|
153
157
|
message_data = __create_message_data_from_transaction(customer_transaction),
|
|
154
158
|
status = MESSAGE_STATUS_NEW,
|
|
155
|
-
|
|
159
|
+
message_from = merchant_acct.brand_name,
|
|
156
160
|
)
|
|
157
161
|
message.put()
|
|
158
|
-
user_acct.new_message_count+=1
|
|
159
|
-
user_acct.put()
|
|
162
|
+
#user_acct.new_message_count+=1
|
|
163
|
+
#user_acct.put()
|
|
160
164
|
|
|
161
165
|
return message
|
|
162
166
|
|
|
@@ -168,46 +172,50 @@ def create_redemption_message(customer_redemption):
|
|
|
168
172
|
|
|
169
173
|
if message is None:
|
|
170
174
|
message = Message(
|
|
175
|
+
parent = user_acct.create_ndb_key(),
|
|
171
176
|
source_key = source_key,
|
|
172
177
|
message_to = user_acct.create_ndb_key(),
|
|
173
178
|
title = 'Redemption',
|
|
174
179
|
message_category = MESSAGE_CATEGORY_REDEEM,
|
|
175
180
|
message_content = __create_message_from_redeem_transaction(merchant_acct, customer_redemption),
|
|
176
|
-
message_data =
|
|
181
|
+
message_data = __create_message_data_from_redemption(customer_redemption),
|
|
177
182
|
status = MESSAGE_STATUS_NEW,
|
|
178
|
-
|
|
183
|
+
message_from = merchant_acct.brand_name,
|
|
179
184
|
)
|
|
180
185
|
message.put()
|
|
181
|
-
user_acct.new_message_count+=1
|
|
182
|
-
user_acct.put()
|
|
186
|
+
#user_acct.new_message_count+=1
|
|
187
|
+
#user_acct.put()
|
|
183
188
|
|
|
184
189
|
return message
|
|
190
|
+
|
|
185
191
|
|
|
186
192
|
def create_redeem_catalogue_item_message(customer, entitled_vouchers_summary, redemption_catalogue_transaction):
|
|
187
|
-
user_acct
|
|
188
|
-
|
|
189
|
-
|
|
193
|
+
user_acct = customer.registered_user_acct
|
|
194
|
+
merchant_acct = customer.registered_merchant_acct
|
|
195
|
+
source_key = redemption_catalogue_transaction.key_in_str
|
|
196
|
+
message = Message.get_by_source_key(source_key)
|
|
190
197
|
|
|
191
198
|
if message is None:
|
|
192
199
|
message = Message(
|
|
193
|
-
|
|
200
|
+
parent = user_acct.create_ndb_key(),
|
|
194
201
|
message_to = user_acct.create_ndb_key(),
|
|
195
|
-
title = 'Redemption Catalogue Reward',
|
|
196
|
-
message_category =
|
|
202
|
+
title = gettext('Redemption Catalogue Reward'),
|
|
203
|
+
message_category = MESSAGE_CATEGORY_REDEMPTION_CATALOGUE,
|
|
197
204
|
message_content = __create_message_from_redeem_catalogue_transaction(customer, entitled_vouchers_summary),
|
|
198
205
|
message_data = __create_message_data_from_redemption_catalogue(redemption_catalogue_transaction),
|
|
199
206
|
status = MESSAGE_STATUS_NEW,
|
|
207
|
+
message_from = merchant_acct.brand_name,
|
|
200
208
|
|
|
201
209
|
)
|
|
202
210
|
message.put()
|
|
203
|
-
user_acct.new_message_count+=1
|
|
204
|
-
user_acct.put()
|
|
211
|
+
#user_acct.new_message_count+=1
|
|
212
|
+
#user_acct.put()
|
|
205
213
|
|
|
206
214
|
return message
|
|
207
215
|
|
|
208
216
|
def __create_message_data_from_transaction(customer_transaction):
|
|
209
217
|
return {
|
|
210
|
-
'
|
|
218
|
+
'reward_transaction_key' : customer_transaction.key_in_str,
|
|
211
219
|
|
|
212
220
|
}
|
|
213
221
|
|
|
@@ -215,7 +223,13 @@ def __create_message_data_from_redemption_catalogue(redemption_catalogue_transac
|
|
|
215
223
|
return {
|
|
216
224
|
'redemption_catalogue_transaction_key' : redemption_catalogue_transaction.key_in_str,
|
|
217
225
|
|
|
218
|
-
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
def __create_message_data_from_redemption(redemption_transaction):
|
|
229
|
+
return {
|
|
230
|
+
'redemption_transaction_key' : redemption_transaction.key_in_str,
|
|
231
|
+
|
|
232
|
+
}
|
|
219
233
|
|
|
220
234
|
def __create_entiled_message_from_customer_transaction(customer_transaction):
|
|
221
235
|
|
|
@@ -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):
|
|
@@ -19,6 +19,26 @@ from trexlib.utils.common.common_util import sort_list, sort_dict_list
|
|
|
19
19
|
#logger = logging.getLogger('model')
|
|
20
20
|
logger = logging.getLogger('debug')
|
|
21
21
|
|
|
22
|
+
def create_schedule_program(merchant_acct, program):
|
|
23
|
+
if program.reward_base in (program_conf.SCHEDULE_BASED_PROGRAM):
|
|
24
|
+
|
|
25
|
+
if program.reward_base == program_conf.REWARD_BASE_ON_BIRTHDAY:
|
|
26
|
+
if program.giveaway_reward_when == program_conf.PROGRAM_SCHEDULE_TYPE_MONTH_START:
|
|
27
|
+
MerchantScheduleProgram.create_first_day_of_month_schedule_program(merchant_acct, program)
|
|
28
|
+
|
|
29
|
+
elif program.giveaway_reward_when == program_conf.ADVANCE_IN_DAY:
|
|
30
|
+
MerchantScheduleProgram.create_daily_schedule_program(merchant_acct, program)
|
|
31
|
+
|
|
32
|
+
elif program.reward_base == program_conf.REWARD_BASE_ON_GIVEAWAY:
|
|
33
|
+
if program.giveaway_system_condition == program_conf.GIVEAWAY_SYSTEM_CONDITION_MEMBERSHIP_YEAR:
|
|
34
|
+
MerchantScheduleProgram.create_daily_schedule_program(merchant_acct, program)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def remove_schedule_program(program):
|
|
39
|
+
if program.reward_base in (program_conf.SCHEDULE_BASED_PROGRAM):
|
|
40
|
+
MerchantScheduleProgram.remove_by_merchant_program(program)
|
|
41
|
+
|
|
22
42
|
class BaseProgram(BaseNModel, DictModel):
|
|
23
43
|
reward_base = ndb.StringProperty(required=True, choices=set(program_conf.REWARD_BASE_SET))
|
|
24
44
|
reward_format = ndb.StringProperty(required=False, choices=set(program_conf.REWARD_FORMAT_SET))
|
|
@@ -164,9 +184,9 @@ class BaseProgram(BaseNModel, DictModel):
|
|
|
164
184
|
program.put()
|
|
165
185
|
|
|
166
186
|
return program
|
|
167
|
-
|
|
187
|
+
'''
|
|
168
188
|
@classmethod
|
|
169
|
-
def
|
|
189
|
+
def create_schedule_program(cls, merchant_acct, program):
|
|
170
190
|
if program.reward_base in (program_conf.SCHEDULE_BASED_PROGRAM):
|
|
171
191
|
|
|
172
192
|
if program.reward_base == program_conf.REWARD_BASE_ON_BIRTHDAY:
|
|
@@ -182,9 +202,10 @@ class BaseProgram(BaseNModel, DictModel):
|
|
|
182
202
|
|
|
183
203
|
|
|
184
204
|
@classmethod
|
|
185
|
-
def
|
|
205
|
+
def remove_schedule_program(cls, program):
|
|
186
206
|
if program.reward_base in (program_conf.SCHEDULE_BASED_PROGRAM):
|
|
187
207
|
MerchantScheduleProgram.remove_by_merchant_program(program)
|
|
208
|
+
'''
|
|
188
209
|
|
|
189
210
|
@classmethod
|
|
190
211
|
@model_transactional(desc="publish_program")
|
|
@@ -196,7 +217,7 @@ class BaseProgram(BaseNModel, DictModel):
|
|
|
196
217
|
merchant_acct = program.merchant_acct
|
|
197
218
|
merchant_acct.update_published_program(program.to_configuration())
|
|
198
219
|
|
|
199
|
-
|
|
220
|
+
create_schedule_program(merchant_acct, program)
|
|
200
221
|
|
|
201
222
|
@classmethod
|
|
202
223
|
@model_transactional(desc="archive_program")
|
|
@@ -208,7 +229,7 @@ class BaseProgram(BaseNModel, DictModel):
|
|
|
208
229
|
merchant_acct = program.merchant_acct
|
|
209
230
|
merchant_acct.remove_program_from_published_program_configuration(program.key_in_str)
|
|
210
231
|
|
|
211
|
-
|
|
232
|
+
remove_schedule_program(program)
|
|
212
233
|
|
|
213
234
|
|
|
214
235
|
@classmethod
|
|
@@ -231,7 +252,7 @@ class BaseProgram(BaseNModel, DictModel):
|
|
|
231
252
|
merchant_acct = program.merchant_acct
|
|
232
253
|
merchant_acct.update_published_program(program.to_configuration())
|
|
233
254
|
|
|
234
|
-
|
|
255
|
+
create_schedule_program(merchant_acct, program)
|
|
235
256
|
|
|
236
257
|
|
|
237
258
|
@classmethod
|
|
@@ -254,7 +275,7 @@ class BaseProgram(BaseNModel, DictModel):
|
|
|
254
275
|
merchant_acct = program.merchant_acct
|
|
255
276
|
merchant_acct.remove_program_from_published_program_configuration(program.key_in_str)
|
|
256
277
|
|
|
257
|
-
|
|
278
|
+
remove_schedule_program(program)
|
|
258
279
|
|
|
259
280
|
def to_configuration(self):
|
|
260
281
|
program_configuration = {
|
|
@@ -698,6 +719,78 @@ class MerchantTierRewardProgram(MerchantProgram):
|
|
|
698
719
|
|
|
699
720
|
return reward_settings_list
|
|
700
721
|
|
|
722
|
+
@staticmethod
|
|
723
|
+
@model_transactional(desc="publish_program")
|
|
724
|
+
def publish_program(program):
|
|
725
|
+
program.completed_status = program_conf.PROGRAM_STATUS_PUBLISH
|
|
726
|
+
program.published_datetime = datetime.now()
|
|
727
|
+
program.put()
|
|
728
|
+
|
|
729
|
+
merchant_acct = program.merchant_acct
|
|
730
|
+
merchant_acct.update_published_program(program.to_configuration())
|
|
731
|
+
|
|
732
|
+
create_schedule_program(merchant_acct, program)
|
|
733
|
+
|
|
734
|
+
@staticmethod
|
|
735
|
+
@model_transactional(desc="archive_program")
|
|
736
|
+
def archive_program(program):
|
|
737
|
+
program.archived = True
|
|
738
|
+
program.archived_datetime = datetime.now()
|
|
739
|
+
program.put()
|
|
740
|
+
|
|
741
|
+
merchant_acct = program.merchant_acct
|
|
742
|
+
#merchant_acct.remove_tier_program_from_published_tier_program_configuration(program.key_in_str)
|
|
743
|
+
merchant_acct.remove_program_from_published_program_configuration(program.key_in_str)
|
|
744
|
+
|
|
745
|
+
remove_schedule_program(program)
|
|
746
|
+
|
|
747
|
+
@staticmethod
|
|
748
|
+
@model_transactional(desc="enable program")
|
|
749
|
+
def enable(program, modified_by=None):
|
|
750
|
+
program.enabled = True
|
|
751
|
+
|
|
752
|
+
modified_by_username = None
|
|
753
|
+
|
|
754
|
+
if is_not_empty(modified_by):
|
|
755
|
+
if isinstance(modified_by, MerchantUser):
|
|
756
|
+
modified_by_username = modified_by.username
|
|
757
|
+
|
|
758
|
+
program.modified_by = modified_by.create_ndb_key()
|
|
759
|
+
program.modified_by_username = modified_by_username
|
|
760
|
+
|
|
761
|
+
program.put()
|
|
762
|
+
|
|
763
|
+
if program.is_published:
|
|
764
|
+
merchant_acct = program.merchant_acct
|
|
765
|
+
#merchant_acct.update_published_tier_program(program.to_configuration())
|
|
766
|
+
merchant_acct.update_published_program(program.to_configuration())
|
|
767
|
+
|
|
768
|
+
create_schedule_program(merchant_acct, program)
|
|
769
|
+
|
|
770
|
+
|
|
771
|
+
@classmethod
|
|
772
|
+
@model_transactional(desc="disable program")
|
|
773
|
+
def disable(cls, program, modified_by=None):
|
|
774
|
+
program.enabled = False
|
|
775
|
+
|
|
776
|
+
modified_by_username = None
|
|
777
|
+
|
|
778
|
+
if is_not_empty(modified_by):
|
|
779
|
+
if isinstance(modified_by, MerchantUser):
|
|
780
|
+
modified_by_username = modified_by.username
|
|
781
|
+
program.modified_by = modified_by.create_ndb_key()
|
|
782
|
+
|
|
783
|
+
program.modified_by_username = modified_by_username
|
|
784
|
+
|
|
785
|
+
program.put()
|
|
786
|
+
|
|
787
|
+
if program.is_published:
|
|
788
|
+
merchant_acct = program.merchant_acct
|
|
789
|
+
#merchant_acct.remove_tier_program_from_published_tier_program_configuration(program.key_in_str)
|
|
790
|
+
merchant_acct.remove_program_from_published_program_configuration(program.key_in_str)
|
|
791
|
+
|
|
792
|
+
remove_schedule_program(program)
|
|
793
|
+
|
|
701
794
|
@staticmethod
|
|
702
795
|
def create(merchant_acct, label=None, is_tier_recycle=True, is_show_progress=True, reward_format=None,
|
|
703
796
|
desc=None, start_date=None, end_date=None, created_by=None):
|
|
@@ -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.5 → trex-model-1.5.0}/trexmodel/models/datastore/redemption_catalogue_models.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{trex-model-1.4.5 → trex-model-1.5.0}/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
|