浏览代码

upgrade for 07/2024:
- recharge page
- fix bugs
- search page

sungroup 1 年之前
父节点
当前提交
9f9ecd04db
共有 50 个文件被更改,包括 2353 次插入172 次删除
  1. 37 0
      WebPortal/Pulsa/Controllers/HomeController.cs
  2. 11 0
      WebPortal/Pulsa/Models/ErrorViewModel.cs
  3. 26 0
      WebPortal/Pulsa/Program.cs
  4. 28 0
      WebPortal/Pulsa/Properties/launchSettings.json
  5. 7 0
      WebPortal/Pulsa/Pulsa.csproj
  6. 57 0
      WebPortal/Pulsa/Startup.cs
  7. 8 0
      WebPortal/Pulsa/Views/Home/Index.cshtml
  8. 6 0
      WebPortal/Pulsa/Views/Home/Privacy.cshtml
  9. 25 0
      WebPortal/Pulsa/Views/Shared/Error.cshtml
  10. 48 0
      WebPortal/Pulsa/Views/Shared/_Layout.cshtml
  11. 2 0
      WebPortal/Pulsa/Views/Shared/_ValidationScriptsPartial.cshtml
  12. 3 0
      WebPortal/Pulsa/Views/_ViewImports.cshtml
  13. 3 0
      WebPortal/Pulsa/Views/_ViewStart.cshtml
  14. 9 0
      WebPortal/Pulsa/appsettings.Development.json
  15. 10 0
      WebPortal/Pulsa/appsettings.json
  16. 71 0
      WebPortal/Pulsa/wwwroot/css/site.css
  17. 二进制
      WebPortal/Pulsa/wwwroot/favicon.ico
  18. 4 0
      WebPortal/Pulsa/wwwroot/js/site.js
  19. 22 0
      WebPortal/Pulsa/wwwroot/lib/bootstrap/LICENSE
  20. 12 0
      WebPortal/Pulsa/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt
  21. 432 0
      WebPortal/Pulsa/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js
  22. 4 0
      WebPortal/Pulsa/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js
  23. 22 0
      WebPortal/Pulsa/wwwroot/lib/jquery-validation/LICENSE.md
  24. 36 0
      WebPortal/Pulsa/wwwroot/lib/jquery/LICENSE.txt
  25. 7 1
      WebPortal/WebPortal.sln
  26. 80 0
      WebPortal/WebPortal/Controllers/CustomerCareController.cs
  27. 8 3
      WebPortal/WebPortal/Controllers/HomeController.cs
  28. 61 2
      WebPortal/WebPortal/Controllers/SubscriberController.cs
  29. 8 0
      WebPortal/WebPortal/Extensions/CommonUtils.cs
  30. 82 1
      WebPortal/WebPortal/Texts/Lang.Designer.cs
  31. 28 1
      WebPortal/WebPortal/Texts/Lang.fr.resx
  32. 28 1
      WebPortal/WebPortal/Texts/Lang.resx
  33. 358 0
      WebPortal/WebPortal/Views/CustomerCare/Search.cshtml
  34. 0 48
      WebPortal/WebPortal/Views/Home/Mosan-Dell-Vostro.cshtml
  35. 218 0
      WebPortal/WebPortal/Views/Home/Recharge.cshtml
  36. 11 2
      WebPortal/WebPortal/Views/Home/RegisterAccount.cshtml
  37. 6 0
      WebPortal/WebPortal/Views/Home/_TopBanner.cshtml
  38. 1 1
      WebPortal/WebPortal/Views/Subscriber/TrialService.cshtml
  39. 3 3
      WebPortal/WebPortal/Views/Subscriber/UpdateSubInfo.cshtml
  40. 8 1
      WebPortal/WebPortal/Views/_ViewStart.cshtml
  41. 2 2
      WebPortal/WebPortal/appsettings.json
  42. 41 0
      WebPortal/WebPortal/wwwroot/css/recharge.css
  43. 31 26
      WebPortal/WebPortal/wwwroot/css/style.css
  44. 二进制
      WebPortal/WebPortal/wwwroot/image/recharge.png
  45. 28 14
      WebPortalWs/Timor_WebPortalWs/src/com/vas/wsfw/database/WsProcessUtils.java
  46. 0 29
      WebPortalWs/Timor_WebPortalWs/src/com/vas/wsfw/main/Dog.java
  47. 0 30
      WebPortalWs/Timor_WebPortalWs/src/com/vas/wsfw/main/test.java
  48. 9 7
      WebPortalWs/etc/database.xml
  49. 57 0
      WebPortalWs/log/error/error.log.2024-07-24
  50. 395 0
      WebPortalWs/log/full/full.log.2024-07-24

+ 37 - 0
WebPortal/Pulsa/Controllers/HomeController.cs

@@ -0,0 +1,37 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Logging;
+using Pulsa.Models;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Pulsa.Controllers
+{
+    public class HomeController : Controller
+    {
+        private readonly ILogger<HomeController> _logger;
+
+        public HomeController(ILogger<HomeController> logger)
+        {
+            _logger = logger;
+        }
+
+        public IActionResult Index()
+        {
+            return View();
+        }
+
+        public IActionResult Privacy()
+        {
+            return View();
+        }
+
+        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
+        public IActionResult Error()
+        {
+            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
+        }
+    }
+}

+ 11 - 0
WebPortal/Pulsa/Models/ErrorViewModel.cs

@@ -0,0 +1,11 @@
+using System;
+
+namespace Pulsa.Models
+{
+    public class ErrorViewModel
+    {
+        public string RequestId { get; set; }
+
+        public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
+    }
+}

+ 26 - 0
WebPortal/Pulsa/Program.cs

@@ -0,0 +1,26 @@
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Pulsa
+{
+    public class Program
+    {
+        public static void Main(string[] args)
+        {
+            CreateHostBuilder(args).Build().Run();
+        }
+
+        public static IHostBuilder CreateHostBuilder(string[] args) =>
+            Host.CreateDefaultBuilder(args)
+                .ConfigureWebHostDefaults(webBuilder =>
+                {
+                    webBuilder.UseStartup<Startup>();
+                });
+    }
+}

+ 28 - 0
WebPortal/Pulsa/Properties/launchSettings.json

@@ -0,0 +1,28 @@
+{
+  "iisSettings": {
+    "windowsAuthentication": false,
+    "anonymousAuthentication": true,
+    "iisExpress": {
+      "applicationUrl": "http://localhost:4619",
+      "sslPort": 44305
+    }
+  },
+  "profiles": {
+    "IIS Express": {
+      "commandName": "IISExpress",
+      "launchBrowser": true,
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    },
+    "Pulsa": {
+      "commandName": "Project",
+      "dotnetRunMessages": "true",
+      "launchBrowser": true,
+      "applicationUrl": "https://localhost:5001;http://localhost:5000",
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    }
+  }
+}

+ 7 - 0
WebPortal/Pulsa/Pulsa.csproj

@@ -0,0 +1,7 @@
+<Project Sdk="Microsoft.NET.Sdk.Web">
+
+  <PropertyGroup>
+    <TargetFramework>net5.0</TargetFramework>
+  </PropertyGroup>
+
+</Project>

+ 57 - 0
WebPortal/Pulsa/Startup.cs

@@ -0,0 +1,57 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.HttpsPolicy;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Pulsa
+{
+    public class Startup
+    {
+        public Startup(IConfiguration configuration)
+        {
+            Configuration = configuration;
+        }
+
+        public IConfiguration Configuration { get; }
+
+        // This method gets called by the runtime. Use this method to add services to the container.
+        public void ConfigureServices(IServiceCollection services)
+        {
+            services.AddControllersWithViews();
+        }
+
+        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+        {
+            if (env.IsDevelopment())
+            {
+                app.UseDeveloperExceptionPage();
+            }
+            else
+            {
+                app.UseExceptionHandler("/Home/Error");
+                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
+                app.UseHsts();
+            }
+            app.UseHttpsRedirection();
+            app.UseStaticFiles();
+
+            app.UseRouting();
+
+            app.UseAuthorization();
+
+            app.UseEndpoints(endpoints =>
+            {
+                endpoints.MapControllerRoute(
+                    name: "default",
+                    pattern: "{controller=Home}/{action=Index}/{id?}");
+            });
+        }
+    }
+}

+ 8 - 0
WebPortal/Pulsa/Views/Home/Index.cshtml

@@ -0,0 +1,8 @@
+@{
+    ViewData["Title"] = "Home Page";
+}
+
+<div class="text-center">
+    <h1 class="display-4">Welcome</h1>
+    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
+</div>

+ 6 - 0
WebPortal/Pulsa/Views/Home/Privacy.cshtml

@@ -0,0 +1,6 @@
+@{
+    ViewData["Title"] = "Privacy Policy";
+}
+<h1>@ViewData["Title"]</h1>
+
+<p>Use this page to detail your site's privacy policy.</p>

+ 25 - 0
WebPortal/Pulsa/Views/Shared/Error.cshtml

@@ -0,0 +1,25 @@
+@model ErrorViewModel
+@{
+    ViewData["Title"] = "Error";
+}
+
+<h1 class="text-danger">Error.</h1>
+<h2 class="text-danger">An error occurred while processing your request.</h2>
+
+@if (Model.ShowRequestId)
+{
+    <p>
+        <strong>Request ID:</strong> <code>@Model.RequestId</code>
+    </p>
+}
+
+<h3>Development Mode</h3>
+<p>
+    Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
+</p>
+<p>
+    <strong>The Development environment shouldn't be enabled for deployed applications.</strong>
+    It can result in displaying sensitive information from exceptions to end users.
+    For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
+    and restarting the app.
+</p>

+ 48 - 0
WebPortal/Pulsa/Views/Shared/_Layout.cshtml

@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>@ViewData["Title"] - Pulsa</title>
+    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
+    <link rel="stylesheet" href="~/css/site.css" />
+</head>
+<body>
+    <header>
+        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
+            <div class="container">
+                <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">Pulsa</a>
+                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
+                        aria-expanded="false" aria-label="Toggle navigation">
+                    <span class="navbar-toggler-icon"></span>
+                </button>
+                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
+                    <ul class="navbar-nav flex-grow-1">
+                        <li class="nav-item">
+                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
+                        </li>
+                        <li class="nav-item">
+                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
+                        </li>
+                    </ul>
+                </div>
+            </div>
+        </nav>
+    </header>
+    <div class="container">
+        <main role="main" class="pb-3">
+            @RenderBody()
+        </main>
+    </div>
+
+    <footer class="border-top footer text-muted">
+        <div class="container">
+            &copy; 2024 - Pulsa - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
+        </div>
+    </footer>
+    <script src="~/lib/jquery/dist/jquery.min.js"></script>
+    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
+    <script src="~/js/site.js" asp-append-version="true"></script>
+    @await RenderSectionAsync("Scripts", required: false)
+</body>
+</html>

+ 2 - 0
WebPortal/Pulsa/Views/Shared/_ValidationScriptsPartial.cshtml

@@ -0,0 +1,2 @@
+<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
+<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>

+ 3 - 0
WebPortal/Pulsa/Views/_ViewImports.cshtml

@@ -0,0 +1,3 @@
+@using Pulsa
+@using Pulsa.Models
+@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

+ 3 - 0
WebPortal/Pulsa/Views/_ViewStart.cshtml

