Prechádzať zdrojové kódy

cộng quyền lợi renew và fix up role cms

student 6 hodín pred
rodič
commit
f49f42adfb

+ 31 - 0
KittyFallWs/KittyFallWs/src/com/vas/kittyfallwsvas/wsfw/database/WsProcessUtils.java

@@ -159,6 +159,8 @@ public class WsProcessUtils extends DbProcessorAbstract {
         PreparedStatement updateRegister = null;
         PreparedStatement selectChargeId = null;
         PreparedStatement insertCharge = null;
+        PreparedStatement updateTurn = null;
+        PreparedStatement insertTurn = null;
         PreparedStatement updateInbox = null;
         ResultSet registerRs = null;
         ResultSet chargeIdRs = null;
@@ -284,6 +286,31 @@ public class WsProcessUtils extends DbProcessorAbstract {
                 }
             }
 
+            // Do not call ADD_TURN here because that procedure commits internally.
+            // Keep the turn credit in the same durable transaction as renew/inbox so
+            // a rollback or replay can never credit the subscriber twice.
+            updateTurn = connection.prepareStatement("UPDATE LUCKY_SPIN SET "
+                    + "ADDED=NVL(ADDED, 0)+?, LAST_UPDATE=SYSDATE "
+                    + "WHERE ID=(SELECT ID FROM LUCKY_SPIN WHERE MSISDN=? AND ROWNUM=1)");
+            setQueryTimeout(updateTurn);
+            updateTurn.setInt(1, event.getProductNumberSpin());
+            updateTurn.setString(2, event.getMsisdn());
+            int updatedTurnRows = updateTurn.executeUpdate();
+            if (updatedTurnRows == 0) {
+                insertTurn = connection.prepareStatement("INSERT INTO LUCKY_SPIN "
+                        + "(ID, MSISDN, ADDED, USED, INSERT_TIME, EXPIRE_TIME, LAST_UPDATE, CHANNEL_ADD) "
+                        + "VALUES (LUCKY_SPIN_SEQ.NEXTVAL, ?, ?, 0, SYSDATE, SYSDATE+7, SYSDATE, 1)");
+                setQueryTimeout(insertTurn);
+                insertTurn.setString(1, event.getMsisdn());
+                insertTurn.setInt(2, event.getProductNumberSpin());
+                if (insertTurn.executeUpdate() != 1) {
+                    throw new SQLException("LUCKY_SPIN insert affected unexpected row count");
+                }
+            } else if (updatedTurnRows != 1) {
+                throw new SQLException("LUCKY_SPIN update affected unexpected row count: "
+                        + updatedTurnRows);
+            }
+
             updateInbox = connection.prepareStatement("UPDATE RESULT_REQUEST_INBOX SET "
                     + "STATUS='PROCESSED', CHARGE_LOG_ID=?, PROCESSED_TIME=SYSTIMESTAMP, "
                     + "UPDATED_TIME=SYSTIMESTAMP WHERE EVENT_ID=?");
@@ -297,6 +324,8 @@ public class WsProcessUtils extends DbProcessorAbstract {
                 throw new SQLException("RESULT_REQUEST_INBOX final update affected unexpected row count");
             }
             connection.commit();