@@ -0,0 +1,3 @@
+@{
+    Layout = "_Layout";
+}

+ 9 - 0
WebPortal/Pulsa/appsettings.Development.json

@@ -0,0 +1,9 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Information",
+      "Microsoft": "Warning",
+      "Microsoft.Hosting.Lifetime": "Information"
+    }
+  }
+}

+ 10 - 0
WebPortal/Pulsa/appsettings.json

@@ -0,0 +1,10 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Information",
+      "Microsoft": "Warning",
+      "Microsoft.Hosting.Lifetime": "Information"
+    }
+  },
+  "AllowedHosts": "*"
+}

+ 71 - 0
WebPortal/Pulsa/wwwroot/css/site.css

@@ -0,0 +1,71 @@
+/* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
+for details on configuring this project to bundle and minify static web assets. */
+
+a.navbar-brand {
+  white-space: normal;
+  text-align: center;
+  word-break: break-all;
+}
+
+/* Provide sufficient contrast against white background */
+a {
+  color: #0366d6;
+}
+
+.btn-primary {
+  color: #fff;
+  background-color: #1b6ec2;
+  border-color: #1861ac;
+}
+
+.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
+  color: #fff;
+  background-color: #1b6ec2;
+  border-color: #1861ac;
+}
+
+/* Sticky footer styles
+-------------------------------------------------- */
+html {
+  font-size: 14px;
+}
+@media (min-width: 768px) {
+  html {
+    font-size: 16px;
+  }
+}
+
+.border-top {
+  border-top: 1px solid #e5e5e5;
+}
+.border-bottom {
+  border-bottom: 1px solid #e5e5e5;
+}
+
+.box-shadow {
+  box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
+}
+
+button.accept-policy {
+  font-size: 1rem;
+  line-height: inherit;
+}
+
+/* Sticky footer styles
+-------------------------------------------------- */
+html {
+  position: relative;
+  min-height: 100%;
+}
+
+body {
+  /* Margin bottom by footer height */
+  margin-bottom: 60px;
+}
+.footer {
+  position: absolute;
+  bottom: 0;
+  width: 100%;
+  white-space: nowrap;
+  line-height: 60px; /* Vertically center the text there */
+}

二进制
WebPortal/Pulsa/wwwroot/favicon.ico


+ 4 - 0
WebPortal/Pulsa/wwwroot/js/site.js

@@ -0,0 +1,4 @@
+// Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
+// for details on configuring this project to bundle and minify static web assets.
+
+// Write your JavaScript code.

+ 22 - 0
WebPortal/Pulsa/wwwroot/lib/bootstrap/LICENSE

@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2011-2018 Twitter, Inc.
+Copyright (c) 2011-2018 The Bootstrap Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

+ 12 - 0
WebPortal/Pulsa/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt

@@ -0,0 +1,12 @@
+Copyright (c) .NET Foundation. All rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use
+these files except in compliance with the License. You may obtain a copy of the
+License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software distributed
+under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+CONDITIONS OF ANY KIND, either express or implied. See the License for the
+specific language governing permissions and limitations under the License.

+ 432 - 0
WebPortal/Pulsa/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js

@@ -0,0 +1,432 @@
+// Unobtrusive validation support library for jQuery and jQuery Validate
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+// @version v3.2.11
+
+/*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */
+/*global document: false, jQuery: false */
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        // AMD. Register as an anonymous module.
+        define("jquery.validate.unobtrusive", ['jquery-validation'], factory);
+    } else if (typeof module === 'object' && module.exports) {
+        // CommonJS-like environments that support module.exports     
+        module.exports = factory(require('jquery-validation'));
+    } else {
+        // Browser global
+        jQuery.validator.unobtrusive = factory(jQuery);
+    }
+}(function ($) {
+    var $jQval = $.validator,
+        adapters,
+        data_validation = "unobtrusiveValidation";
+
+    function setValidationValues(options, ruleName, value) {
+        options.rules[ruleName] = value;
+        if (options.message) {
+            options.messages[ruleName] = options.message;
+        }
+    }
+
+    function splitAndTrim(value) {
+        return value.replace(/^\s+|\s+$/g, "").split(/\s*,\s*/g);
+    }
+
+    function escapeAttributeValue(value) {
+        // As mentioned on http://api.jquery.com/category/selectors/
+        return value.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g, "\\$1");
+    }
+
+    function getModelPrefix(fieldName) {
+        return fieldName.substr(0, fieldName.lastIndexOf(".") + 1);
+    }
+
+    function appendModelPrefix(value, prefix) {
+        if (value.indexOf("*.") === 0) {
+            value = value.replace("*.", prefix);
+        }
+        return value;
+    }
+
+    function onError(error, inputElement) {  // 'this' is the form element
+        var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"),
+            replaceAttrValue = container.attr("data-valmsg-replace"),
+            replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null;
+
+        container.removeClass("field-validation-valid").addClass("field-validation-error");
+        error.data("unobtrusiveContainer", container);
+
+        if (replace) {
+            container.empty();
+            error.removeClass("input-validation-error").appendTo(container);
+        }
+        else {
+            error.hide();
+        }
+    }
+
+    function onErrors(event, validator) {  // 'this' is the form element
+        var container = $(this).find("[data-valmsg-summary=true]"),
+            list = container.find("ul");
+
+        if (list && list.length && validator.errorList.length) {
+            list.empty();
+            container.addClass("validation-summary-errors").removeClass("validation-summary-valid");
+
+            $.each(validator.errorList, function () {
+                $("<li />").html(this.message).appendTo(list);
+            });
+        }
+    }
+
+    function onSuccess(error) {  // 'this' is the form element
+        var container = error.data("unobtrusiveContainer");
+
+        if (container) {
+            var replaceAttrValue = container.attr("data-valmsg-replace"),
+                replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) : null;
+
+            container.addClass("field-validation-valid").removeClass("field-validation-error");
+            error.removeData("unobtrusiveContainer");
+
+            if (replace) {
+                container.empty();
+            }
+        }
+    }
+
+    function onReset(event) {  // 'this' is the form element
+        var $form = $(this),
+            key = '__jquery_unobtrusive_validation_form_reset';
+        if ($form.data(key)) {
+            return;
+        }
+        // Set a flag that indicates we're currently resetting the form.
+        $form.data(key, true);
+        try {
+            $form.data("validator").resetForm();
+        } finally {
+            $form.removeData(key);
+        }
+
+        $form.find(".validation-summary-errors")
+            .addClass("validation-summary-valid")
+            .removeClass("validation-summary-errors");
+        $form.find(".field-validation-error")
+            .addClass("field-validation-valid")
+            .removeClass("field-validation-error")
+            .removeData("unobtrusiveContainer")
+            .find(">*")  // If we were using valmsg-replace, get the underlying error
+            .removeData("unobtrusiveContainer");
+    }
+
+    function validationInfo(form) {
+        var $form = $(form),
+            result = $form.data(data_validation),
+            onResetProxy = $.proxy(onReset, form),
+            defaultOptions = $jQval.unobtrusive.options || {},
+            execInContext = function (name, args) {
+                var func = defaultOptions[name];
+                func && $.isFunction(func) && func.apply(form, args);
+            };
+
+        if (!result) {
+            result = {
+                options: {  // options structure passed to jQuery Validate's validate() method
+                    errorClass: defaultOptions.errorClass || "input-validation-error",
+                    errorElement: defaultOptions.errorElement || "span",
+                    errorPlacement: function () {
+                        onError.apply(form, arguments);
+                        execInContext("errorPlacement", arguments);
+                    },
+                    invalidHandler: function () {
+                        onErrors.apply(form, arguments);
+                        execInContext("invalidHandler", arguments);
+                    },
+                    messages: {},
+                    rules: {},
+                    success: function () {
+                        onSuccess.apply(form, arguments);
+                        execInContext("success", arguments);
+                    }
+                },
+                attachValidation: function () {
+                    $form
+                        .off("reset." + data_validation, onResetProxy)
+                        .on("reset." + data_validation, onResetProxy)
+                        .validate(this.options);
+                },
+                validate: function () {  // a validation function that is called by unobtrusive Ajax
+                    $form.validate();
+                    return $form.valid();
+                }
+            };
+            $form.data(data_validation, result);
+        }
+
+        return result;
+    }
+
+    $jQval.unobtrusive = {
+        adapters: [],
+
+        parseElement: function (element, skipAttach) {
+            /// <summary>
+            /// Parses a single HTML element for unobtrusive validation attributes.
+            /// </summary>
+            /// <param name="element" domElement="true">The HTML element to be parsed.</param>
+            /// <param name="skipAttach" type="Boolean">[Optional] true to skip attaching the
+            /// validation to the form. If parsing just this single element, you should specify true.
+            /// If parsing several elements, you should specify false, and manually attach the validation
+            /// to the form when you are finished. The default is false.</param>
+            var $element = $(element),
+                form = $element.parents("form")[0],
+                valInfo, rules, messages;
+
+            if (!form) {  // Cannot do client-side validation without a form
+                return;
+            }
+
+            valInfo = validationInfo(form);
+            valInfo.options.rules[element.name] = rules = {};
+            valInfo.options.messages[element.name] = messages = {};
+
+            $.each(this.adapters, function () {
+                var prefix = "data-val-" + this.name,
+                    message = $element.attr(prefix),
+                    paramValues = {};
+
+                if (message !== undefined) {  // Compare against undefined, because an empty message is legal (and falsy)
+                    prefix += "-";
+
+                    $.each(this.params, function () {
+                        paramValues[this] = $element.attr(prefix + this);
+                    });
+
+                    this.adapt({
+                        element: element,
+                        form: form,
+                        message: message,
+                        params: paramValues,
+                        rules: rules,
+                        messages: messages
+                    });
+                }
+            });
+
+            $.extend(rules, { "__dummy__": true });
+
+            if (!skipAttach) {
+                valInfo.attachValidation();
+            }
+        },
+
+        parse: function (selector) {
+            /// <summary>
+            /// Parses all the HTML elements in the specified selector. It looks for input elements decorated
+            /// with the [data-val=true] attribute value and enables validation according to the data-val-*
+            /// attribute values.
+            /// </summary>
+            /// <param name="selector" type="String">Any valid jQuery selector.</param>
+
+            // $forms includes all forms in selector's DOM hierarchy (parent, children and self) that have at least one
+            // element with data-val=true
+            var $selector = $(selector),
+                $forms = $selector.parents()
+                    .addBack()
+                    .filter("form")
+                    .add($selector.find("form"))
+                    .has("[data-val=true]");
+
+            $selector.find("[data-val=true]").each(function () {
+                $jQval.unobtrusive.parseElement(this, true);
+            });
+
+            $forms.each(function () {
+                var info = validationInfo(this);
+                if (info) {
+                    info.attachValidation();
+                }
+            });
+        }
+    };
+
+    adapters = $jQval.unobtrusive.adapters;
+
+    adapters.add = function (adapterName, params, fn) {
+        /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation.</summary>
+        /// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
+        /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
+        /// <param name="params" type="Array" optional="true">[Optional] An array of parameter names (strings) that will
+        /// be extracted from the data-val-nnnn-mmmm HTML attributes (where nnnn is the adapter name, and
+        /// mmmm is the parameter name).</param>
+        /// <param name="fn" type="Function">The function to call, which adapts the values from the HTML
+        /// attributes into jQuery Validate rules and/or messages.</param>
+        /// <returns type="jQuery.validator.unobtrusive.adapters" />
+        if (!fn) {  // Called with no params, just a function
+            fn = params;
+            params = [];
+        }
+        this.push({ name: adapterName, params: params, adapt: fn });
+        return this;
+    };
+
+    adapters.addBool = function (adapterName, ruleName) {
+        /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
+        /// the jQuery Validate validation rule has no parameter values.</summary>
+        /// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
+        /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
+        /// <param name="ruleName" type="String" optional="true">[Optional] The name of the jQuery Validate rule. If not provided, the value
+        /// of adapterName will be used instead.</param>
+        /// <returns type="jQuery.validator.unobtrusive.adapters" />
+        return this.add(adapterName, function (options) {
+            setValidationValues(options, ruleName || adapterName, true);
+        });
+    };
+
+    adapters.addMinMax = function (adapterName, minRuleName, maxRuleName, minMaxRuleName, minAttribute, maxAttribute) {
+        /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
+        /// the jQuery Validate validation has three potential rules (one for min-only, one for max-only, and
+        /// one for min-and-max). The HTML parameters are expected to be named -min and -max.</summary>
+        /// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
+        /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
+        /// <param name="minRuleName" type="String">The name of the jQuery Validate rule to be used when you only
+        /// have a minimum value.</param>
+        /// <param name="maxRuleName" type="String">The name of the jQuery Validate rule to be used when you only
+        /// have a maximum value.</param>
+        /// <param name="minMaxRuleName" type="String">The name of the jQuery Validate rule to be used when you
+        /// have both a minimum and maximum value.</param>
+        /// <param name="minAttribute" type="String" optional="true">[Optional] The name of the HTML attribute that
+        /// contains the minimum value. The default is "min".</param>
+        /// <param name="maxAttribute" type="String" optional="true">[Optional] The name of the HTML attribute that
+        /// contains the maximum value. The default is "max".</param>
+        /// <returns type="jQuery.validator.unobtrusive.adapters" />
+        return this.add(adapterName, [minAttribute || "min", maxAttribute || "max"], function (options) {
+            var min = options.params.min,
+                max = options.params.max;
+
+            if (min && max) {
+                setValidationValues(options, minMaxRuleName, [min, max]);
+            }
+            else if (min) {
+                setValidationValues(options, minRuleName, min);
+            }
+            else if (max) {
+                setValidationValues(options, maxRuleName, max);
+            }
+        });
+    };
+
+    adapters.addSingleVal = function (adapterName, attribute, ruleName) {
+        /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
+        /// the jQuery Validate validation rule has a single value.</summary>
+        /// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
+        /// in the data-val-nnnn HTML attribute(where nnnn is the adapter name).</param>
+        /// <param name="attribute" type="String">[Optional] The name of the HTML attribute that contains the value.
+        /// The default is "val".</param>
+        /// <param name="ruleName" type="String" optional="true">[Optional] The name of the jQuery Validate rule. If not provided, the value
+        /// of adapterName will be used instead.</param>
+        /// <returns type="jQuery.validator.unobtrusive.adapters" />
+        return this.add(adapterName, [attribute || "val"], function (options) {
+            setValidationValues(options, ruleName || adapterName, options.params[attribute]);
+        });
+    };
+
+    $jQval.addMethod("__dummy__", function (value, element, params) {
+        return true;
+    });
+
+    $jQval.addMethod("regex", function (value, element, params) {
+        var match;
+        if (this.optional(element)) {
+            return true;
+        }
+
+        match = new RegExp(params).exec(value);
+        return (match && (match.index === 0) && (match[0].length === value.length));
+    });
+
+    $jQval.addMethod("nonalphamin", function (value, element, nonalphamin) {
+        var match;
+        if (nonalphamin) {
+            match = value.match(/\W/g);
+            match = match && match.length >= nonalphamin;
+        }
+        return match;
+    });
+
+    if ($jQval.methods.extension) {
+        adapters.addSingleVal("accept", "mimtype");
+        adapters.addSingleVal("extension", "extension");
+    } else {
+        // for backward compatibility, when the 'extension' validation method does not exist, such as with versions
+        // of JQuery Validation plugin prior to 1.10, we should use the 'accept' method for
+        // validating the extension, and ignore mime-type validations as they are not supported.
+        adapters.addSingleVal("extension", "extension", "accept");
+    }
+
+    adapters.addSingleVal("regex", "pattern");
+    adapters.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url");
+    adapters.addMinMax("length", "minlength", "maxlength", "rangelength").addMinMax("range", "min", "max", "range");
+    adapters.addMinMax("minlength", "minlength").addMinMax("maxlength", "minlength", "maxlength");
+    adapters.add("equalto", ["other"], function (options) {
+        var prefix = getModelPrefix(options.element.name),
+            other = options.params.other,
+            fullOtherName = appendModelPrefix(other, prefix),
+            element = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(fullOtherName) + "']")[0];
+
+        setValidationValues(options, "equalTo", element);
+    });
+    adapters.add("required", function (options) {
+        // jQuery Validate equates "required" with "mandatory" for checkbox elements
+        if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") {
+            setValidationValues(options, "required", true);
+        }
+    });
+    adapters.add("remote", ["url", "type", "additionalfields"], function (options) {
+        var value = {
+            url: options.params.url,
+            type: options.params.type || "GET",
+            data: {}
+        },
+            prefix = getModelPrefix(options.element.name);
+
+        $.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) {
+            var paramName = appendModelPrefix(fieldName, prefix);
+            value.data[paramName] = function () {
+                var field = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(paramName) + "']");
+                // For checkboxes and radio buttons, only pick up values from checked fields.
+                if (field.is(":checkbox")) {
+                    return field.filter(":checked").val() || field.filter(":hidden").val() || '';
+                }
+                else if (field.is(":radio")) {
+                    return field.filter(":checked").val() || '';
+                }
+                return field.val();
+            };
+        });
+
+        setValidationValues(options, "remote", value);
+    });
+    adapters.add("password", ["min", "nonalphamin", "regex"], function (options) {
+        if (options.params.min) {
+            setValidationValues(options, "minlength", options.params.min);
+        }
+        if (options.params.nonalphamin) {
+            setValidationValues(options, "nonalphamin", options.params.nonalphamin);
+        }
+        if (options.params.regex) {
+            setValidationValues(options, "regex", options.params.regex);
+        }
+    });
+    adapters.add("fileextensions", ["extensions"], function (options) {
+        setValidationValues(options, "extension", options.params.extensions);
+    });
+
+    $(function () {
+        $jQval.unobtrusive.parse(document);
+    });
+
+    return $jQval.unobtrusive;
+}));