+            logger.info("add turn success Renew " + event.getMsisdn()
+                    + ", turn " + event.getProductNumberSpin());
             return 0;
         } catch (SQLException ex) {
             if (connection != null) {
@@ -312,6 +341,8 @@ public class WsProcessUtils extends DbProcessorAbstract {
             closeResultSet(registerRs);
             closeResultSet(duplicateRs);
             closeStatement(updateInbox);
+            closeStatement(insertTurn);
+            closeStatement(updateTurn);
             closeStatement(insertCharge);
             closeStatement(selectChargeId);
             closeStatement(updateRegister);

+ 1 - 1
KittyFallWs/KittyFallWs/src/com/vas/webservices/KittyFallWs.java

@@ -153,7 +153,7 @@ public class KittyFallWs extends WebserviceAbstract {
                 chargeLog.setStatus(Common.Constant.RENEW_STATUS);
                 db.iInsertChargeLog(chargeLog);
             }
-//            db.addTurnSpin(msisdn,productInfo.getNumberSpin());
+            db.addTurnSpin(msisdn,productInfo.getNumberSpin());
             // send message
             String message;
             message = MessageResponse.get(Common.Message.RENEW_SUCCESS,

+ 13 - 2
Kitty_Fall/Kitty_Fall/Kitty_Fall.Cms/Controllers/AuthController.cs

@@ -68,12 +68,23 @@ public class AuthController : Controller
             if (!string.IsNullOrWhiteSpace(accountRole))
             {
                 var normalizedRole = accountRole.ToUpperInvariant();
+                // Role CODE is the stable identity stored on the account. Resolve it
+                // first so a different role NAME cannot accidentally win the OR query.
                 role = await _db.Roles
                     .AsNoTracking()
                     .FirstOrDefaultAsync(x =>
                         (x.Status ?? CommonErrorCode.STATUS_ACTIVE) == CommonErrorCode.STATUS_ACTIVE &&
-                        (((x.Code ?? string.Empty).ToUpper() == normalizedRole) ||
-                         ((x.Name ?? string.Empty).ToUpper() == normalizedRole)));
+                        (x.Code ?? string.Empty).ToUpper() == normalizedRole);
+
+                // Backward compatibility for old ACCOUNT_ADMIN rows that stored role NAME.
+                if (role == null)
+                {
+                    role = await _db.Roles
+                        .AsNoTracking()
+                        .FirstOrDefaultAsync(x =>
+                            (x.Status ?? CommonErrorCode.STATUS_ACTIVE) == CommonErrorCode.STATUS_ACTIVE &&
+                            (x.Name ?? string.Empty).ToUpper() == normalizedRole);
+                }
             }
 
             var permissions = new List<CmsPermissionGrant>();

+ 53 - 13
Kitty_Fall/Kitty_Fall/Kitty_Fall.Cms/Controllers/CmsAccountController.cs

@@ -177,6 +177,15 @@ public class CmsAccountController : CmsAuthorizedController
                 return Json(new { errorCode = 400, message = "Role code is required." });
             }
 
+            var duplicateCode = await _db.Roles.AsNoTracking().AnyAsync(x =>
+                x.Id != role.Id
+                && x.Code != null
+                && x.Code.ToUpper() == code);
+            if (duplicateCode)
+            {
+                return Json(new { errorCode = 400, message = "Role code already exists. Each role must have a unique code." });
+            }
+
             if (role.Id == 0)
             {
                 var newId = await Database.DbLogic.GenIdAsync(_db, "ROLE_SEQ") ?? 0;
@@ -253,24 +262,55 @@ public class CmsAccountController : CmsAuthorizedController
 
         try
         {
-            var existing = await _db.RolePermissions.Where(x => x.RoleId == roleId).ToListAsync();
-            _db.RolePermissions.RemoveRange(existing);
+            var roleExists = await _db.Roles.AsNoTracking().AnyAsync(x => x.Id == roleId);
+            if (!roleExists)
+            {
+                return Json(new { errorCode = 404, message = "Role not found." });
+            }
 
-            if (permissionIds != null)
+            var requestedPermissionIds = (permissionIds ?? new List<decimal>())
+                .Distinct()
+                .ToList();
+            var validPermissionIds = await _db.Permissions.AsNoTracking()
+                .Where(x => requestedPermissionIds.Contains(x.Id))
+                .Select(x => x.Id)
+                .ToListAsync();
+            if (validPermissionIds.Count != requestedPermissionIds.Count)
             {
-                foreach (var pId in permissionIds)
+                return Json(new { errorCode = 400, message = "One or more permissions are invalid." });
+            }
+
+            var replacements = new List<RolePermission>();
+            foreach (var pId in validPermissionIds)
+            {
+                replacements.Add(new RolePermission
                 {
-                    _db.RolePermissions.Add(new RolePermission
-                    {
-                        Id = (decimal)await Database.DbLogic.GenIdAsync(_db, "ROLE_PERMISSION_SEQ"),
-                        RoleId = roleId,
-                        PermissionId = pId,
-                        Status = "ACTIVE"
-                    });
-                }
+                    Id = (decimal)await Database.DbLogic.GenIdAsync(_db, "ROLE_PERMISSION_SEQ"),
+                    RoleId = roleId,
+                    PermissionId = pId,
+                    Status = "ACTIVE"
+                });
+            }
+
+            await using var transaction = await _db.Database.BeginTransactionAsync();
+            try
+            {
+                // This delete is deliberately scoped to the role being edited.
+                await _db.RolePermissions
+                    .Where(x => x.RoleId == roleId)
+                    .ExecuteDeleteAsync();
+
+                _db.RolePermissions.AddRange(replacements);
+
+                await _db.SaveChangesAsync();
+                await transaction.CommitAsync();
+            }
+            catch
+            {
+                await transaction.RollbackAsync();
+                throw;
             }
 
-            await _db.SaveChangesAsync();
             return Json(new { errorCode = 200, message = "Success" });
         }
         catch (Exception ex)

+ 14 - 1
Kitty_Fall/Kitty_Fall/Kitty_Fall.Woker/Services/GameRewardPayoutWorker.cs

@@ -114,12 +114,14 @@ namespace Kitty_Fall.Woker.Services
                     return;
                 }
 
+                var payoutPackageName = GetPackageName(rewardLog);
                 var addPointRes = DotnetLib.Mytel.AddingPointLogic.AddingPointHandler(
                     log,
                     configuration,
                     rewardLog.Msisdn,
                     rewardLog.RewardLogId.ToString(CultureInfo.InvariantCulture),
-                    GetPackageName(rewardLog));
+                    payoutPackageName);
+
                 var responseStatus = addPointRes?.result?.status;
                 var hasResponseCode = int.TryParse(
                     responseStatus,
@@ -144,6 +146,17 @@ namespace Kitty_Fall.Woker.Services
                 if (isSuccess)
                 {
                     rewardLog.Status = StatusSuccess;
+                    dbContext.ChargeLogs.Add(new ChargeLog
+                    {
+                        Id = await NextDecimalIdAsync(dbContext, "CHARGE_LOG_SEQ"),
+                        Msisdn = rewardLog.Msisdn,
+                        Fee = -rewardLog.RewardValue,
+                        ChargeTime = now,
+                        InsertTime = now,
+                        Description = $"Exchange expense {rewardLog.RewardType?.ToUpperInvariant()} - {payoutPackageName}",
+                        AccountId = null,
+                        Status = CommonConstants.UNCHARGE_STATUS
+                    });
                     await UpdateLimitUsageAsync(dbContext, rewardLog, now, cancellationToken);
                     await dbContext.SaveChangesAsync(cancellationToken);
                     await SendSuccessMtAsync(dbContext, rewardLog, cancellationToken);