文件差异内容过多而无法显示
+ 4 - 0
WebPortal/Pulsa/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js


+ 22 - 0
WebPortal/Pulsa/wwwroot/lib/jquery-validation/LICENSE.md

@@ -0,0 +1,22 @@
+The MIT License (MIT)
+=====================
+
+Copyright Jörn Zaefferer
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

+ 36 - 0
WebPortal/Pulsa/wwwroot/lib/jquery/LICENSE.txt

@@ -0,0 +1,36 @@
+Copyright JS Foundation and other contributors, https://js.foundation/
+
+This software consists of voluntary contributions made by many
+individuals. For exact contribution history, see the revision history
+available at https://github.com/jquery/jquery
+
+The following license applies to all parts of this software except as
+documented below:
+
+====
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+====
+
+All files located in the node_modules and external directories are
+externally maintained libraries used by this software which have their
+own licenses; we recommend you read them, as their terms may differ from
+the terms above.

+ 7 - 1
WebPortal/WebPortal.sln

@@ -5,7 +5,9 @@ VisualStudioVersion = 16.0.31624.102
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebPortal", "WebPortal\WebPortal.csproj", "{588DC231-933B-445A-91F2-7D7BC35606AB}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GuestName", "GuestName\GuestName.csproj", "{6EDDA2D4-F695-4DF6-BBBD-F03BD185809B}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Guestname", "GuestName\Guestname.csproj", "{6EDDA2D4-F695-4DF6-BBBD-F03BD185809B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pulsa", "Pulsa\Pulsa.csproj", "{9CC03BE1-8272-44C3-B489-F8BC34197C0B}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -21,6 +23,10 @@ Global
 		{6EDDA2D4-F695-4DF6-BBBD-F03BD185809B}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{6EDDA2D4-F695-4DF6-BBBD-F03BD185809B}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{6EDDA2D4-F695-4DF6-BBBD-F03BD185809B}.Release|Any CPU.Build.0 = Release|Any CPU
+		{9CC03BE1-8272-44C3-B489-F8BC34197C0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{9CC03BE1-8272-44C3-B489-F8BC34197C0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{9CC03BE1-8272-44C3-B489-F8BC34197C0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{9CC03BE1-8272-44C3-B489-F8BC34197C0B}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 80 - 0
WebPortal/WebPortal/Controllers/CustomerCareController.cs

@@ -67,6 +67,86 @@ namespace WebPortal.Controllers
             }
         }
 
+        public ActionResult Search(String keywords, String preview)
+        {
+            // load FAQs
+            try
+            {
+                SetWsClient(ref wsClient);
+                if (keywords != null && keywords.Trim().Length >= 2)
+                {
+                    // search content
+                    wsSearchTreeContentRequest wsRequest = new wsSearchTreeContentRequest(
+                         BaseController.wsUser,
+                         BaseController.wsPassword,
+                         ProductType.ROOT,
+                         keywords,
+                         getCurrentLang());
+                    var wsResponse = wsClient.wsSearchTreeContent(wsRequest);
+                    var listContent = wsResponse.@return.listContent;
+
+                    List<ProductModel> listGroup = new List<ProductModel>();
+                    long tempId = 0;
+                    // group
+                    ProductModel groupModel = null;
+                    List<contentTreeObj> listTemp = new List<contentTreeObj>();
+                    if (listContent != null)
+                    {
+                        foreach (var content in listContent)
+                        {
+                            if (tempId != content.parentId)
+                            {
+                                if (tempId != 0)
+                                {
+                                    // clear
+                                    groupModel.listContent = listTemp.ToArray();
+                                    listGroup.Add(groupModel);
+                                    listTemp.Clear();
+                                    // add new group
+                                    wsGetTreeByIdRequest reqParent = new wsGetTreeByIdRequest(wsUser, wsPassword, content.parentId + "", getCurrentLang());
+                                    var group = wsClient.wsGetTreeById(reqParent).@return.listContent[0];
+                                    groupModel = new ProductModel();
+                                    groupModel.content = group;
+                                    tempId = content.parentId;
+                                }
+                                else
+                                {
+                                    tempId = content.parentId;
+                                    // first time
+                                    wsGetTreeByIdRequest reqParent = new wsGetTreeByIdRequest(wsUser, wsPassword, content.parentId + "", getCurrentLang());
+                                    var group = wsClient.wsGetTreeById(reqParent).@return.listContent[0];
+                                    groupModel = new ProductModel();
+                                    groupModel.content = group;
+                                }
+                                listTemp.Add(content);
+                            }
+                            else
+                            {
+                                listTemp.Add(content);
+                            }
+                        }
+                        // last time
+                        groupModel.listContent = listTemp.ToArray();
+                        listGroup.Add(groupModel);
+                        listTemp.Clear();
+                    }
+
+                    ViewBag.keywords = keywords;
+                    return View(listGroup);
+                }
+                else
+                {
+                    return View();
+                }
+            }
+            catch (Exception ex)
+            {
+                log.Error("Exception Search", ex);
+
+                return Redirect("/Home/Error");
+            }
+        }
+
         public ActionResult FaqDetail(String id)
         {
             // load FAQs

+ 8 - 3
WebPortal/WebPortal/Controllers/HomeController.cs

@@ -57,9 +57,7 @@ namespace WebPortal.Controllers
                 log.Info("Current theme: " + wsResponse.@return.listTheme[0].themeName);
                 HttpContext.Session.SetComplexData("currentTheme", wsResponse.@return.listTheme[0]);
             }
-        }
-
-        
+        }        
 
         private void LoadBanner(String type)
         {
@@ -518,6 +516,13 @@ namespace WebPortal.Controllers
 
 
 
+        public IActionResult Recharge()
+        {
+            LoadBanner("HOME");
+            ViewBag.productType = ProductType.RECHARGE;
+            return View();
+        }
+
 
         [HttpPost]
         [ValidateAntiForgeryToken]

+ 61 - 2
WebPortal/WebPortal/Controllers/SubscriberController.cs

@@ -377,7 +377,7 @@ namespace WebPortal.Controllers
         }
 
         public IActionResult Pulsa()
-        { 
+        {
             return View();
         }
 
@@ -781,6 +781,65 @@ namespace WebPortal.Controllers
                         content = "Timeout"
                     });
                 }
+                if (portrait != null)
+                {
+                    if (!portrait.FileName.EndsWith(".jpg") && !portrait.FileName.EndsWith(".jpeg") && !portrait.FileName.EndsWith(".png"))
+                    {
+                        return Json(new
+                        {
+                            error = "-1",
+                            content = "Invalid portrait"
+                        });
+                    }
+
+                    if (portrait.Length / 1024 > 1024)
+                    {
+                        return Json(new
+                        {
+                            error = "-1",
+                            content = Lang.PortraitTooBig
+                        });
+                    }
+                }
+                if (frontId != null)
+                {
+                    if (!frontId.FileName.EndsWith(".jpg") && !frontId.FileName.EndsWith(".jpeg") && !frontId.FileName.EndsWith(".png"))
+                    {
+                        return Json(new
+                        {
+                            error = "-1",
+                            content = "Invalid fontId"
+                        });
+                    }
+                    if (frontId.Length / 1024 > 1024)
+                    {
+                        return Json(new
+                        {
+                            error = "-1",
+                            content = Lang.FrontIdTooBig
+                        });
+                    }
+                }
+                if (behindId != null)
+                {
+                    if (!behindId.FileName.EndsWith(".jpg") && !behindId.FileName.EndsWith(".jpeg") && !behindId.FileName.EndsWith(".png"))
+                    {
+                        return Json(new
+                        {
+                            error = "-1",
+                            content = "Invalid behindId"
+                        });
+                    }
+
+                    if (frontId.Length / 1024 > 1024)
+                    {
+                        return Json(new
+                        {
+                            error = "-1",
+                            content = Lang.BehindIdTooBig
+                        });
+                    }
+                }
 
                 updateReq.isdn = msisdn.Substring(CountryCode.Length);
                 updateReq.portrait_image = ImageToBase64(portrait);
@@ -852,7 +911,7 @@ namespace WebPortal.Controllers
             }
             catch (Exception ex)
             {
-                log.Error("Exception UpdateSubInfoAction", ex);
+                log.Error("Exception RechargeScratch", ex);
                 return Json(new
                 {
                     error = "-1",

+ 8 - 0
WebPortal/WebPortal/Extensions/CommonUtils.cs

@@ -26,15 +26,23 @@ namespace WebPortal.Extensions
 
     public class ProductType
     {
+        public static String ROOT = "ROOT";
         public static String BROADBAND = "BROADBAND";
         public static String MOBILE = "MOBILE";
         public static String DEVICE = "DEVICE";
         public static String VAS = "VAS";
         public static String ICT = "ICT";
+        public static String RECHARGE = "RECHARGE";
         public static String MOSAN = "MOSAN";
         public static String NEWS = "NEWS";
         public static String CAREER = "CAREER";
         public static String CUSTOMER_FAQ = "CUSTOMER_FAQ";
+
+        // Mobile detail
+        public static String MB_MOBILE = "MB_MOBILE";
+        public static String MB_CALLSMS = "MB_CALLSMS";
+        public static String MB_SIM = "MB_SIM";
+
         // About
         public static String ABOUT_PROFILE = "ABOUT_PROFILE";
         public static String ABOUT_SOCIAL = "ABOUT_SOCIAL";

+ 82 - 1
WebPortal/WebPortal/Texts/Lang.Designer.cs

@@ -212,6 +212,15 @@ namespace WebPortal.Texts {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Behind Id image must be &lt; 1MB.
+        /// </summary>
+        public static string BehindIdTooBig {
+            get {
+                return ResourceManager.GetString("BehindIdTooBig", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to Broadband.
         /// </summary>
@@ -919,6 +928,15 @@ namespace WebPortal.Texts {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Front Id image must be &lt; 1MB.
+        /// </summary>
+        public static string FrontIdTooBig {
+            get {
+                return ResourceManager.GetString("FrontIdTooBig", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to General Line.
         /// </summary>
@@ -1099,6 +1117,15 @@ namespace WebPortal.Texts {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Keyword to search must has at least 2 characters.
+        /// </summary>
+        public static string KeyWordLengthMin {
+            get {
+                return ResourceManager.GetString("KeyWordLengthMin", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to Language.
         /// </summary>
@@ -1469,7 +1496,7 @@ namespace WebPortal.Texts {
         }
         
         /// <summary>
-        ///   Looks up a localized string similar to Package.
+        ///   Looks up a localized string similar to All Packages.
         /// </summary>
         public static string Package {
             get {
@@ -1630,6 +1657,15 @@ namespace WebPortal.Texts {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Portrait image must be &lt; 1MB.
+        /// </summary>
+        public static string PortraitTooBig {
+            get {
+                return ResourceManager.GetString("PortraitTooBig", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to Previous.
         /// </summary>
@@ -1747,6 +1783,24 @@ namespace WebPortal.Texts {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to RECHARGE ON KAKOAK.
+        /// </summary>
+        public static string RechargeKakoak {
+            get {
+                return ResourceManager.GetString("RechargeKakoak", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to RECHARGE ON MOSAN.
+        /// </summary>
+        public static string RechargeMosan {
+            get {
+                return ResourceManager.GetString("RechargeMosan", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to Recharge Now.
         /// </summary>
@@ -1756,6 +1810,24 @@ namespace WebPortal.Texts {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to RECHARGE BY SCRATCH CARD.
+        /// </summary>
+        public static string RechargeScratch {
+            get {
+                return ResourceManager.GetString("RechargeScratch", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Recharge By Ussd.
+        /// </summary>
+        public static string RechargeUssd {
+            get {
+                return ResourceManager.GetString("RechargeUssd", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to Register.
         /// </summary>
@@ -1891,6 +1963,15 @@ namespace WebPortal.Texts {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Scratch Code Invalid.
+        /// </summary>
+        public static string ScratchCodeInvalid {
+            get {
+                return ResourceManager.GetString("ScratchCodeInvalid", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to Scratch code required.
         /// </summary>

+ 28 - 1
WebPortal/WebPortal/Texts/Lang.fr.resx

@@ -172,6 +172,9 @@
   <data name="Back" xml:space="preserve">
     <value>Fila</value>
   </data>
+  <data name="BehindIdTooBig" xml:space="preserve">
+    <value>Imajen Kotuk Identifikasaun iha kotuk tenki &lt; 1MB</value>
+  </data>
   <data name="Broadband" xml:space="preserve">
     <value>Broadband</value>
   </data>
@@ -410,6 +413,9 @@ Periodu uzu: 30 loron hafoin troka.</value>
 Minimu troka: 100 pontu.
 Periodu uzu: 30 loron hafoin troka.</value>
   </data>
+  <data name="FrontIdTooBig" xml:space="preserve">
+    <value>Imajen Frente Identifikasaun tenki &lt; 1MB</value>
+  </data>
   <data name="GeneralLine" xml:space="preserve">
     <value>Liña Jerál</value>
   </data>
@@ -470,6 +476,9 @@ Periodu uzu: 30 loron hafoin troka.</value>
   <data name="Internet" xml:space="preserve">
     <value>Internet</value>
   </data>
+  <data name="KeyWordLengthMin" xml:space="preserve">
+    <value>Fatin buka tenki iha mínimu 2 karakter.</value>
+  </data>
   <data name="Language" xml:space="preserve">
     <value>Lingua</value>
   </data>
@@ -594,7 +603,7 @@ Periodu uzu: 30 loron hafoin troka.</value>
     <value>Ita-boot uza ona kapasidade dadus iha pakote nee, favór ida, top-up atu kontinua uza servisu nee.</value>
   </data>
   <data name="Package" xml:space="preserve">
-    <value>Pakote</value>
+    <value>Hotu pakote</value>
   </data>
   <data name="PassportVisa" xml:space="preserve">
     <value>Pasaporte / Visa</value>
@@ -647,6 +656,9 @@ Periodu uzu: 30 loron hafoin troka.</value>
   <data name="points" xml:space="preserve">
     <value>Pontu sira</value>
   </data>
+  <data name="PortraitTooBig" xml:space="preserve">
+    <value>Imajen Portrait tenki &lt; 1MB</value>
+  </data>
   <data name="Previous" xml:space="preserve">
     <value>Anteriór</value>
   </data>
@@ -686,9 +698,21 @@ Periodu uzu: 30 loron hafoin troka.</value>
   <data name="Recharge" xml:space="preserve">
     <value>Karega</value>
   </data>
+  <data name="RechargeKakoak" xml:space="preserve">
+    <value>Karega Iha Kakoak</value>
+  </data>
+  <data name="RechargeMosan" xml:space="preserve">
+    <value>Karega Iha Mosan</value>
+  </data>
   <data name="RechargeNow" xml:space="preserve">
     <value>Rekarrega Blokeiu Ona</value>
   </data>
+  <data name="RechargeScratch" xml:space="preserve">
+    <value>Karega Ho Kartão Sikat</value>
+  </data>
+  <data name="RechargeUssd" xml:space="preserve">
+    <value>Karega Ho USSD</value>
+  </data>
   <data name="Register" xml:space="preserve">
     <value>Rejistu</value>
   </data>
@@ -734,6 +758,9 @@ Periodu uzu: 30 loron hafoin troka.</value>
   <data name="Rules" xml:space="preserve">
     <value>Regra</value>
   </data>
+  <data name="ScratchCodeInvalid" xml:space="preserve">
+    <value>Kódigu Sikat La Válidu</value>
+  </data>
   <data name="ScratchCodeRequired" xml:space="preserve">
     <value>Kódigu raskadu rekesitu</value>
   </data>

+ 28 - 1
WebPortal/WebPortal/Texts/Lang.resx

@@ -173,6 +173,9 @@ For IT and Developer: Add 1 button, when click to open Message fake MO with cont
   <data name="Back" xml:space="preserve">
     <value>Back</value>
   </data>
+  <data name="BehindIdTooBig" xml:space="preserve">
+    <value>Behind Id image must be &lt; 1MB</value>
+  </data>
   <data name="Broadband" xml:space="preserve">
     <value>Broadband</value>
   </data>
@@ -418,6 +421,9 @@ Minimum redemption: 100 points.
 
 Usage period: 30 days after exchange.</value>
   </data>
+  <data name="FrontIdTooBig" xml:space="preserve">
+    <value>Front Id image must be &lt; 1MB</value>
+  </data>
   <data name="GeneralLine" xml:space="preserve">
     <value>General Line</value>
   </data>
@@ -478,6 +484,9 @@ Usage period: 30 days after exchange.</value>
   <data name="Internet" xml:space="preserve">
     <value>Internet</value>
   </data>
+  <data name="KeyWordLengthMin" xml:space="preserve">
+    <value>Keyword to search must has at least 2 characters</value>
+  </data>
   <data name="Language" xml:space="preserve">
     <value>Language</value>
   </data>
@@ -602,7 +611,7 @@ Usage period: 30 days after exchange.</value>
     <value>You have used up the data capacity of the package, please topup to continue using the service.</value>
   </data>
   <data name="Package" xml:space="preserve">
-    <value>Package</value>
+    <value>All Packages</value>
   </data>
   <data name="PassportVisa" xml:space="preserve">
     <value>Passport / Visa</value>
@@ -655,6 +664,9 @@ Usage period: 30 days after exchange.</value>
   <data name="points" xml:space="preserve">
     <value>points</value>
   </data>
+  <data name="PortraitTooBig" xml:space="preserve">
+    <value>Portrait image must be &lt; 1MB</value>
+  </data>
   <data name="Previous" xml:space="preserve">
     <value>Previous</value>
   </data>
@@ -694,9 +706,21 @@ Usage period: 30 days after exchange.</value>
   <data name="Recharge" xml:space="preserve">
     <value>Recharge</value>
   </data>
+  <data name="RechargeKakoak" xml:space="preserve">
+    <value>RECHARGE ON KAKOAK</value>
+  </data>
+  <data name="RechargeMosan" xml:space="preserve">
+    <value>RECHARGE ON MOSAN</value>
+  </data>
   <data name="RechargeNow" xml:space="preserve">
     <value>Recharge Now</value>
   </data>
+  <data name="RechargeScratch" xml:space="preserve">
+    <value>RECHARGE BY SCRATCH CARD</value>
+  </data>
+  <data name="RechargeUssd" xml:space="preserve">
+    <value>Recharge By Ussd</value>
+  </data>
   <data name="Register" xml:space="preserve">
     <value>Register</value>
   </data>
@@ -742,6 +766,9 @@ Usage period: 30 days after exchange.</value>
   <data name="Rules" xml:space="preserve">
     <value>Rules</value>
   </data>
+  <data name="ScratchCodeInvalid" xml:space="preserve">
+    <value>Scratch Code Invalid</value>
+  </data>
   <data name="ScratchCodeRequired" xml:space="preserve">
     <value>Scratch code required</value>
   </data>

+ 358 - 0
WebPortal/WebPortal/Views/CustomerCare/Search.cshtml

@@ -0,0 +1,358 @@
+@{
+    ViewData["Title"] = "Customer Care";
+
+    ViewBag.description = "Access customer care services at Telemor for support and assistance with all your needs.";
+}
+
+@using WebPortal.Texts;
+@using WebService;
+
+@model List<ProductModel>
+
+@{
+    var keywords = ViewBag.keywords;
+}
+@Html.Partial("../Partial/_Ask")
+
+<div class="pathway pt-5">
+    <div class="container">
+        <ul class="breadcrumb">
+            <li class="breadcrumb-item"><a href="/Home">@Lang.Home</a></li>
+            <li class="breadcrumb-item active">@Lang.CustomerCare</li>
+        </ul>
+    </div>
+</div>
+
+<div class="tele-product  mt-0">
+    <div class="container aos-init" data-aos="fade-up">
+        <div id="list-products">
+            @if (Model != null)
+            {
+                foreach (ProductModel group in Model)
+                {
+                    <div class="item-product item-cate-filter" cate="@group.content.nodeCode">
+                        <div class="title mb-4">
+                            <span>@group.content.nodeName</span>
+                            @*@if (group.listContent.Length > 6)
+                            {
+                                <a href="/CustomerCare/Search?parentCode=@group.content.nodeCode&keyword=@keywords" class="viewmore">
+                                    @Lang.ViewAll <img src="~/image/dot4.svg" class="ml-2" alt="more">
+                                </a>
+                            }*@
+                        </div>
+                        @if (group.content.nodeCode == ProductType.MB_SIM || group.content.nodeCode == ProductType.MB_MOBILE || group.content.nodeCode == ProductType.MB_CALLSMS)
+                        {
+                            <div class="row  ">
+                                @foreach (var product in group.listContent)
+                                {
+                                    if (product != null)
+                                    {
+                                        <div class="col-md-4 col-sm-6 features item-product-filter">
+                                            <div class="items ">
+                                                <div class="img">
+                                                    <a href="/Home/ProductDetail?productType=@group.content.nodeCode&productId=@product.id">
+                                                        <img src="@product.imgBanner" alt="banner">
+                                                    </a>
+                                                </div>
+                                                <div class="box">
+                                                    <div class="title">
+                                                        <h3><b>@product.nodeName</b></h3>
+                                                    </div>
+                                                    <p>
+                                                        @(product.description != null && product.description.Length > 77 ?
+                    product.description.Substring(0, 74) + "..." :
+                    product.description) <a href="/Home/ProductDetail?productType=@group.content.nodeCode&productId=@product.id" class="viewmore">
+                                                            @Lang.ViewAll <img src="~/image/dot4.svg" class="ml-2" alt="more">
+                                                        </a>
+                                                    </p>
+                                                    <p class="mb-0">
+                                                        <a class="btn-blue btn-regis register-service"
+                                                           href="/Home/ProductDetail?productType=@group.content.nodeCode&productId=@product.id">@Lang.LearnMore</a>
+                                                    </p>
+                                                </div>
+                                            </div>
+                                        </div>
+                                    }
+                                }
+                            </div>
+                        }
+                        else if (group.content.nodeCode == ProductType.NEWS)
+                        {
+                            <div class="row  ">
+                                @Html.Partial("../Home/_News", group)
+                            </div>
+                        }
+                        else if (group.content.nodeCode == ProductType.BROADBAND)
+                        {
+                            <div class="item-product">
+                                <div class="row card-deck mb-5" id="broadbands">
+
+                                    @for (int i = 0; i < group.listContent.Length; i++)
+                                    {
+                                        var news = group.listContent[i];
+                                        if (news != null)
+                                        {
+                                            <div class="card">
+                                                <div class="items feature-items">
+                                                    <h4>@news.nodeName</h4>
+                                                    <div class="boxcoint">
+                                                        @*<p>
+                                                                @Lang.Speed
+                                                                <b>@news.speed</b>
+                                                            </p>*@
+                                                        <ul class="m-0">
+                                                            @foreach (var text in news.description.Split("\n"))
+                                                            {
+                                                                <li>@text</li>
+                                                            }
+                                                        </ul>
+                                                    </div>
+
+                                                </div>
+                                                <div class="bottom">
+                                                    @*<span class="f14">@news.price</span>*@
+                                                    <a href="/Home/ProductDetail?productType=@ProductType.BROADBAND&productId=@news.id" class="btn-blue btn-regis">@Lang.LearnMore</a>
+                                                </div>
+                                            </div>
+                                        }
+
+                                    }
+                                </div>
+                            </div>
+
+                        }
+                        else if (group.content.nodeCode == ProductType.DEVICE)
+                        {
+                            <div class="row">
+                                @for (int i = 0; i < group.listContent.Length; i++)
+                                {
+                                    var news = group.listContent[i];
+                                    <div class="col-md-4 col-sm-6 features">
+                                        <div class="items listproduct">
+                                            <a href="/Home/DeviceDetail?id=@news.id" class="title"><img src="@news.imgAvatar" class="img" alt="avatar"></a>
+                                            <a href="/Home/DeviceDetail?id=@news.id" class="title">@news.nodeName</a>
+                                        </div>
+                                    </div>
+                                }
+                            </div>
+                        }
+                        else if (group.content.nodeCode == ProductType.VAS)
+                        {
+                            <div class="row  ">
+                                @for (int i = 0; i < group.listContent.Length; i++)
+                                {
+                                    var news = group.listContent[i];
+                                    if (news != null)
+                                    {
+                                        <div class="col-md-4 col-sm-6 features">
+                                            <div class="items item-vas">
+                                                <div class="img">
+                                                    <a href="/Home/ProductDetail?productType=@ProductType.VAS&productId=@news.id">
+                                                        <img src="@news.imgBanner" alt="banner">
+                                                    </a>
+                                                </div>
+                                                <div class="boxcont text-center">
+                                                    <h3 class="f24"><b>@(news.nodeName != null && news.nodeName.Length > 20 ? news.nodeName.Substring(0, 17) + "..." : news.nodeName)</b></h3>
+                                                    <p class="descrip">
+                                                        @(news.description != null && news.description.Length > 77 ? news.description.Substring(0, 74) + "..." : news.description)
+                                                    </p>
+                                                    @*<p class="dola mb-0"><span>$</span> <b> @news.price</b></p>
+                                                        <p class="daily">@news.period</p>*@
+                                                    <p><a href="/Home/ProductDetail?productType=@ProductType.VAS&productId=@news.id" class="btn-blue btn-regis">@Lang.LearnMore</a></p>
+                                                </div>
+                                            </div>
+                                        </div>
+                                    }
+                                }
+                            </div>
+                        }
+                        else if (group.content.nodeCode == ProductType.ICT)
+                        {
+                            for (int i = 0; i < group.listContent.Length; i++)
+                            {
+                                var product = group.listContent[i];
+
+                                if (product != null)
+                                {
+                                    if (i % 2 == 0)
+                                    {
+                                        <div class="banner-slide" style="background-image: url('@product.imgBackground');">
+                                            <div class="container aos-init" data- aos="fade-up">
+                                                <div class="row">
+                                                    <div class="col-md-7 ml-auto">
+                                                        <h3 data-aos="fade-left" data-aos-delay="200" class="mb-5">@product.nodeName</h3>
+                                                        <p data-aos="fade-right" data-aos-delay="300" class="f14 mb-5">
+                                                            @product.description
+                                                        </p>
+                                                        <p><a href="/Home/ProductDetail?productType=@group.content.nodeCode&productId=@product.id" class="btn-blue btn-regis">@Lang.LearnMore</a></p>
+                                                    </div>
+                                                </div>
+                                            </div>
+                                        </div>
+                                    }
+                                    else
+                                    {
+                                        <div class="banner-slide" style="background-image: url('@product.imgBackground');">
+                                            <div class="container aos-init" data-aos="fade-up">
+                                                <div class="row">
+                                                    <div class="col-md-7">
+                                                        <h3 data-aos="fade-left" data-aos-delay="200" class="mb-5 cl000">@product.nodeName</h3>
+                                                        <p data-aos="fade-right" data-aos-delay="300" class="f14 mb-5 cl000">
+                                                            @product.description
+                                                        </p>
+                                                        <p><a href="/Home/ProductDetail?productType=@group.content.nodeCode&productId=@product.id" class="btn-blue btn-regis">@Lang.LearnMore</a></p>
+                                                    </div>
+                                                </div>
+                                            </div>
+                                        </div>
+                                    }
+                                }
+                            }
+                        }
+                        else if (group.content.nodeCode == ProductType.CUSTOMER_FAQ)
+                        {
+                            <div class="box-customer">
+                                <div id="accordion" class="accordion">
+                                    @foreach (contentTreeObj content in group.listContent)
+                                    {
+                                        @if (keywords == null || keywords.Trim().Length == 0)
+                                        {
+                                            <div class="card" data-aos="fade-up" data-aos-delay="100">
+                                                <div class="card-header">
+                                                    <a class="card-link collapsed" data-toggle="collapse" href="@("#c" + content.id)" onclick="loadFaqs(@content.id)">
+                                                        @content.nodeName
+                                                    </a>
+                                                </div>
+                                                <div id="@("c" + content.id)" class="collapse " data-parent="#accordion">
+                                                    <div class="card-body" id="@("body-" + content.id)">
+                                                    </div>
+                                                </div>
+                                            </div>
+                                        }
+                                        else
+                                        {
+                                            <p><a href="@("/CustomerCare/FaqDetail?id=" + content.id)">@content.nodeName</a></p>
+                                        }
+                                    }
+                                </div>
+                            </div>
+                        }
+                    </div>
+                }
+            }
+            else
+            {
+                <div class="col-sm-12">
+                    <div class="boxsppage">@Lang.NoMoreData</div>
+                </div>
+            }
+        </div>
+    </div>
+</div>
+
+
+<div class="ads mb-5">
+    <div class="container">
+        <a href="/CustomerCare/Loyalty" class="d-block"><img src="~/image/banner/ads.png" alt="banner"> </a>
+    </div>
+</div>
+
+<div class="tele-utili item-product mb-5">
+    <div class="container aos-init" data-aos="fade-up">
+        <div class="title mb-4">
+            <span class="text-uppercase">@Lang.Utilities</span>
+        </div>
+        <div class="boxcont">
+            <div class="row justify-content-center">
+                <div class="col-md-4  text-center">
+                    <a href="/Home/Error" class="d-block">
+                        <div class="rounded-circle">
+                            <img src="~/image/policy.svg " alt="policy">
+                        </div>
+                        <p class="mb-0">
+                            <b class="f14">
+                                @Lang.WarrantyPolicy
+                            </b>
+                        </p>
+                    </a>
+                </div>
+                <div class="col-md-4 text-center">
+                    <a href="/CustomerCare/Showroom" class="d-block">
+                        <div class="rounded-circle">
+                            <img src="~/image/service.svg" alt="service">
+                        </div>
+                        <p class="mb-0">
+                            <b class="f14">
+                                @Lang.FindStore
+                            </b>
+                        </p>
+                    </a>
+                </div>
+                @*<div class="col-md-2 text-center">
+                        <a href="/Home/Error" class="d-block">
+                            <div class="rounded-circle">
+                                <img src="~/image/searching.svg ">
+                            </div>
+                            <p class="mb-0"><b class="f14">@Lang.Searching</b></p>
+                        </a>
+                    </div>*@
+                <div class="col-md-4 text-center">
+                    <a href="#" class="d-block">
+                        <div class="rounded-circle">
+                            <img src="~/image/vas1.svg" alt="vas">
+                        </div>
+                        <p class="mb-0"><b class="f14">@Lang.FAQs</b></p>
+                    </a>
+                </div>
+                @*<div class="col-md-2 text-center">
+                        <a href="/Home/Error" class="d-block">
+                            <div class="rounded-circle">
+                                <img src="~/image/contact.svg">
+                            </div>
+                            <p class="mb-0"><b class="f14">@Lang.Contact</b></p>
+                        </a>
+                    </div>*@
+            </div>
+
+        </div>
+    </div>
+</div>
+
+@section Scripts {
+    <script>
+        function loadFaqs(parentId) {
+            console.log("loadFaqs " + parentId);
+            var target = "body-" + parentId;
+            if ($("#c" + parentId + " .card-body").children().length == 0) {
+                console.log(target);
+                startSpinner(target);
+                $.ajax({
+                    url: "/Home/TreeLoad",
+                    data: {
+                        __RequestVerificationToken: $('input[name=__RequestVerificationToken]').val(),
+                        parentId: parentId,
+                        page: "1",
+                        size: "1000"
+                    },
+                    type: "POST",
+                    success: function (result) {
+                        console.log(result);
+                        stopSpinner(target);
+                        if (result.error == "0") {
+                            for (var i = 0; i < result.data.length; i++) {
+                                let div = '<p><a href="/CustomerCare/FaqDetail?id=' + result.data[i].id + '">' + result.data[i].nodeName + '</a></p>';
+                                //console.log(div);
+                                $("#c" + parentId + " .card-body").append(div);
+                            };
+                        }
+                    },
+                    error: function (data) {
+                        stopSpinner(target);
+                        console.log(data);
+                    }
+                });
+            }
+        };
+
+    </script>
+}

+ 0 - 48
WebPortal/WebPortal/Views/Home/Mosan-Dell-Vostro.cshtml

@@ -1,48 +0,0 @@
-@{
-    ViewData["Title"] = "Products & Services";
-}
-
-@using WebPortal.Texts
-@using WebPortal.Models
-@using WebPortal.Controllers
-@using WebPortal.Extensions
-@using WebService
-@using Microsoft.AspNetCore.Http
-
-@model ProductModel
-@{
-    //wsLoginResponse userInfo = Context.Session.GetComplexData<wsLoginResponse>("userInfo");
-    String msisdn = Context.Session.GetString("account");
-    String isdn = "";
-    if (msisdn != null && msisdn.Length > BaseController.CountryCode.Length)
-    {
-        isdn = msisdn.Substring(BaseController.CountryCode.Length);
-    }
-}
-
-
-@*@Html.Partial("_TopBanner", Model)*@
-
-
-<div class="pathway pt-5">
-    <div class="container">
-        <ul class="breadcrumb">
-            <li class="breadcrumb-item"><a href="/Home">Home</a></li>
-            <li class="breadcrumb-item active">Mosan</li>
-        </ul>
-    </div>
-</div>
-<div class="tele-showroom">
-    <div class="container aos-init" data-aos="fade-up">
-        <div class="box">
-            <h3 class="f24 mb-4"><b>Contact Nearest Showroom</b></h3>
-            <p class="mb-2">
-                <b>Location: </b>Viettel Timor Leste Unip, Lda (Telemor) CBD4, Timor Plaza, Comoro, Dili
-            </p>
-            <p class="mb-5"><b>Company:</b> Telemor</p>
-            <p class="text-center"><img src="~/image/showroom.png" alt="showroom"></p>
-        </div>
-    </div>
-</div>
-
-@Html.Partial("../Partial/_Ask")

+ 218 - 0
WebPortal/WebPortal/Views/Home/Recharge.cshtml

@@ -0,0 +1,218 @@
+@{
+    ViewData["Title"] = "Products & Services";
+}
+
+@using WebPortal.Texts
+@using WebPortal.Models
+@using WebPortal.Controllers
+@using WebPortal.Extensions
+@using WebService
+@using Microsoft.AspNetCore.Http
+
+@model ProductModel
+@{
+    //wsLoginResponse userInfo = Context.Session.GetComplexData<wsLoginResponse>("userInfo");
+    String msisdn = Context.Session.GetString("account");
+    String isdn = "";
+    if (msisdn != null && msisdn.Length > BaseController.CountryCode.Length)
+    {
+        isdn = msisdn.Substring(BaseController.CountryCode.Length);
+    }
+}
+
+
+@Html.Partial("_TopBanner", Model)
+
+
+<div class="pathway pt-5">
+    <div class="container">
+        <ul class="breadcrumb">
+            <li class="breadcrumb-item"><a href="/Home">Home</a></li>
+            <li class="breadcrumb-item active">@Lang.Recharge</li>
+        </ul>
+    </div>
+</div>
+
+<div class="recharge">
+
+    <div class="container aos-init" data-aos="fade-up">         
+
+        <div class="row">
+            <div class="col-md-5">
+                <h3 class="f20 mb-4 tab-recharge active">@Lang.RechargeScratch</h3>
+                @*<h3 class="f24 mb-4 tab-recharge">@Lang.RechargeUssd</h3>
+                <h3 class="f24 mb-4 tab-recharge">@Lang.RechargeKakoak</h3>
+                <h3 class="f24 mb-4 tab-recharge">@Lang.RechargeMosan</h3>*@
+            </div>
+            <div class="col-md-7">
+                <div class="box">
+                    <form class="formstyle">
+                        <div class="form-group">
+                            <input type="text" class="form-control" placeholder="@Lang.PhoneNumber *" id="phoneNumber2" value="@msisdn">
+                            <p class="invalid-feedback" id="recharge-phoneNumberError2"></p>
+                        </div>
+                        <div class="form-group">
+                            <input class="form-control" type="text" placeholder="@Lang.EnterScratchCode" id="scratchCode2" maxlength="13">
+                            <p class="invalid-feedback" id="recharge-scratchCodeError2"></p>
+                            @*</div>*@
+                        </div>
+                        <div class="form-group">
+                            <div class="d-flex align-items-center">
+                                <div id="captcha-topup"></div>
+                            </div>
+
+                        </div>
+                        <div class="form-group recharge-action">
+                            <a class="btn-white text-center heg42" onclick="clearData();" id="btn-clear">@Lang.Reset</a>
+                            <a class="btn-blue btn-regis text-center heg42" onclick="recharge2();" id="btn-recharge2">@Lang.Recharge</a>
+                        </div>
+                    </form>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+ 
+
+<link rel="stylesheet" type="text/css" href="~/css/recharge.css">
+
+@section Scripts{
+    <script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit"
+            async defer>
+    </script>
+
+    <script>
+        // Restricts input for the set of matched elements to the given inputFilter function.
+        (function ($) {
+            $.fn.inputFilter = function (callback, errMsg) {
+                return this.on("input keydown keyup mousedown mouseup select contextmenu drop focusout", function (e) {
+                    if (callback(this.value)) {
+                        // Accepted value
+                        if (["keydown", "mousedown", "focusout"].indexOf(e.type) >= 0) {
+                            $(this).removeClass("input-error");
+                            this.setCustomValidity("");
+                        }
+                        this.oldValue = this.value;
+                        this.oldSelectionStart = this.selectionStart;
+                        this.oldSelectionEnd = this.selectionEnd;
+                    } else if (this.hasOwnProperty("oldValue")) {
+                        // Rejected value - restore the previous one
+                        $(this).addClass("input-error");
+                        this.setCustomValidity(errMsg);
+                        this.reportValidity();
+                        this.value = this.oldValue;
+                        this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);
+                    } else {
+                        // Rejected value - nothing to restore
+                        this.value = "";
+                    }
+                });
+            };
+        }(jQuery));
+
+        $(document).ready(function () {
+            $("#scratchCode2").inputFilter(function (value) {
+                return /^\d*$/.test(value);    // Allow digits only, using a RegExp
+            }, "Only digits allowed");
+        });
+    </script>
+
+    <script>
+
+        var widgetId1;
+        var onloadCallback = function () {
+            widgetId1 = grecaptcha.render(
+                'captcha-topup',
+                {
+                    'sitekey': '@BaseController.CaptchaSiteKey'
+                });
+            };
+
+        function clearData() {
+            $("#scratchCode2").val("");
+            grecaptcha.reset(widgetId1);
+        }
+
+        var updating2 = false;
+        function recharge2() {
+            if (updating2) {
+                return;
+            }
+            console.log("recharge2");
+            var token = $('input[name=__RequestVerificationToken]').val();
+            var msisdn = $('#phoneNumber2').val();
+            var code = $('#scratchCode2').val();
+
+            // validate
+            if (!msisdn || msisdn == "") {
+                $("#recharge-phoneNumberError2").html("@Lang.PhonenumberRequired");
+                $("#recharge-phoneNumberError2").show();
+                $('#phoneNumber2').addClass("is-invalid");
+                return;
+            }
+
+            if (!code || code == "") {
+                $("#recharge-scratchCodeError2").html("@Lang.ScratchCodeRequired");
+                $("#recharge-scratchCodeError2").show();
+                $('#scratchCode2').addClass("is-invalid");
+                return;
+            }
+
+            if (code.length != 13) {
+                $("#recharge-scratchCodeError2").html("@Lang.ScratchCodeInvalid");
+                $("#recharge-scratchCodeError2").show();
+                $('#scratchCode2').addClass("is-invalid");
+                return;
+            }
+
+            //$("#btn-recharge2").prop('disabled', true);
+            startSpinner("btn-recharge2");
+            updating2 = true;
+            var formData = new FormData();
+            formData.append('__RequestVerificationToken', token);
+            formData.append('msisdn', msisdn);
+            formData.append('code', code);
+            formData.append('captcharesponse', grecaptcha.getResponse(widgetId1));
+
+            $.ajax({
+                type: "POST",
+                url: ("/Subscriber/RechargeScratch"),
+                headers: { 'RequestVerificationToken': token },
+                data: formData,
+                contentType: false,
+                processData: false,
+                success: function (result) {
+                    updating2 = false;
+                    grecaptcha.reset(widgetId1);
+                    //$("#btn-recharge2").prop('disabled', false);
+                    stopSpinner("btn-recharge2");
+                    console.log(result);
+                    hideModal("Recharge");
+                    $("#scratchCode2").val("");
+                    if (result.error == '0') {
+                        $('#message-success').html(result.content);
+                        showModal("modalSuccess");
+                    } else {
+                        showModal("modalFail");
+                        $('#message-error').html(result.content);
+                    }
+                },
+                error: function (err) {
+                    updating2 = false;
+                    $("#scratchCode2").val("");
+                    grecaptcha.reset(widgetId1);
+                    //$("#btn-recharge2").prop('disabled', false);
+                    stopSpinner("btn-recharge2");
+                    hideModal("Recharge");
+                    showModal("modalFail");
+                    $('#message-error').html(err.statusText);
+                }
+            });
+
+        }
+
+    </script>
+
+
+
+}

+ 11 - 2
WebPortal/WebPortal/Views/Home/RegisterAccount.cshtml

@@ -51,8 +51,8 @@
                         </div>
                         <div class="form-group">
                             <span class="f14">
-                                @Lang.WouldYouLike <a class="text-primary">
-                                    <b class="login-dialog">
+                                @Lang.WouldYouLike <a class="text-primary login-dialog">
+                                    <b class="">
                                         @Lang.Login?
                                     </b>
                                 </a>
@@ -68,3 +68,12 @@
     </div>
 </div>
 
+
+@section Scripts {
+    <script>
+        $(".login-dialog").click(function () {
+            $("#modalLogin").modal({ backdrop: 'static', keyboard: false });
+        });
+    </script>
+
+}

+ 6 - 0
WebPortal/WebPortal/Views/Home/_TopBanner.cshtml

@@ -218,6 +218,12 @@ else
                                 <span>@Lang.Mosan</span>
                             </a>
                         </li>
+                        <li>
+                            <a href="/Home/Recharge" class="@(productType.Contains(ProductType.RECHARGE) ? "active":"")">
+                                <img src="~/image/recharge.png " alt="recharge">
+                                <span>@Lang.Recharge</span>
+                            </a>
+                        </li>
                     </ul>
                 </div>
             }

+ 1 - 1
WebPortal/WebPortal/Views/Subscriber/TrialService.cshtml

@@ -97,7 +97,7 @@
                             <img src="/image/Register1.png" alt="Register1">
                             <span class="title">@Lang.Recharge</span>
                         </a>*@
-                        <a href="/Subscriber/MyAccount">
+                        <a href="/Home/Recharge">
                             <img src="/image/Register1.png" alt="Register1">
                             <span class="title">@Lang.Recharge</span>
                         </a>

+ 3 - 3
WebPortal/WebPortal/Views/Subscriber/UpdateSubInfo.cshtml

@@ -128,7 +128,7 @@
                         <div class="d-flex">
                             <input class="form-control" type="text" placeholder="" readonly>
                             <label class="btn btn-select ml-4" for="file_portrait">@Lang.Select</label>
-                            <input type="file" style="display:none" id="file_portrait" />
+                            <input type="file" style="display:none" id="file_portrait" accept="image/png, image/jpeg, image/jpg"/>
                         </div>
 
                     </div>
@@ -139,7 +139,7 @@
                         <div class="d-flex">
                             <input class="form-control" type="text" placeholder="" readonly>
                             <label class="btn btn-select ml-4" for="file_front_card">@Lang.Select</label>
-                            <input type="file" style="display:none" id="file_front_card" />
+                            <input type="file" style="display:none" id="file_front_card" accept="image/png, image/jpeg, image/jpg"/>
                         </div>
                     </div>
                 </div>
@@ -149,7 +149,7 @@
                         <div class="d-flex">
                             <input class="form-control" type="text" placeholder="" readonly>
                             <label class="btn btn-select ml-4" for="file_behind_card">@Lang.Select</label>
-                            <input type="file" style="display:none" id="file_behind_card" />
+                            <input type="file" style="display:none" id="file_behind_card" accept="image/png, image/jpeg, image/jpg"/>
                         </div>
                     </div>
                 </div>

+ 8 - 1
WebPortal/WebPortal/Views/_ViewStart.cshtml

@@ -709,7 +709,14 @@
         $(".btn-success").click(function (e) {
             e.preventDefault();
             var key = $(this).prev().val();
-            window.location.href = "/CustomerCare/Index?keywords=" + key;
+            // check keyword length
+            if (key.length < 2) {
+                showModal("modalFail");
+                $('#message-error').html('@Lang.KeyWordLengthMin');
+                return;
+            } else {
+                window.location.href = "/CustomerCare/Search?keywords=" + key;
+            }
         });
     });
 

+ 2 - 2
WebPortal/WebPortal/appsettings.json

@@ -8,9 +8,9 @@
   "channel": "WEB",
   "numWs": "1",
   "reloadPeriod": "10",
-  "wsUrl1": "http://10.226.234.24:8088/WsWebPortal?wsdl",
+  //"wsUrl1": "http://10.226.234.24:8088/WsWebPortal?wsdl",
   //"wsUrl2": "http://10.226.234.24:8088/WsWebPortal?wsdl",
-  //"wsUrl1": "http://127.0.0.1:8088/WsWebPortal?wsdl",
+  "wsUrl1": "http://10.226.234.25:8488/WsWebPortal?wsdl",
   //"wsUrl2": "http://127.0.0.1:8088/WsWebPortal?wsdl",
   "wsLoginFail1": "http://10.226.234.24:8087/WsLoginFail?wsdl",
 

+ 41 - 0
WebPortal/WebPortal/wwwroot/css/recharge.css

@@ -0,0 +1,41 @@
+
+
+.tab-recharge {
+    padding: 10px;
+    border-radius: 30px;
+    width: 100%;
+    max-width: 480px;
+    font-family: Magistral-Medium !important;
+    text-align: center;
+    background-color: #fff;
+    color: #0072BC;
+    text-transform: uppercase;
+}
+
+    .tab-recharge.active {
+        background-color: #0072BC;
+        color: #fff;
+    }
+
+.recharge-action {
+    display: flex;
+    justify-content: end;
+    gap: 20px;
+}
+
+    .recharge-action a {
+        flex-grow: 1;
+    }
+
+.recharge {
+    background-color: #F9F7F7;
+    padding: 30px 0;
+}
+
+    .recharge .box {
+        box-shadow: 0 4px 40px rgb(0 0 0 / 15%);
+        border-radius: 33px;
+        padding: 40px 40px 24px 40px;
+        /*margin-bottom: 30px;*/
+        background-color: #fff;
+    }

+ 31 - 26
WebPortal/WebPortal/wwwroot/css/style.css

@@ -475,6 +475,7 @@ a {
     .mega-menu ul.list {
         display: flex;
         align-items: center;
+        justify-content: center;
     }
 
         .mega-menu ul.list li {
@@ -2502,41 +2503,46 @@ ul.listsite {
     font-size: 14px !important;
 }
 
-.modal .modal-dialog {
-    max-width: 360px;
+.modal {
+    padding-right: 0px !important;
 }
 
-.modal .modal-header {
-    border: none;
-    text-align: center;
-    align-items: center;
-    position: relative;
-}
+    .modal .modal-dialog {
+        max-width: 360px;
+    }
 
-.modal .modal-title {
-    text-align: center;
-    display: block;
-    margin: 0 auto;
-}
+    .modal .modal-header {
+        border: none;
+        text-align: center;
+        align-items: center;
+        position: relative;
+    }
 
-.modal .modal-header button {
-    border: none;
-    background: none;
-    margin: 0;
-    position: absolute;
-    right: 3px;
-    top: 5px;
-    opacity: 1;
-}
+    .modal .modal-title {
+        text-align: center;
+        display: block;
+        margin: 0 auto;
+    }
 
-.modal .form-group {
-    margin-bottom: 20px;
-}
+    .modal .modal-header button {
+        border: none;
+        background: none;
+        margin: 0;
+        position: absolute;
+        right: 3px;
+        top: 5px;
+        opacity: 1;
+    }
+
+    .modal .form-group {
+        margin-bottom: 20px;
+    }
 
 .modal-content {
     font-family: Helvetica;
 }
 
+
 /* timeline */
 .tele-ourcompany .boxcoint {
     display: flex;
@@ -4942,7 +4948,6 @@ ul.listsite {
     .pulsa-content .box {
         margin-bottom: 10%;
     }
-
 }
 
 @media only screen and (max-width:480px) {

二进制
WebPortal/WebPortal/wwwroot/image/recharge.png


+ 28 - 14
WebPortalWs/Timor_WebPortalWs/src/com/vas/wsfw/database/WsProcessUtils.java

@@ -1394,20 +1394,34 @@ public class WsProcessUtils extends DbProcessorAbstract {
 
             while (rs.next()) {
                 ContentTreeObj obj = new ContentTreeObj();
-                obj.setId(rs.getLong(ProductObj.ID));
-                obj.setNodeCode(rs.getString(ContentTreeObj.NODE_CODE));
-                if (Common.Language.Lang1.equals(lang)) {
-                    obj.setNodeName(rs.getString(ContentTreeObj.NODE_NAME_1));
-                } else if (Common.Language.Lang2.equals(lang)) {
-                    obj.setNodeName(rs.getString(ContentTreeObj.NODE_NAME_2));
-                } else if (Common.Language.LangAll.equals(lang)) {
-                    obj.setNodeName(rs.getString(ContentTreeObj.NODE_NAME));
-                    obj.setNodeName1(rs.getString(ContentTreeObj.NODE_NAME_1));
-                    obj.setNodeName2(rs.getString(ContentTreeObj.NODE_NAME_2));
-                } else {
-                    obj.setNodeName(rs.getString(ContentTreeObj.NODE_NAME));
-                }
-                result.add(obj);
+//                obj.setId(rs.getLong(ProductObj.ID));
+//                obj.setNodeCode(rs.getString(ContentTreeObj.NODE_CODE));
+//                // node name
+//                if (Common.Language.Lang1.equals(lang)) {
+//                    obj.setNodeName(rs.getString(ContentTreeObj.NODE_NAME_1));
+//                } else if (Common.Language.Lang2.equals(lang)) {
+//                    obj.setNodeName(rs.getString(ContentTreeObj.NODE_NAME_2));
+//                } else if (Common.Language.LangAll.equals(lang)) {
+//                    obj.setNodeName(rs.getString(ContentTreeObj.NODE_NAME));
+//                    obj.setNodeName1(rs.getString(ContentTreeObj.NODE_NAME_1));
+//                    obj.setNodeName2(rs.getString(ContentTreeObj.NODE_NAME_2));
+//                } else {
+//                    obj.setNodeName(rs.getString(ContentTreeObj.NODE_NAME));
+//                }
+//                // description
+//                if (Common.Language.Lang1.equals(lang)) {
+//                    obj.setDescription(rs.getString(ContentTreeObj.DESCRIPTION_1));
+//                } else if (Common.Language.Lang2.equals(lang)) {
+//                    obj.setDescription(rs.getString(ContentTreeObj.DESCRIPTION_2));
+//                } else if (Common.Language.LangAll.equals(lang)) {
+//                    obj.setDescription(rs.getString(ContentTreeObj.DESCRIPTION));
+//                    obj.setDescription1(rs.getString(ContentTreeObj.DESCRIPTION_1));
+//                    obj.setDescription2(rs.getString(ContentTreeObj.DESCRIPTION_2));
+//                } else {
+//                    obj.setDescription(rs.getString(ContentTreeObj.DESCRIPTION));
+//                }
+
+                result.add(parseTree(rs, obj, lang, false));
             }
 
         } catch (SQLException ex) {

+ 0 - 29
WebPortalWs/Timor_WebPortalWs/src/com/vas/wsfw/main/Dog.java

@@ -1,29 +0,0 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-package com.vas.wsfw.main;
-
-/**
- *
- * @author nvta8hp0
- */
-public class Dog {
-
-    public Dog() {
-    }
-
-    public Dog(String name) {
-        this.name = name;
-    }
-    private String name;
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-}

+ 0 - 30
WebPortalWs/Timor_WebPortalWs/src/com/vas/wsfw/main/test.java

@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2010 Viettel Telecom. All rights reserved.
- * VIETTEL PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- */
-package com.vas.wsfw.main;
-
-import com.sun.org.apache.xerces.internal.impl.xpath.regex.RegularExpression;
-
-/**
- *
- * @author minhnh@viettel.com.vn
- * @since Jun 3, 2013
- * @version 1.0
- */
-public class test {
-
-    public static void main(String[] args) {
-        Dog aDog = new Dog("Max");
-
-        foo(aDog);
-        // when foo(...) returns, the name of the dog has been changed to "Fifi"
-        System.out.println(aDog.getName()); // true 
-    }
-
-    public static void foo(Dog d) {
-        System.out.println(d.getName()); // true
-        // this changes the name of d to be "Fifi"
-        d.setName("Fifi");
-    }
-}

+ 9 - 7
WebPortalWs/etc/database.xml

@@ -9,13 +9,15 @@
   </timeout-config>
   <named-config name="dbProcess">
 	<property name="driver">oracle.jdbc.driver.OracleDriver</property>
-	<!-- <property name="connection">jdbc:oracle:thin:@(DESCRIPTION =(ADDRESS = (PROTOCOL = TCP)(HOST = 10.226.45.61)(PORT = 1521)) -->
-	<!-- (ADDRESS = (PROTOCOL = TCP)(HOST = 10.226.45.71)(PORT = 1521))(LOAD_BALANCE = yes)(CONNECT_DATA =(SERVER = SHARED)(SERVICE_NAME=vas)))</property> -->
-	<!-- <property name="username">Webportal</property> -->
-	<!-- <property name="password">W313Por7@l</property> -->
-	<property name="connection">jdbc:oracle:thin:@(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1539))(CONNECT_DATA =(SERVER = DEDICATED)(SERVICE_NAME=ORA12C)))</property>
-	<property name="username">timor_landingpage</property>
-	<property name="password">timor_landingpage</property>
+	<property name="connection">jdbc:oracle:thin:@(DESCRIPTION= 
+          (ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1541))
+        (CONNECT_DATA=(FAILOVER_MODE=(TYPE=select)(METHOD=basic)(RETRIES=180)(DELAY=5))(SERVICE_NAME=bss)))
+	</property>
+	<property name="username">Webportal</property>
+	<property name="password">W313Por7@l</property>
+	<!-- <property name="connection">jdbc:oracle:thin:@(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1539))(CONNECT_DATA =(SERVER = DEDICATED)(SERVICE_NAME=ORA12C)))</property> -->
+	<!-- <property name="username">timor_landingpage</property> -->
+	<!-- <property name="password">timor_landingpage</property> -->
     <property name="initialPoolSize">5</property>
 	<property name="maxPoolSize">30</property>
 	<property name="minPoolSize">10</property>

+ 57 - 0
WebPortalWs/log/error/error.log.2024-07-24

@@ -0,0 +1,57 @@
+24/07/2024 11:32:35 ERROR [main] Tools:mmserver: 
+24/07/2024 11:32:35 ERROR [main] Tools:mmserver: java.lang.NullPointerException
+24/07/2024 11:32:35 ERROR [main] actionlog: Error in start ActionLogDbUtils
+24/07/2024 11:32:35 ERROR [main] actionlog: java.lang.NullPointerException
+24/07/2024 11:33:37 ERROR [main] ConnectionPoolManager: Can't connect DB, with ID: dbProcess
+java.sql.SQLException: An attempt by a client to checkout a Connection has timed out.
+	at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:118)
+	at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:77)
+	at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:687)
+	at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:140)
+	at com.viettel.ussdfw.database.ConnectionPoolManager.getConnection(ConnectionPoolManager.java:169)
+	at com.viettel.ussdfw.database.DbProcessorFW.getWebservice(DbProcessorFW.java:473)
+	at com.viettel.ussdfw.database.DbProcessorFW.iGetWebservice(DbProcessorFW.java:440)
+	at com.viettel.ussdfw.webservice.WebserviceFW.loadConfigDb(WebserviceFW.java:132)
+	at com.viettel.ussdfw.webservice.WebserviceFW.<init>(WebserviceFW.java:78)
+	at com.vas.wsfw.services.WSProcessor.<init>(WSProcessor.java:83)
+	at com.vas.wsfw.services.ProcessReload.<init>(ProcessReload.java:30)
+	at com.vas.wsfw.common.WebserviceManager.<init>(WebserviceManager.java:380)
+	at com.vas.wsfw.common.WebserviceManager.getInstance(WebserviceManager.java:92)
+	at com.vas.wsfw.main.ScanProcessManager.start(ScanProcessManager.java:36)
+	at com.vas.wsfw.main.Start.main(Start.java:18)
+Caused by: com.mchange.v2.resourcepool.TimeoutException: A client timed out while waiting to acquire a resource from com.mchange.v2.resourcepool.BasicResourcePool@3ffc5af1 -- timeout at awaitAvailable()
+	at com.mchange.v2.resourcepool.BasicResourcePool.awaitAvailable(BasicResourcePool.java:1416)
+	at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:606)
+	at com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource(BasicResourcePool.java:526)
+	at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutAndMarkConnectionInUse(C3P0PooledConnectionPool.java:755)
+	at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:682)
+	... 12 more
+24/07/2024 11:33:37 ERROR [main] ProcessReload: DbProcessor-FW: Wed Jul 24 11:33:37 ICT 2024
+ERROR select WEBSERVICE
+java.lang.NullPointerException
+	at com.viettel.ussdfw.database.DbProcessorFW.getWebservice(DbProcessorFW.java:475)
+	at com.viettel.ussdfw.database.DbProcessorFW.iGetWebservice(DbProcessorFW.java:440)
+	at com.viettel.ussdfw.webservice.WebserviceFW.loadConfigDb(WebserviceFW.java:132)
+	at com.viettel.ussdfw.webservice.WebserviceFW.<init>(WebserviceFW.java:78)
+	at com.vas.wsfw.services.WSProcessor.<init>(WSProcessor.java:83)
+	at com.vas.wsfw.services.ProcessReload.<init>(ProcessReload.java:30)
+	at com.vas.wsfw.common.WebserviceManager.<init>(WebserviceManager.java:380)
+	at com.vas.wsfw.common.WebserviceManager.getInstance(WebserviceManager.java:92)
+	at com.vas.wsfw.main.ScanProcessManager.start(ScanProcessManager.java:36)
+	at com.vas.wsfw.main.Start.main(Start.java:18)
+24/07/2024 11:33:37 ERROR [main] ProcessReload: ERROR when init ProcessReload
+java.lang.NullPointerException
+	at com.viettel.ussdfw.database.DbProcessorFW.getWebservice(DbProcessorFW.java:475)
+	at com.viettel.ussdfw.database.DbProcessorFW.iGetWebservice(DbProcessorFW.java:440)
+	at com.viettel.ussdfw.webservice.WebserviceFW.loadConfigDb(WebserviceFW.java:132)
+	at com.viettel.ussdfw.webservice.WebserviceFW.<init>(WebserviceFW.java:78)
+	at com.vas.wsfw.services.WSProcessor.<init>(WSProcessor.java:83)
+	at com.vas.wsfw.services.ProcessReload.<init>(ProcessReload.java:30)
+	at com.vas.wsfw.common.WebserviceManager.<init>(WebserviceManager.java:380)
+	at com.vas.wsfw.common.WebserviceManager.getInstance(WebserviceManager.java:92)
+	at com.vas.wsfw.main.ScanProcessManager.start(ScanProcessManager.java:36)
+	at com.vas.wsfw.main.Start.main(Start.java:18)
+24/07/2024 13:43:16 ERROR [main] Tools:mmserver: 
+24/07/2024 13:43:16 ERROR [main] Tools:mmserver: java.lang.NullPointerException
+24/07/2024 13:43:16 ERROR [main] actionlog: Error in start ActionLogDbUtils
+24/07/2024 13:43:16 ERROR [main] actionlog: java.lang.NullPointerException

文件差异内容过多而无法显示
+ 395 - 0
WebPortalWs/log/full/full.log.2024-07-24


部分文件因为文件数量过多而无法显示