diff --git a/accounts/.pylintrc b/accounts/.pylintrc new file mode 100644 index 0000000..3cb87fe --- /dev/null +++ b/accounts/.pylintrc @@ -0,0 +1,638 @@ +[MAIN] + +# Analyse import fallback blocks. This can be used to support both Python 2 and +# 3 compatible code, which means that the block might have code that exists +# only in one or another interpreter, leading to false positives when analysed. +analyse-fallback-blocks=no + +# Clear in-memory caches upon conclusion of linting. Useful if running pylint +# in a server-like mode. +clear-cache-post-run=no + +# Load and enable all available extensions. Use --list-extensions to see a list +# all available extensions. +#enable-all-extensions= + +# In error mode, messages with a category besides ERROR or FATAL are +# suppressed, and no reports are done by default. Error mode is compatible with +# disabling specific errors. +#errors-only= + +# Always return a 0 (non-error) status code, even if lint errors are found. +# This is primarily useful in continuous integration scripts. +#exit-zero= + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code. +extension-pkg-allow-list= + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code. (This is an alternative name to extension-pkg-allow-list +# for backward compatibility.) +extension-pkg-whitelist= + +# Return non-zero exit code if any of these messages/categories are detected, +# even if score is above --fail-under value. Syntax same as enable. Messages +# specified are enabled, while categories only check already-enabled messages. +fail-on= + +# Specify a score threshold under which the program will exit with error. +fail-under=10 + +# Interpret the stdin as a python script, whose filename needs to be passed as +# the module_or_package argument. +#from-stdin= + +# Files or directories to be skipped. They should be base names, not paths. +ignore=CVS + +# Add files or directories matching the regular expressions patterns to the +# ignore-list. The regex matches against paths and can be in Posix or Windows +# format. Because '\\' represents the directory delimiter on Windows systems, +# it can't be used as an escape character. +ignore-paths= + +# Files or directories matching the regular expression patterns are skipped. +# The regex matches against base names, not paths. The default value ignores +# Emacs file locks +ignore-patterns=^\.# + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis). It +# supports qualified module names, as well as Unix pattern matching. +ignored-modules= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +#init-hook= + +# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the +# number of processors available to use, and will cap the count on Windows to +# avoid hangs. +jobs=1 + +# Control the amount of potential inferred values when inferring a single +# object. This can help the performance when dealing with large functions or +# complex, nested conditions. +limit-inference-results=100 + +# List of plugins (as comma separated values of python module names) to load, +# usually to register additional checkers. +load-plugins= + +# Pickle collected data for later comparisons. +persistent=yes + +# Minimum Python version to use for version dependent checks. Will default to +# the version used to run pylint. +py-version=3.9 + +# Discover python modules and packages in the file system subtree. +recursive=no + +# Add paths to the list of the source roots. Supports globbing patterns. The +# source root is an absolute path or a path relative to the current working +# directory used to determine a package namespace for modules located under the +# source root. +source-roots= + +# When enabled, pylint would attempt to guess common misconfiguration and emit +# user-friendly hints instead of false-positive error messages. +suggestion-mode=yes + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + +# In verbose mode, extra non-checker-related info will be displayed. +#verbose= + + +[BASIC] + +# Naming style matching correct argument names. +argument-naming-style=snake_case + +# Regular expression matching correct argument names. Overrides argument- +# naming-style. If left empty, argument names will be checked with the set +# naming style. +#argument-rgx= + +# Naming style matching correct attribute names. +attr-naming-style=snake_case + +# Regular expression matching correct attribute names. Overrides attr-naming- +# style. If left empty, attribute names will be checked with the set naming +# style. +#attr-rgx= + +# Bad variable names which should always be refused, separated by a comma. +bad-names=foo, + bar, + baz, + toto, + tutu, + tata + +# Bad variable names regexes, separated by a comma. If names match any regex, +# they will always be refused +bad-names-rgxs= + +# Naming style matching correct class attribute names. +class-attribute-naming-style=any + +# Regular expression matching correct class attribute names. Overrides class- +# attribute-naming-style. If left empty, class attribute names will be checked +# with the set naming style. +#class-attribute-rgx= + +# Naming style matching correct class constant names. +class-const-naming-style=UPPER_CASE + +# Regular expression matching correct class constant names. Overrides class- +# const-naming-style. If left empty, class constant names will be checked with +# the set naming style. +#class-const-rgx= + +# Naming style matching correct class names. +class-naming-style=PascalCase + +# Regular expression matching correct class names. Overrides class-naming- +# style. If left empty, class names will be checked with the set naming style. +#class-rgx= + +# Naming style matching correct constant names. +const-naming-style=UPPER_CASE + +# Regular expression matching correct constant names. Overrides const-naming- +# style. If left empty, constant names will be checked with the set naming +# style. +#const-rgx= + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=-1 + +# Naming style matching correct function names. +function-naming-style=snake_case + +# Regular expression matching correct function names. Overrides function- +# naming-style. If left empty, function names will be checked with the set +# naming style. +#function-rgx= + +# Good variable names which should always be accepted, separated by a comma. +good-names=i, + j, + k, + ex, + Run, + _ + +# Good variable names regexes, separated by a comma. If names match any regex, +# they will always be accepted +good-names-rgxs= + +# Include a hint for the correct naming format with invalid-name. +include-naming-hint=no + +# Naming style matching correct inline iteration names. +inlinevar-naming-style=any + +# Regular expression matching correct inline iteration names. Overrides +# inlinevar-naming-style. If left empty, inline iteration names will be checked +# with the set naming style. +#inlinevar-rgx= + +# Naming style matching correct method names. +method-naming-style=snake_case + +# Regular expression matching correct method names. Overrides method-naming- +# style. If left empty, method names will be checked with the set naming style. +#method-rgx= + +# Naming style matching correct module names. +module-naming-style=snake_case + +# Regular expression matching correct module names. Overrides module-naming- +# style. If left empty, module names will be checked with the set naming style. +#module-rgx= + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=^_ + +# List of decorators that produce properties, such as abc.abstractproperty. Add +# to this list to register other decorators that produce valid properties. +# These decorators are taken in consideration only for invalid-name. +property-classes=abc.abstractproperty + +# Regular expression matching correct type alias names. If left empty, type +# alias names will be checked with the set naming style. +#typealias-rgx= + +# Regular expression matching correct type variable names. If left empty, type +# variable names will be checked with the set naming style. +#typevar-rgx= + +# Naming style matching correct variable names. +variable-naming-style=snake_case + +# Regular expression matching correct variable names. Overrides variable- +# naming-style. If left empty, variable names will be checked with the set +# naming style. +#variable-rgx= + + +[CLASSES] + +# Warn about protected attribute access inside special methods +check-protected-access-in-special-methods=no + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__, + __new__, + setUp, + asyncSetUp, + __post_init__ + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict,_fields,_replace,_source,_make,os._exit + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs + + +[DESIGN] + +# List of regular expressions of class ancestor names to ignore when counting +# public methods (see R0903) +exclude-too-few-public-methods= + +# List of qualified class names to ignore when counting class parents (see +# R0901) +ignored-parents= + +# Maximum number of arguments for function / method. +max-args=5 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Maximum number of boolean expressions in an if statement (see R0916). +max-bool-expr=5 + +# Maximum number of branch for function / method body. +max-branches=12 + +# Maximum number of locals for function / method body. +max-locals=15 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + +# Maximum number of return / yield for function / method body. +max-returns=6 + +# Maximum number of statements in function / method body. +max-statements=50 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when caught. +overgeneral-exceptions=builtins.BaseException,builtins.Exception + + +[FORMAT] + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=^\s*(# )??$ + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + +# Maximum number of characters on a single line. +max-line-length=100 + +# Maximum number of lines in a module. +max-module-lines=1000 + +# Allow the body of a class to be on the same line as the declaration if body +# contains single statement. +single-line-class-stmt=no + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + + +[IMPORTS] + +# List of modules that can be imported at any level, not just the top level +# one. +allow-any-import-level= + +# Allow explicit reexports by alias from a package __init__. +allow-reexport-from-package=no + +# Allow wildcard imports from modules that define __all__. +allow-wildcard-with-all=no + +# Deprecated modules which should not be used, separated by a comma. +deprecated-modules= + +# Output a graph (.gv or any supported image format) of external dependencies +# to the given file (report RP0402 must not be disabled). +ext-import-graph= + +# Output a graph (.gv or any supported image format) of all (i.e. internal and +# external) dependencies to the given file (report RP0402 must not be +# disabled). +import-graph= + +# Output a graph (.gv or any supported image format) of internal dependencies +# to the given file (report RP0402 must not be disabled). +int-import-graph= + +# Force import order to recognize a module as part of the standard +# compatibility libraries. +known-standard-library= + +# Force import order to recognize a module as part of a third party library. +known-third-party=enchant + +# Couples of modules and preferred modules, separated by a comma. +preferred-modules= + + +[LOGGING] + +# The type of string formatting that logging methods do. `old` means using % +# formatting, `new` is for `{}` formatting. +logging-format-style=old + +# Logging modules to check that the string format arguments are in logging +# function parameter format. +logging-modules=logging + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE, +# UNDEFINED. +confidence=HIGH, + CONTROL_FLOW, + INFERENCE, + INFERENCE_FAILURE, + UNDEFINED + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once). You can also use "--disable=all" to +# disable everything first and then re-enable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use "--disable=all --enable=classes +# --disable=W". +disable=raw-checker-failed, + bad-inline-option, + locally-disabled, + file-ignored, + suppressed-message, + useless-suppression, + deprecated-pragma, + use-symbolic-message-instead, + use-implicit-booleaness-not-comparison-to-string, + use-implicit-booleaness-not-comparison-to-zero + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time (only on the command line, not in the configuration file where +# it should appear only once). See also the "--disable" option for examples. +enable= + + +[METHOD_ARGS] + +# List of qualified names (i.e., library.method) which require a timeout +# parameter e.g. 'requests.api.get,requests.api.post' +timeout-methods=requests.api.delete,requests.api.get,requests.api.head,requests.api.options,requests.api.patch,requests.api.post,requests.api.put,requests.api.request + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME, + XXX, + TODO + +# Regular expression of note tags to take in consideration. +notes-rgx= + + +[REFACTORING] + +# Maximum number of nested blocks for function / method body +max-nested-blocks=5 + +# Complete name of functions that never returns. When checking for +# inconsistent-return-statements if a never returning function is called then +# it will be considered as an explicit return statement and no message will be +# printed. +never-returning-functions=sys.exit,argparse.parse_error + + +[REPORTS] + +# Python expression which should return a score less than or equal to 10. You +# have access to the variables 'fatal', 'error', 'warning', 'refactor', +# 'convention', and 'info' which contain the number of messages in each +# category, as well as 'statement' which is the total number of statements +# analyzed. This score is used by the global evaluation report (RP0004). +evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)) + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details. +msg-template= + +# Set the output format. Available formats are: text, parseable, colorized, +# json2 (improved json format), json (old json format) and msvs (visual +# studio). You can also give a reporter class, e.g. +# mypackage.mymodule.MyReporterClass. +#output-format= + +# Tells whether to display a full report or only the messages. +reports=no + +# Activate the evaluation score. +score=yes + + +[SIMILARITIES] + +# Comments are removed from the similarity computation +ignore-comments=yes + +# Docstrings are removed from the similarity computation +ignore-docstrings=yes + +# Imports are removed from the similarity computation +ignore-imports=yes + +# Signatures are removed from the similarity computation +ignore-signatures=yes + +# Minimum lines number of a similarity. +min-similarity-lines=4 + + +[SPELLING] + +# Limits count of emitted suggestions for spelling mistakes. +max-spelling-suggestions=4 + +# Spelling dictionary name. No available dictionaries : You need to install +# both the python package and the system dependency for enchant to work. +spelling-dict= + +# List of comma separated words that should be considered directives if they +# appear at the beginning of a comment and should not be checked. +spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy: + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains the private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to the private dictionary (see the +# --spelling-private-dict-file option) instead of raising a message. +spelling-store-unknown-words=no + + +[STRING] + +# This flag controls whether inconsistent-quotes generates a warning when the +# character used as a quote delimiter is used inconsistently within a module. +check-quote-consistency=no + +# This flag controls whether the implicit-str-concat should generate a warning +# on implicit string concatenation in sequences defined over several lines. +check-str-concat-over-line-jumps=no + + +[TYPECHECK] + +# List of decorators that produce context managers, such as +# contextlib.contextmanager. Add to this list to register other decorators that +# produce valid context managers. +contextmanager-decorators=contextlib.contextmanager + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members= + +# Tells whether to warn about missing members when the owner of the attribute +# is inferred to be None. +ignore-none=yes + +# This flag controls whether pylint should warn about no-member and similar +# checks whenever an opaque object is returned when inferring. The inference +# can return multiple potential results while evaluating a Python object, but +# some branches might not be evaluated, which results in partial inference. In +# that case, it might be useful to still emit no-member and other checks for +# the rest of the inferred objects. +ignore-on-opaque-inference=yes + +# List of symbolic message names to ignore for Mixin members. +ignored-checks-for-mixins=no-member, + not-async-context-manager, + not-context-manager, + attribute-defined-outside-init + +# List of class names for which member attributes should not be checked (useful +# for classes with dynamically set attributes). This supports the use of +# qualified names. +ignored-classes=optparse.Values,thread._local,_thread._local,argparse.Namespace + +# Show a hint with possible names when a member name was not found. The aspect +# of finding the hint is based on edit distance. +missing-member-hint=yes + +# The minimum edit distance a name should have in order to be considered a +# similar match for a missing member name. +missing-member-hint-distance=1 + +# The total number of similar names that should be taken in consideration when +# showing a hint for a missing member. +missing-member-max-choices=1 + +# Regex pattern to define which classes are considered mixins. +mixin-class-rgx=.*[Mm]ixin + +# List of decorators that change the signature of a decorated function. +signature-mutators= + + +[VARIABLES] + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid defining new builtins when possible. +additional-builtins= + +# Tells whether unused global variables should be treated as a violation. +allow-global-unused-variables=yes + +# List of names allowed to shadow builtins +allowed-redefined-builtins= + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_, + _cb + +# A regular expression matching the name of dummy variables (i.e. expected to +# not be used). +dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ + +# Argument names that match this expression will be ignored. +ignored-argument-names=_.*|^ignored_|^unused_ + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# List of qualified module names which can have objects that can redefine +# builtins. +redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io +ignore=accounts_pb2.py + +[TYPECHECK] +generated-members=_ACCOUNT,_CREATEACCOUNTREQUEST,_CREATEACCOUNTRESPONSE,_GETACCOUNTSREQUEST,_GETACCOUNTSRESPONSE,_ACCOUNTDETAIL,_GETACCOUNTDETAILREQUEST,_ACCOUNTDETAILSSERVICE diff --git a/accounts/accounts.py b/accounts/accounts.py index 2d27337..3368fa9 100644 --- a/accounts/accounts.py +++ b/accounts/accounts.py @@ -2,232 +2,169 @@ # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. -from concurrent import futures +# app.py +import os import random import datetime -import os +import logging import grpc +from concurrent import futures +from flask import Flask, request, jsonify +from pymongo import MongoClient +from dotenv import load_dotenv from accounts_pb2 import * import accounts_pb2_grpc -import logging from dotmap import DotMap -from pymongo.mongo_client import MongoClient -from flask import Flask, request, jsonify -# set logging to debug -logging.basicConfig(level=logging.DEBUG) -from dotenv import load_dotenv +# Load environment variables load_dotenv() - -# db_host = os.getenv("DATABASE_HOST", "localhost") db_url = os.getenv("DB_URL") if db_url is None: - raise Exception("DB_URL environment variable is not set") + raise ValueError("DB_URL environment variable is not set") +protocol = os.getenv('SERVICE_PROTOCOL', 'http').lower() +if protocol not in ['http', 'grpc']: + raise ValueError("SERVICE_PROTOCOL environment variable must be 'http' or 'grpc'") -# protocol = os.getenv('SERVICE_PROTOCOL') -protocol = os.getenv('SERVICE_PROTOCOL', 'http') -if protocol is None: - raise Exception("SERVICE_PROTOCOL environment variable is not set") +# Database setup +client = MongoClient(db_url) +db = client["bank"] +collection = db["accounts"] -protocol = protocol.lower() -logging.debug(f"microservice protocol: {protocol}") +# Configure logging +logging.basicConfig(level=logging.DEBUG) +class AccountsService: + """ + Service for handling account operations. + """ -uri = db_url + def __init__(self): + self.collection = collection -client = MongoClient(uri) -db = client["bank"] -collection = db["accounts"] + def get_account_details(self, account_number): + """ + Retrieves account details given an account number. + Args: + account_number (str): The account number. -class AccountsGeneric: - def getAccountDetails(self, request): + Returns: + dict: Account details if found, empty dict otherwise. + """ logging.debug("Get Account Details called") - account = collection.find_one({"account_number": request.account_number}) - - + account = self.collection.find_one({"account_number": account_number}) + return account if account else {} - if account: - return {'account_number': account["account_number"],'name': account["name"], 'balance': account["balance"], 'currency': account["currency"]} - + def create_account(self, account_data): + """ + Creates a new account with the provided data. - return {} + Args: + account_data (dict): Data for the new account. - # Todo: check if the account already exist or not - - def createAccount(self, request): + Returns: + bool: True if account creation is successful, False otherwise. + """ logging.debug("Create Account called") - # find the account with email and account type if it already exist then return false - count = collection.count_documents( - {"email_id": request.email_id, "account_type": request.account_type} + # Check if the account already exists + existing_count = self.collection.count_documents( + {"email_id": account_data.email_id, "account_type": account_data.account_type} ) - - logging.debug(f" count: {count}") - - if count > 0: - logging.debug("Account already exist") - return False # CreateAccountResponse(result=False) - - account = { - "email_id": request.email_id, - "account_type": request.account_type, - "address": request.address, - "govt_id_number": request.govt_id_number, - "government_id_type": request.government_id_type, - # "account_holder_name": request.account_holder_name, - "name": request.name, + if existing_count > 0: + logging.debug("Account already exists") + return False + + new_account = { + "email_id": account_data.email_id, + "account_type": account_data.account_type, + "address": account_data.address, + "govt_id_number": account_data.govt_id_number, + "government_id_type": account_data.government_id_type, + "name": account_data.name, "balance": 100, "currency": "USD", + "account_number": f"IBAN{random.randint(1000000000000000, 9999999999999999)}", + "created_at": datetime.datetime.now() } + self.collection.insert_one(new_account) + return True - # assign a random 16 digit account number - account[ - "account_number" - ] = f"IBAN{random.randint(1000000000000000, 9999999999999999)}" - # timestamp the account creation - account["created_at"] = datetime.datetime.now() - # insert the account into the list of accounts - collection.insert_one(account) - return True # CreateAccountResponse(result=True) - - def getAccounts(self, request): - email_id = request.email_id - accounts = collection.find({"email_id": email_id}) - account_list = [] - for account in accounts: - # logging.debug(account["balance"]) - # account_list.append( - # Account( - # account_number=account["account_number"], - # email_id=account["email_id"], - # account_type=account["account_type"], - # address=account["address"], - # govt_id_number=account["govt_id_number"], - # government_id_type=account["government_id_type"], - # name=account["name"], - # balance=account["balance"], - # currency=account["currency"], - # ) - # ) - acc = { - k: v - for k, v in account.items() - if k - in [ - "account_number", - "email_id", - "account_type", - "address", - "govt_id_number", - "government_id_type", - "name", - "balance", - "currency", - ] - } - account_list.append(acc) - - return account_list + def get_accounts(self, email_id): + """ + Retrieves all accounts for a given email ID. + Args: + email_id (str): Email ID to search for accounts. -class AccountDetailsService(accounts_pb2_grpc.AccountDetailsServiceServicer): - def __init__(self): - self.accounts = AccountsGeneric() + Returns: + list: A list of accounts associated with the email ID. + """ + accounts = self.collection.find({"email_id": email_id}) + return [acc for acc in accounts if acc is not None] - def getAccountDetails(self, request, context): - logging.debug("Get Account Details called") +class AccountDetailsService(accounts_pb2_grpc.AccountDetailsServiceServicer): + """ + gRPC service for account details. + """ - account = self.accounts.getAccountDetails(request) + def __init__(self): + self.service = AccountsService() - if len(account) > 0: - return AccountDetail( - account_number=account["account_number"], - name=account["name"], - balance=account["balance"], - currency=account["currency"], - ) + def get_account_details(self, request, context): + account = self.service.get_account_details(request.account_number) + if account: + return AccountDetail(**account) return AccountDetail() - def createAccount(self, request, context): - # return self.accounts.createAccount(request) - result = self.accounts.createAccount(request) + def create_account(self, request, context): + result = self.service.create_account(request) return CreateAccountResponse(result=result) - def getAccounts(self, request, context): - # return self.accounts.getAccounts(request) - accounts = self.accounts.getAccounts(request) - account_list = [] - for account in accounts: - account_list.append( - Account( - account_number=account["account_number"], - email_id=account["email_id"], - account_type=account["account_type"], - address=account["address"], - govt_id_number=account["govt_id_number"], - government_id_type=account["government_id_type"], - name=account["name"], - balance=account["balance"], - currency=account["currency"], - ) - ) - return GetAccountsResponse(accounts=account_list) + def get_accounts(self, request, context): + accounts = self.service.get_accounts(request.email_id) + return GetAccountsResponse(accounts=[Account(**acc) for acc in accounts]) +# Flask App Setup app = Flask(__name__) -accounts_generic = AccountsGeneric() +accounts_service = AccountsService() + @app.route("/account-detail", methods=["POST"]) -def getAccountDetails(): - data = request.json - data = DotMap(data) - # account_number = request.json["account_number"] - account = accounts_generic.getAccountDetails(data) +def get_account_details(): + data = DotMap(request.json) + account = accounts_service.get_account_details(data.account_number) return jsonify(account) @app.route("/create-account", methods=["POST"]) -def createAccount(): - data = request.json - data = DotMap(data) - result = accounts_generic.createAccount(data) - return jsonify(result) +def create_account(): + data = DotMap(request.json) + result = accounts_service.create_account(data) + return jsonify(result=result) @app.route("/get-all-accounts", methods=["POST"]) -def getAccounts(): - data = request.json - data = DotMap(data) - accounts = accounts_generic.getAccounts(data) +def get_accounts(): + data = DotMap(request.json) + accounts = accounts_service.get_accounts(data.email_id) return jsonify(accounts) - -def serverFlask(port): - logging.debug(f"Starting Flask server on port {port}") - app.run(host='0.0.0.0' ,port=port, debug=True) - - -def serverGRPC(port): - # recommendations_host = os.getenv("RECOMMENDATIONS_HOST", "localhost") - server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) - accounts_pb2_grpc.add_AccountDetailsServiceServicer_to_server( - AccountDetailsService(), server - ) - server.add_insecure_port(f"[::]:{port}") - # server.add_insecure_port(f"{recommendations_host}:50051") - # print server ip and port - logging.debug(f"Server started at port {port}") - # print IP - server.start() - server.wait_for_termination() - - - - -if __name__ == "__main__": +def run_server(): port = 50051 - # serverGRPC(port) if protocol == "grpc": - serverGRPC(port) + server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) + accounts_pb2_grpc.add_AccountDetailsServiceServicer_to_server( + AccountDetailsService(), server + ) + server.add_insecure_port(f"[::]:{port}") + logging.debug(f"gRPC server starting on port {port}") + server.start() + server.wait_for_termination() else: - serverFlask(port) + logging.debug(f"Flask server starting on port {port}") + app.run(host='0.0.0.0', port=port, debug=True) + + +if __name__ == "__main__": + run_server() diff --git a/accounts/accounts_pb2.py b/accounts/accounts_pb2.py index ac6ba3e..e3e85cd 100644 --- a/accounts/accounts_pb2.py +++ b/accounts/accounts_pb2.py @@ -14,30 +14,50 @@ _sym_db = _symbol_database.Default() - - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0e\x61\x63\x63ounts.proto\"\xbf\x01\n\x07\x41\x63\x63ount\x12\x16\n\x0e\x61\x63\x63ount_number\x18\x01 \x01(\t\x12\x10\n\x08\x65mail_id\x18\x02 \x01(\t\x12\x14\n\x0c\x61\x63\x63ount_type\x18\x03 \x01(\t\x12\x0f\n\x07\x61\x64\x64ress\x18\x04 \x01(\t\x12\x16\n\x0egovt_id_number\x18\x05 \x01(\t\x12\x1a\n\x12government_id_type\x18\x06 \x01(\t\x12\x0c\n\x04name\x18\x07 \x01(\t\x12\x10\n\x08\x63urrency\x18\x08 \x01(\t\x12\x0f\n\x07\x62\x61lance\x18\t \x01(\x01\"\x91\x01\n\x14\x43reateAccountRequest\x12\x10\n\x08\x65mail_id\x18\x01 \x01(\t\x12\x14\n\x0c\x61\x63\x63ount_type\x18\x02 \x01(\t\x12\x0f\n\x07\x61\x64\x64ress\x18\x03 \x01(\t\x12\x16\n\x0egovt_id_number\x18\x04 \x01(\t\x12\x1a\n\x12government_id_type\x18\x05 \x01(\t\x12\x0c\n\x04name\x18\x06 \x01(\t\"\'\n\x15\x43reateAccountResponse\x12\x0e\n\x06result\x18\x01 \x01(\x08\"&\n\x12GetAccountsRequest\x12\x10\n\x08\x65mail_id\x18\x01 \x01(\t\"1\n\x13GetAccountsResponse\x12\x1a\n\x08\x61\x63\x63ounts\x18\x01 \x03(\x0b\x32\x08.Account\"X\n\rAccountDetail\x12\x16\n\x0e\x61\x63\x63ount_number\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0f\n\x07\x62\x61lance\x18\x03 \x01(\x01\x12\x10\n\x08\x63urrency\x18\x04 \x01(\t\"1\n\x17GetAccountDetailRequest\x12\x16\n\x0e\x61\x63\x63ount_number\x18\x01 \x01(\t2\xd0\x01\n\x15\x41\x63\x63ountDetailsService\x12=\n\x11getAccountDetails\x12\x18.GetAccountDetailRequest\x1a\x0e.AccountDetail\x12>\n\rcreateAccount\x12\x15.CreateAccountRequest\x1a\x16.CreateAccountResponse\x12\x38\n\x0bgetAccounts\x12\x13.GetAccountsRequest\x1a\x14.GetAccountsResponseb\x06proto3') +DESCRIPTOR = ( + _descriptor_pool.Default().AddSerializedFile( + b'\n\x0e\x61\x63\x63ounts.proto\"\xbf\x01\n\x07\x41\x63\x63ount' + b'\x12\x16\n\x0e\x61\x63\x63ount_number\x18\x01 \x01(\t\x12\x10\n\x08' + b'\x65mail_id\x18\x02 \x01(\t\x12\x14\n\x0c\x61\x63\x63ount_type\x18\x03 ' + b'\x01(\t\x12\x0f\n\x07\x61\x64\x64ress\x18\x04 \x01(\t\x12\x16\n\x0e' + b'govt_id_number\x18\x05 \x01(\t\x12\x1a\n\x12government_id_type\x18\x06 ' + b'\x01(\t\x12\x0c\n\x04name\x18\x07 \x01(\t\x12\x10\n\x08\x63urrency\x18\x08 ' + b'\x01(\t\x12\x0f\n\x07\x62\x61lance\x18\t \x01(\x01\"\x91\x01\n\x14' + b'\x43reateAccountRequest\x12\x10\n\x08\x65mail_id\x18\x01 \x01(\t\x12\x14\n\x0c' + b'\x61\x63\x63ount_type\x18\x02 \x01(\t\x12\x0f\n\x07\x61\x64\x64ress\x18\x03 ' + b'\x01(\t\x12\x16\n\x0egovt_id_number\x18\x04 \x01(\t\x12\x1a\n\x12government_id_type' + b'\x18\x05 \x01(\t\x12\x0c\n\x04name\x18\x06 \x01(\t\"\'\n\x15\x43reateAccountResponse' + b'\x12\x0e\n\x06result\x18\x01 \x01(\x08\"&\n\x12GetAccountsRequest\x12\x10\n\x08' + b'\x65mail_id\x18\x01 \x01(\t\"1\n\x13GetAccountsResponse\x12\x1a\n\x08\x61\x63\x63ounts' + b'\x18\x01 \x03(\x0b\x32\x08.Account\"X\n\rAccountDetail\x12\x16\n\x0e\x61\x63\x63ount_number' + b'\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0f\n\x07\x62\x61lance\x18\x03 ' + b'\x01(\x01\x12\x10\n\x08\x63urrency\x18\x04 \x01(\t\"1\n\x17GetAccountDetailRequest\x12\x16' + b'\n\x0e\x61\x63\x63ount_number\x18\x01 \x01(\t2\xd0\x01\n\x15\x41\x63\x63ountDetailsService' + b'\x12=\n\x11getAccountDetails\x12\x18.GetAccountDetailRequest\x1a\x0e.AccountDetail' + b'\x12>\n\rcreateAccount\x12\x15.CreateAccountRequest\x1a\x16.CreateAccountResponse' + b'\x12\x38\n\x0bgetAccounts\x12\x13.GetAccountsRequest\x1a\x14.GetAccountsResponseb\x06proto3' + ) +) _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'accounts_pb2', globals()) -if _descriptor._USE_C_DESCRIPTORS == False: - - DESCRIPTOR._options = None - _ACCOUNT._serialized_start=19 - _ACCOUNT._serialized_end=210 - _CREATEACCOUNTREQUEST._serialized_start=213 - _CREATEACCOUNTREQUEST._serialized_end=358 - _CREATEACCOUNTRESPONSE._serialized_start=360 - _CREATEACCOUNTRESPONSE._serialized_end=399 - _GETACCOUNTSREQUEST._serialized_start=401 - _GETACCOUNTSREQUEST._serialized_end=439 - _GETACCOUNTSRESPONSE._serialized_start=441 - _GETACCOUNTSRESPONSE._serialized_end=490 - _ACCOUNTDETAIL._serialized_start=492 - _ACCOUNTDETAIL._serialized_end=580 - _GETACCOUNTDETAILREQUEST._serialized_start=582 - _GETACCOUNTDETAILREQUEST._serialized_end=631 - _ACCOUNTDETAILSSERVICE._serialized_start=634 - _ACCOUNTDETAILSSERVICE._serialized_end=842 +if _descriptor._USE_C_DESCRIPTORS is False: + + DESCRIPTOR._options = None + _ACCOUNT._serialized_start=19 + _ACCOUNT._serialized_end=210 + _CREATEACCOUNTREQUEST._serialized_start=213 + _CREATEACCOUNTREQUEST._serialized_end=358 + _CREATEACCOUNTRESPONSE._serialized_start=360 + _CREATEACCOUNTRESPONSE._serialized_end=399 + _GETACCOUNTSREQUEST._serialized_start=401 + _GETACCOUNTSREQUEST._serialized_end=439 + _GETACCOUNTSRESPONSE._serialized_start=441 + _GETACCOUNTSRESPONSE._serialized_end=490 + _ACCOUNTDETAIL._serialized_start=492 + _ACCOUNTDETAIL._serialized_end=580 + _GETACCOUNTDETAILREQUEST._serialized_start=582 + _GETACCOUNTDETAILREQUEST._serialized_end=631 + _ACCOUNTDETAILSSERVICE._serialized_start=634 + _ACCOUNTDETAILSSERVICE._serialized_end=842 # @@protoc_insertion_point(module_scope) diff --git a/accounts/accounts_pb2_grpc.py b/accounts/accounts_pb2_grpc.py index 6acacb6..8835bb0 100644 --- a/accounts/accounts_pb2_grpc.py +++ b/accounts/accounts_pb2_grpc.py @@ -3,146 +3,188 @@ # license that can be found in the LICENSE file. # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -"""Client and server classes corresponding to protobuf-defined services.""" +"""Client and server classes corresponding to protobuf-defined services. +This module provides client and server classes for the AccountDetailsService using gRPC. +""" import grpc +import accounts_pb2 -import accounts_pb2 as accounts__pb2 - - -class AccountDetailsServiceStub(object): - """message GetAccountDetailResponse { - AccountDetail account = 1; - } - +class AccountDetailsServiceStub: + """ + Stub for the AccountDetailsService. + Provides methods to interact with the AccountDetailsService. """ - def __init__(self, channel): - """Constructor. + """ + Initialize the AccountDetailsServiceStub. Args: - channel: A grpc.Channel. + channel (grpc.Channel): A gRPC channel. """ - self.getAccountDetails = channel.unary_unary( - '/AccountDetailsService/getAccountDetails', - request_serializer=accounts__pb2.GetAccountDetailRequest.SerializeToString, - response_deserializer=accounts__pb2.AccountDetail.FromString, - ) - self.createAccount = channel.unary_unary( - '/AccountDetailsService/createAccount', - request_serializer=accounts__pb2.CreateAccountRequest.SerializeToString, - response_deserializer=accounts__pb2.CreateAccountResponse.FromString, - ) - self.getAccounts = channel.unary_unary( - '/AccountDetailsService/getAccounts', - request_serializer=accounts__pb2.GetAccountsRequest.SerializeToString, - response_deserializer=accounts__pb2.GetAccountsResponse.FromString, - ) - - -class AccountDetailsServiceServicer(object): - """message GetAccountDetailResponse { - AccountDetail account = 1; - } + self.get_account_details = channel.unary_unary( + '/AccountDetailsService/getAccountDetails', + request_serializer=accounts_pb2.GetAccountDetailRequest.SerializeToString, + response_deserializer=accounts_pb2.AccountDetail.FromString, + ) + self.create_account = channel.unary_unary( + '/AccountDetailsService/createAccount', + request_serializer=accounts_pb2.CreateAccountRequest.SerializeToString, + response_deserializer=accounts_pb2.CreateAccountResponse.FromString, + ) + self.get_accounts = channel.unary_unary( + '/AccountDetailsService/getAccounts', + request_serializer=accounts_pb2.GetAccountsRequest.SerializeToString, + response_deserializer=accounts_pb2.GetAccountsResponse.FromString, + ) + +class AccountDetailsServiceServicer: + """ + Service for managing account details. + Provides methods to get, create, and list account details. """ - def getAccountDetails(self, request, context): - """Missing associated documentation comment in .proto file.""" + @staticmethod + def get_account_details(request, context): + """ + Retrieve account details for a given account ID. + + Args: + request: The request containing the account ID. + context: gRPC context. + + Raises: + NotImplementedError: If the method is not yet implemented. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') - def createAccount(self, request, context): - """Missing associated documentation comment in .proto file.""" + @staticmethod + def create_account(request, context): + """ + Create a new account with the provided details. + + Args: + request: The request containing account creation details. + context: gRPC context. + + Raises: + NotImplementedError: If the method is not yet implemented. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') - def getAccounts(self, request, context): - """Missing associated documentation comment in .proto file.""" + @staticmethod + def get_accounts(request, context): + """ + Retrieve a list of all accounts. + + Args: + request: The request for getting accounts. + context: gRPC context. + + Raises: + NotImplementedError: If the method is not yet implemented. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') +def add_account_details_service_servicer_to_server(servicer, server): + """ + Register the AccountDetailsServiceServicer with the gRPC server. - -def add_AccountDetailsServiceServicer_to_server(servicer, server): + Args: + servicer (AccountDetailsServiceServicer): The servicer instance. + server (grpc.Server): The gRPC server. + """ rpc_method_handlers = { - 'getAccountDetails': grpc.unary_unary_rpc_method_handler( - servicer.getAccountDetails, - request_deserializer=accounts__pb2.GetAccountDetailRequest.FromString, - response_serializer=accounts__pb2.AccountDetail.SerializeToString, - ), - 'createAccount': grpc.unary_unary_rpc_method_handler( - servicer.createAccount, - request_deserializer=accounts__pb2.CreateAccountRequest.FromString, - response_serializer=accounts__pb2.CreateAccountResponse.SerializeToString, - ), - 'getAccounts': grpc.unary_unary_rpc_method_handler( - servicer.getAccounts, - request_deserializer=accounts__pb2.GetAccountsRequest.FromString, - response_serializer=accounts__pb2.GetAccountsResponse.SerializeToString, - ), + 'getAccountDetails': grpc.unary_unary_rpc_method_handler( + servicer.get_account_details, + request_deserializer=accounts_pb2.GetAccountDetailRequest.FromString, + response_serializer=accounts_pb2.AccountDetail.SerializeToString, + ), + 'createAccount': grpc.unary_unary_rpc_method_handler( + servicer.create_account, + request_deserializer=accounts_pb2.CreateAccountRequest.FromString, + response_serializer=accounts_pb2.CreateAccountResponse.SerializeToString, + ), + 'getAccounts': grpc.unary_unary_rpc_method_handler( + servicer.get_accounts, + request_deserializer=accounts_pb2.GetAccountsRequest.FromString, + response_serializer=accounts_pb2.GetAccountsResponse.SerializeToString, + ), } generic_handler = grpc.method_handlers_generic_handler( - 'AccountDetailsService', rpc_method_handlers) + 'AccountDetailsService', rpc_method_handlers) server.add_generic_rpc_handlers((generic_handler,)) - - # This class is part of an EXPERIMENTAL API. class AccountDetailsService(object): - """message GetAccountDetailResponse { - AccountDetail account = 1; - } - """ + AccountDetailsService provides gRPC-based services for managing and retrieving account details. + """ + + GET_ACCOUNT_DETAILS_PATH = '/AccountDetailsService/getAccountDetails' + CREATE_ACCOUNT_PATH = '/AccountDetailsService/createAccount' + GET_ACCOUNTS_PATH = '/AccountDetailsService/getAccounts' @staticmethod - def getAccountDetails(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary(request, target, '/AccountDetailsService/getAccountDetails', - accounts__pb2.GetAccountDetailRequest.SerializeToString, - accounts__pb2.AccountDetail.FromString, - options, channel_credentials, - insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + def get_account_details(request, target, options=(), channel_credentials=None, + call_credentials=None, insecure=False, compression=None, + wait_for_ready=None, timeout=None, metadata=None): + """ + Fetches account details based on the provided request. + + :param request: gRPC request object for getting account details. + :param target: The server address. + :other params: Additional gRPC call configurations. + :return: gRPC response for account details. + """ + return grpc.experimental.unary_unary( + request, target, AccountDetailsService.GET_ACCOUNT_DETAILS_PATH, + accounts_pb2.GetAccountDetailRequest.SerializeToString, + accounts_pb2.AccountDetail.FromString, + options, channel_credentials, insecure, call_credentials, + compression, wait_for_ready, timeout, metadata + ) @staticmethod - def createAccount(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary(request, target, '/AccountDetailsService/createAccount', - accounts__pb2.CreateAccountRequest.SerializeToString, - accounts__pb2.CreateAccountResponse.FromString, - options, channel_credentials, - insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + def create_account(request, target, options=(), channel_credentials=None, + call_credentials=None, insecure=False, compression=None, + wait_for_ready=None, timeout=None, metadata=None): + """ + Handles the creation of a new account. + + :param request: gRPC request object for account creation. + :param target: The server address. + :other params: Additional gRPC call configurations. + :return: gRPC response for account creation. + """ + return grpc.experimental.unary_unary( + request, target, AccountDetailsService.CREATE_ACCOUNT_PATH, + accounts_pb2.CreateAccountRequest.SerializeToString, + accounts_pb2.CreateAccountResponse.FromString, + options, channel_credentials, insecure, call_credentials, + compression, wait_for_ready, timeout, metadata + ) @staticmethod - def getAccounts(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary(request, target, '/AccountDetailsService/getAccounts', - accounts__pb2.GetAccountsRequest.SerializeToString, - accounts__pb2.GetAccountsResponse.FromString, - options, channel_credentials, - insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + def get_accounts(request, target, options=(), channel_credentials=None, + call_credentials=None, insecure=False, compression=None, + wait_for_ready=None, timeout=None, metadata=None): + """ + Retrieves multiple accounts based on the given request. + + :param request: gRPC request object for retrieving accounts. + :param target: The server address. + :other params: Additional gRPC call configurations. + :return: gRPC response for the accounts retrieval. + """ + return grpc.experimental.unary_unary( + request, target, AccountDetailsService.GET_ACCOUNTS_PATH, + accounts_pb2.GetAccountsRequest.SerializeToString, + accounts_pb2.GetAccountsResponse.FromString, + options, channel_credentials, insecure, call_credentials, + compression, wait_for_ready, timeout, metadata + ) diff --git a/accounts/api_client.py b/accounts/api_client.py index 93598de..0ee795b 100644 --- a/accounts/api_client.py +++ b/accounts/api_client.py @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. +# client.py import grpc from accounts_pb2_grpc import * from accounts_pb2 import * @@ -10,5 +11,5 @@ client = AccountDetailsServiceStub(channel) request = CreateAccountRequest(email_id="test", account_type="test", address="test", govt_id_number="test", government_id_type="test", name="test") -response = client.createAccount(request) +response = client.create_account(request) print(response) \ No newline at end of file diff --git a/dashboard/accounts_pb2.py b/dashboard/accounts_pb2.py index ac6ba3e..3cfa9e3 100644 --- a/dashboard/accounts_pb2.py +++ b/dashboard/accounts_pb2.py @@ -16,28 +16,46 @@ - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0e\x61\x63\x63ounts.proto\"\xbf\x01\n\x07\x41\x63\x63ount\x12\x16\n\x0e\x61\x63\x63ount_number\x18\x01 \x01(\t\x12\x10\n\x08\x65mail_id\x18\x02 \x01(\t\x12\x14\n\x0c\x61\x63\x63ount_type\x18\x03 \x01(\t\x12\x0f\n\x07\x61\x64\x64ress\x18\x04 \x01(\t\x12\x16\n\x0egovt_id_number\x18\x05 \x01(\t\x12\x1a\n\x12government_id_type\x18\x06 \x01(\t\x12\x0c\n\x04name\x18\x07 \x01(\t\x12\x10\n\x08\x63urrency\x18\x08 \x01(\t\x12\x0f\n\x07\x62\x61lance\x18\t \x01(\x01\"\x91\x01\n\x14\x43reateAccountRequest\x12\x10\n\x08\x65mail_id\x18\x01 \x01(\t\x12\x14\n\x0c\x61\x63\x63ount_type\x18\x02 \x01(\t\x12\x0f\n\x07\x61\x64\x64ress\x18\x03 \x01(\t\x12\x16\n\x0egovt_id_number\x18\x04 \x01(\t\x12\x1a\n\x12government_id_type\x18\x05 \x01(\t\x12\x0c\n\x04name\x18\x06 \x01(\t\"\'\n\x15\x43reateAccountResponse\x12\x0e\n\x06result\x18\x01 \x01(\x08\"&\n\x12GetAccountsRequest\x12\x10\n\x08\x65mail_id\x18\x01 \x01(\t\"1\n\x13GetAccountsResponse\x12\x1a\n\x08\x61\x63\x63ounts\x18\x01 \x03(\x0b\x32\x08.Account\"X\n\rAccountDetail\x12\x16\n\x0e\x61\x63\x63ount_number\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0f\n\x07\x62\x61lance\x18\x03 \x01(\x01\x12\x10\n\x08\x63urrency\x18\x04 \x01(\t\"1\n\x17GetAccountDetailRequest\x12\x16\n\x0e\x61\x63\x63ount_number\x18\x01 \x01(\t2\xd0\x01\n\x15\x41\x63\x63ountDetailsService\x12=\n\x11getAccountDetails\x12\x18.GetAccountDetailRequest\x1a\x0e.AccountDetail\x12>\n\rcreateAccount\x12\x15.CreateAccountRequest\x1a\x16.CreateAccountResponse\x12\x38\n\x0bgetAccounts\x12\x13.GetAccountsRequest\x1a\x14.GetAccountsResponseb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( + b'\n\x0e\x61\x63\x63ounts.proto\"\xbf\x01\n\x07\x41\x63\x63ount' + b'\x12\x16\n\x0e\x61\x63\x63ount_number\x18\x01 \x01(\t\x12\x10\n\x08' + b'\x65mail_id\x18\x02 \x01(\t\x12\x14\n\x0c\x61\x63\x63ount_type\x18\x03 \x01(\t' + b'\x12\x0f\n\x07\x61\x64\x64ress\x18\x04 \x01(\t\x12\x16\n\x0egovt_id_number\x18\x05 \x01(\t' + b'\x12\x1a\n\x12government_id_type\x18\x06 \x01(\t\x12\x0c\n\x04name\x18\x07 \x01(\t' + b'\x12\x10\n\x08\x63urrency\x18\x08 \x01(\t\x12\x0f\n\x07\x62\x61lance\x18\t \x01(\x01' + b'\"\x91\x01\n\x14\x43reateAccountRequest\x12\x10\n\x08\x65mail_id\x18\x01 \x01(\t' + b'\x12\x14\n\x0c\x61\x63\x63ount_type\x18\x02 \x01(\t\x12\x0f\n\x07\x61\x64\x64ress\x18\x03 \x01(\t' + b'\x12\x16\n\x0egovt_id_number\x18\x04 \x01(\t\x12\x1a\n\x12government_id_type\x18\x05 \x01(\t' + b'\x12\x0c\n\x04name\x18\x06 \x01(\t\"\'\n\x15\x43reateAccountResponse\x12\x0e\n\x06result\x18\x01 \x01(\x08' + b'\"&\n\x12GetAccountsRequest\x12\x10\n\x08\x65mail_id\x18\x01 \x01(\t' + b'\"1\n\x13GetAccountsResponse\x12\x1a\n\x08\x61\x63\x63ounts\x18\x01 \x03(\x0b\x32\x08.Account' + b'\"X\n\rAccountDetail\x12\x16\n\x0e\x61\x63\x63ount_number\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t' + b'\x12\x0f\n\x07\x62\x61lance\x18\x03 \x01(\x01\x12\x10\n\x08\x63urrency\x18\x04 \x01(\t' + b'\"1\n\x17GetAccountDetailRequest\x12\x16\n\x0e\x61\x63\x63ount_number\x18\x01 \x01(\t' + b'2\xd0\x01\n\x15\x41\x63\x63ountDetailsService\x12=\n\x11getAccountDetails' + b'\x12\x18.GetAccountDetailRequest\x1a\x0e.AccountDetail' + b'\x12>\n\rcreateAccount\x12\x15.CreateAccountRequest\x1a\x16.CreateAccountResponse' + b'\x12\x38\n\x0bgetAccounts\x12\x13.GetAccountsRequest\x1a\x14.GetAccountsResponseb\x06proto3' +) _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'accounts_pb2', globals()) -if _descriptor._USE_C_DESCRIPTORS == False: - +if not _descriptor._USE_C_DESCRIPTORS: DESCRIPTOR._options = None - _ACCOUNT._serialized_start=19 - _ACCOUNT._serialized_end=210 - _CREATEACCOUNTREQUEST._serialized_start=213 - _CREATEACCOUNTREQUEST._serialized_end=358 - _CREATEACCOUNTRESPONSE._serialized_start=360 - _CREATEACCOUNTRESPONSE._serialized_end=399 - _GETACCOUNTSREQUEST._serialized_start=401 - _GETACCOUNTSREQUEST._serialized_end=439 - _GETACCOUNTSRESPONSE._serialized_start=441 - _GETACCOUNTSRESPONSE._serialized_end=490 - _ACCOUNTDETAIL._serialized_start=492 - _ACCOUNTDETAIL._serialized_end=580 - _GETACCOUNTDETAILREQUEST._serialized_start=582 - _GETACCOUNTDETAILREQUEST._serialized_end=631 - _ACCOUNTDETAILSSERVICE._serialized_start=634 - _ACCOUNTDETAILSSERVICE._serialized_end=842 + ACCOUNT._serialized_start=19 + ACCOUNT._serialized_end=210 + CREATEACCOUNTREQUEST._serialized_start=213 + CREATEACCOUNTREQUEST._serialized_end=358 + CREATEACCOUNTRESPONSE._serialized_start=360 + CREATEACCOUNTRESPONSE._serialized_end=399 + GETACCOUNTSREQUEST._serialized_start=401 + GETACCOUNTSREQUEST._serialized_end=439 + GETACCOUNTSRESPONSE._serialized_start=441 + GETACCOUNTSRESPONSE._serialized_end=490 + ACCOUNTDETAIL._serialized_start=492 + ACCOUNTDETAIL._serialized_end=580 + GETACCOUNTDETAILREQUEST._serialized_start=582 + GETACCOUNTDETAILREQUEST._serialized_end=631 + ACCOUNTDETAILSSERVICE._serialized_start=634 + ACCOUNTDETAILSSERVICE._serialized_end=842 # @@protoc_insertion_point(module_scope) diff --git a/dashboard/accounts_pb2_grpc.py b/dashboard/accounts_pb2_grpc.py index 6acacb6..1cccfdd 100644 --- a/dashboard/accounts_pb2_grpc.py +++ b/dashboard/accounts_pb2_grpc.py @@ -4,90 +4,114 @@ # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! """Client and server classes corresponding to protobuf-defined services.""" +# grpc_service.py +"""Client and server classes corresponding to protobuf-defined services.""" import grpc +import accounts_pb2 +import accounts_pb2_grpc -import accounts_pb2 as accounts__pb2 - - -class AccountDetailsServiceStub(object): - """message GetAccountDetailResponse { - AccountDetail account = 1; - } - - """ +class AccountDetailsServiceStub: + """Stub for the AccountDetailsService.""" def __init__(self, channel): - """Constructor. + """Initialize the AccountDetailsServiceStub. Args: - channel: A grpc.Channel. + channel (grpc.Channel): A gRPC channel. """ - self.getAccountDetails = channel.unary_unary( - '/AccountDetailsService/getAccountDetails', - request_serializer=accounts__pb2.GetAccountDetailRequest.SerializeToString, - response_deserializer=accounts__pb2.AccountDetail.FromString, - ) - self.createAccount = channel.unary_unary( - '/AccountDetailsService/createAccount', - request_serializer=accounts__pb2.CreateAccountRequest.SerializeToString, - response_deserializer=accounts__pb2.CreateAccountResponse.FromString, - ) - self.getAccounts = channel.unary_unary( - '/AccountDetailsService/getAccounts', - request_serializer=accounts__pb2.GetAccountsRequest.SerializeToString, - response_deserializer=accounts__pb2.GetAccountsResponse.FromString, - ) + self.get_account_details = channel.unary_unary( + '/AccountDetailsService/getAccountDetails', + request_serializer=accounts_pb2.GetAccountDetailRequest.SerializeToString, + response_deserializer=accounts_pb2.AccountDetail.FromString, + ) + self.create_account = channel.unary_unary( + '/AccountDetailsService/createAccount', + request_serializer=accounts_pb2.CreateAccountRequest.SerializeToString, + response_deserializer=accounts_pb2.CreateAccountResponse.FromString, + ) + self.get_accounts = channel.unary_unary( + '/AccountDetailsService/getAccounts', + request_serializer=accounts_pb2.GetAccountsRequest.SerializeToString, + response_deserializer=accounts_pb2.GetAccountsResponse.FromString, + ) class AccountDetailsServiceServicer(object): - """message GetAccountDetailResponse { - AccountDetail account = 1; - } + """Service for managing account details.""" - """ + def get_account_details(self, request, context): + """Retrieve account details based on the request. + + Args: + request: The request for account details. + context: The gRPC context. - def getAccountDetails(self, request, context): - """Missing associated documentation comment in .proto file.""" + Raises: + NotImplementedError: If the method is not implemented. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') - def createAccount(self, request, context): - """Missing associated documentation comment in .proto file.""" + def create_account(self, request, context): + """Create a new account. + + Args: + request: The request to create an account. + context: The gRPC context. + + Raises: + NotImplementedError: If the method is not implemented. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') - def getAccounts(self, request, context): - """Missing associated documentation comment in .proto file.""" + def get_accounts(self, request, context): + """Get a list of accounts. + + Args: + request: The request to get accounts. + context: The gRPC context. + + Raises: + NotImplementedError: If the method is not implemented. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') -def add_AccountDetailsServiceServicer_to_server(servicer, server): +def add_account_details_service_servicer_to_server(servicer, server): + """Register the servicer with the server. + + Args: + servicer: The service implementation. + server: The gRPC server. + """ rpc_method_handlers = { - 'getAccountDetails': grpc.unary_unary_rpc_method_handler( - servicer.getAccountDetails, - request_deserializer=accounts__pb2.GetAccountDetailRequest.FromString, - response_serializer=accounts__pb2.AccountDetail.SerializeToString, - ), - 'createAccount': grpc.unary_unary_rpc_method_handler( - servicer.createAccount, - request_deserializer=accounts__pb2.CreateAccountRequest.FromString, - response_serializer=accounts__pb2.CreateAccountResponse.SerializeToString, - ), - 'getAccounts': grpc.unary_unary_rpc_method_handler( - servicer.getAccounts, - request_deserializer=accounts__pb2.GetAccountsRequest.FromString, - response_serializer=accounts__pb2.GetAccountsResponse.SerializeToString, - ), + 'getAccountDetails': grpc.unary_unary_rpc_method_handler( + servicer.get_account_details, + request_deserializer=accounts_pb2.GetAccountDetailRequest.FromString, + response_serializer=accounts_pb2.AccountDetail.SerializeToString, + ), + 'createAccount': grpc.unary_unary_rpc_method_handler( + servicer.create_account, + request_deserializer=accounts_pb2.CreateAccountRequest.FromString, + response_serializer=accounts_pb2.CreateAccountResponse.SerializeToString, + ), + 'getAccounts': grpc.unary_unary_rpc_method_handler( + servicer.get_accounts, + request_deserializer=accounts_pb2.GetAccountsRequest.FromString, + response_serializer=accounts_pb2.GetAccountsResponse.SerializeToString, + ), } generic_handler = grpc.method_handlers_generic_handler( - 'AccountDetailsService', rpc_method_handlers) + 'AccountDetailsService', rpc_method_handlers) server.add_generic_rpc_handlers((generic_handler,)) + # This class is part of an EXPERIMENTAL API. class AccountDetailsService(object): """message GetAccountDetailResponse { @@ -97,7 +121,7 @@ class AccountDetailsService(object): """ @staticmethod - def getAccountDetails(request, + def get_account_details(request, target, options=(), channel_credentials=None, @@ -108,13 +132,13 @@ def getAccountDetails(request, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/AccountDetailsService/getAccountDetails', - accounts__pb2.GetAccountDetailRequest.SerializeToString, - accounts__pb2.AccountDetail.FromString, + accounts_pb2.GetAccountDetailRequest.SerializeToString, + accounts_pb2.AccountDetail.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod - def createAccount(request, + def create_account(request, target, options=(), channel_credentials=None, @@ -125,13 +149,13 @@ def createAccount(request, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/AccountDetailsService/createAccount', - accounts__pb2.CreateAccountRequest.SerializeToString, - accounts__pb2.CreateAccountResponse.FromString, + accounts_pb2.CreateAccountRequest.SerializeToString, + accounts_pb2.CreateAccountResponse.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod - def getAccounts(request, + def get_accounts(request, target, options=(), channel_credentials=None, @@ -142,7 +166,7 @@ def getAccounts(request, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/AccountDetailsService/getAccounts', - accounts__pb2.GetAccountsRequest.SerializeToString, - accounts__pb2.GetAccountsResponse.FromString, + accounts_pb2.GetAccountsRequest.SerializeToString, + accounts_pb2.GetAccountsResponse.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata) diff --git a/dashboard/dashboard.py b/dashboard/dashboard.py index fadfe27..dedc1cb 100644 --- a/dashboard/dashboard.py +++ b/dashboard/dashboard.py @@ -1,65 +1,64 @@ # Copyright (c) 2023 Cisco Systems, Inc. and its affiliates All rights reserved. # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. +""" +# dashboard.py + +This module implements a Flask application with various routes for handling +different functionalities, including account management, transactions, and +integration with gRPC services. +""" import os import logging import json - -# from google.protobuf.json_format import MessageToDict from flask_cors import CORS - from flask import Flask, render_template, request, jsonify import grpc - from dotenv import load_dotenv -load_dotenv() - -from accounts_pb2 import * -from accounts_pb2_grpc import * - -from transaction_pb2_grpc import * -from transaction_pb2 import * +from pymongo.mongo_client import MongoClient +import requests as flask_client_requests +# Specific imports from the protobuf-generated files +from accounts_pb2 import CreateAccountRequest, GetAccountDetailRequest, GetAccountsRequest +from accounts_pb2_grpc import AccountDetailsServiceStub +from transaction_pb2 import TransactionRequest, ZelleRequest, TransactionByIDRequest, GetALLTransactionsRequest +from transaction_pb2_grpc import TransactionServiceStub +from loan_pb2 import LoanRequest, LoansHistoryRequest from loan_pb2_grpc import LoanServiceStub -from loan_pb2 import * -from pymongo.mongo_client import MongoClient - -import requests as flask_client_requests +load_dotenv() -# set logging to debug +# Set logging to debug logging.basicConfig(level=logging.DEBUG) - -# db_host = os.getenv("DATABASE_HOST", "localhost") db_url = os.getenv("DB_URL") if db_url is None: raise Exception("DB_URL environment variable is not set") uri = db_url +logging.debug("Connecting to MongoDB at %s", uri) -logging.debug(f"Connecting to MongoDB at {uri}") - -# protocol = os.getenv('SERVICE_PROTOCOL') protocol = os.getenv('SERVICE_PROTOCOL', 'http') - if protocol is None: raise Exception("SERVICE_PROTOCOL environment variable is not set") protocol = protocol.lower() -logging.debug(f"microservice protocol: {protocol}") - +logging.debug("microservice protocol: %s", protocol) client = MongoClient(uri) db = client["bank"] collection = db["accounts"] - app = Flask(__name__) CORS(app) + + + + + @app.route("/") def render_homepage(): return f"Dashboard is running..." diff --git a/dashboard/loan_pb2.py b/dashboard/loan_pb2.py index 92e32f9..b0144ed 100644 --- a/dashboard/loan_pb2.py +++ b/dashboard/loan_pb2.py @@ -15,9 +15,26 @@ _sym_db = _symbol_database.Default() - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\nloan.proto\"\xda\x01\n\x0bLoanRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05\x65mail\x18\x02 \x01(\t\x12\x14\n\x0c\x61\x63\x63ount_type\x18\x03 \x01(\t\x12\x16\n\x0e\x61\x63\x63ount_number\x18\x04 \x01(\t\x12\x14\n\x0cgovt_id_type\x18\x05 \x01(\t\x12\x16\n\x0egovt_id_number\x18\x06 \x01(\t\x12\x11\n\tloan_type\x18\x07 \x01(\t\x12\x13\n\x0bloan_amount\x18\x08 \x01(\x01\x12\x15\n\rinterest_rate\x18\t \x01(\x01\x12\x13\n\x0btime_period\x18\n \x01(\t\"1\n\x0cLoanResponse\x12\x10\n\x08\x61pproved\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\"$\n\x13LoansHistoryRequest\x12\r\n\x05\x65mail\x18\x01 \x01(\t\"\xf6\x01\n\x04Loan\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05\x65mail\x18\x02 \x01(\t\x12\x14\n\x0c\x61\x63\x63ount_type\x18\x03 \x01(\t\x12\x16\n\x0e\x61\x63\x63ount_number\x18\x04 \x01(\t\x12\x14\n\x0cgovt_id_type\x18\x05 \x01(\t\x12\x16\n\x0egovt_id_number\x18\x06 \x01(\t\x12\x11\n\tloan_type\x18\x07 \x01(\t\x12\x13\n\x0bloan_amount\x18\x08 \x01(\x01\x12\x15\n\rinterest_rate\x18\t \x01(\x01\x12\x13\n\x0btime_period\x18\n \x01(\t\x12\x0e\n\x06status\x18\x0b \x01(\t\x12\x11\n\ttimestamp\x18\x0c \x01(\t\",\n\x14LoansHistoryResponse\x12\x14\n\x05loans\x18\x01 \x03(\x0b\x32\x05.Loan2\x7f\n\x0bLoanService\x12\x31\n\x12ProcessLoanRequest\x12\x0c.LoanRequest\x1a\r.LoanResponse\x12=\n\x0egetLoanHistory\x12\x14.LoansHistoryRequest\x1a\x15.LoansHistoryResponseb\x06proto3') +serialized_data = ( + b'\n\nloan.proto\"\xda\x01\n\x0bLoanRequest\x12\x0c\n\x04name\x18\x01 \x01(\t' + b'\x12\r\n\x05\x65mail\x18\x02 \x01(\t\x12\x14\n\x0c\x61\x63\x63ount_type\x18\x03 \x01(\t' + b'\x12\x16\n\x0e\x61\x63\x63ount_number\x18\x04 \x01(\t\x12\x14\n\x0cgovt_id_type\x18\x05 \x01(\t' + b'\x12\x16\n\x0egovt_id_number\x18\x06 \x01(\t\x12\x11\n\tloan_type\x18\x07 \x01(\t' + b'\x12\x13\n\x0bloan_amount\x18\x08 \x01(\x01\x12\x15\n\rinterest_rate\x18\t \x01(\x01' + b'\x12\x13\n\x0btime_period\x18\n \x01(\t\"1\n\x0cLoanResponse\x12\x10\n\x08\x61pproved\x18\x01 \x01(\x08' + b'\x12\x0f\n\x07message\x18\x02 \x01(\t\"$\n\x13LoansHistoryRequest\x12\r\n\x05\x65mail\x18\x01 \x01(\t' + b'\"\xf6\x01\n\x04Loan\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05\x65mail\x18\x02 \x01(\t' + b'\x12\x14\n\x0c\x61\x63\x63ount_type\x18\x03 \x01(\t\x12\x16\n\x0e\x61\x63\x63ount_number\x18\x04 \x01(\t' + b'\x12\x14\n\x0cgovt_id_type\x18\x05 \x01(\t\x12\x16\n\x0egovt_id_number\x18\x06 \x01(\t' + b'\x12\x11\n\tloan_type\x18\x07 \x01(\t\x12\x13\n\x0bloan_amount\x18\x08 \x01(\x01' + b'\x12\x15\n\rinterest_rate\x18\t \x01(\x01\x12\x13\n\x0btime_period\x18\n \x01(\t' + b'\x12\x0e\n\x06status\x18\x0b \x01(\t\x12\x11\n\ttimestamp\x18\x0c \x01(\t\",' + b'\n\x14LoansHistoryResponse\x12\x14\n\x05loans\x18\x01 \x03(\x0b\x32\x05.Loan2\x7f' + b'\n\x0bLoanService\x12\x31\n\x12ProcessLoanRequest\x12\x0c.LoanRequest\x1a\r.LoanResponse' + b'\x12=\n\x0egetLoanHistory\x12\x14.LoansHistoryRequest\x1a\x15.LoansHistoryResponseb\x06proto3' +) + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(serialized_data) _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'loan_pb2', globals()) diff --git a/dashboard/loan_pb2_grpc.py b/dashboard/loan_pb2_grpc.py index 4a73bc3..1b459cc 100644 --- a/dashboard/loan_pb2_grpc.py +++ b/dashboard/loan_pb2_grpc.py @@ -4,100 +4,151 @@ # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! """Client and server classes corresponding to protobuf-defined services.""" -import grpc +""" +Client and server classes corresponding to protobuf-defined services for LoanService. +""" + +""" +Client and server classes corresponding to protobuf-defined services for LoanService. +""" +import grpc import loan_pb2 as loan__pb2 +# Ensure that the protobuf module is correctly generated and available +if not hasattr(loan__pb2, 'LoanRequest'): + raise ImportError("loan_pb2 module does not have LoanRequest") +if not hasattr(loan__pb2, 'LoanResponse'): + raise ImportError("loan_pb2 module does not have LoanResponse") +if not hasattr(loan__pb2, 'LoansHistoryRequest'): + raise ImportError("loan_pb2 module does not have LoansHistoryRequest") +if not hasattr(loan__pb2, 'LoansHistoryResponse'): + raise ImportError("loan_pb2 module does not have LoansHistoryResponse") -class LoanServiceStub(object): - """Missing associated documentation comment in .proto file.""" + +class LoanServiceStub: + """ + Stub class for the LoanService. + Provides methods to interact with the LoanService via gRPC. + """ def __init__(self, channel): - """Constructor. + """ + Initialize the LoanServiceStub. Args: channel: A grpc.Channel. """ - self.ProcessLoanRequest = channel.unary_unary( - '/LoanService/ProcessLoanRequest', - request_serializer=loan__pb2.LoanRequest.SerializeToString, - response_deserializer=loan__pb2.LoanResponse.FromString, - ) - self.getLoanHistory = channel.unary_unary( - '/LoanService/getLoanHistory', - request_serializer=loan__pb2.LoansHistoryRequest.SerializeToString, - response_deserializer=loan__pb2.LoansHistoryResponse.FromString, - ) - - -class LoanServiceServicer(object): - """Missing associated documentation comment in .proto file.""" - - def ProcessLoanRequest(self, request, context): - """Missing associated documentation comment in .proto file.""" + self.process_loan_request = channel.unary_unary( + '/LoanService/ProcessLoanRequest', + request_serializer=loan__pb2.LoanRequest.SerializeToString, + response_deserializer=loan__pb2.LoanResponse.FromString, + ) + self.get_loan_history = channel.unary_unary( + '/LoanService/getLoanHistory', + request_serializer=loan__pb2.LoansHistoryRequest.SerializeToString, + response_deserializer=loan__pb2.LoansHistoryResponse.FromString, + ) + + +class LoanServiceServicer: + """ + Servicer class for the LoanService. + Implements server-side methods for handling LoanService requests. + """ + + def process_loan_request(self, request, context): + """ + Process a loan request. (To be implemented) + + Args: + request: A LoanRequest object. + context: gRPC context. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') - def getLoanHistory(self, request, context): - """Missing associated documentation comment in .proto file.""" + def get_loan_history(self, request, context): + """ + Retrieve loan history. (To be implemented) + + Args: + request: A LoansHistoryRequest object. + context: gRPC context. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') -def add_LoanServiceServicer_to_server(servicer, server): +def add_loan_service_servicer_to_server(servicer, server): + """ + Register the LoanServiceServicer to a gRPC server. + + Args: + servicer: An instance of LoanServiceServicer. + server: A gRPC server instance. + """ rpc_method_handlers = { - 'ProcessLoanRequest': grpc.unary_unary_rpc_method_handler( - servicer.ProcessLoanRequest, - request_deserializer=loan__pb2.LoanRequest.FromString, - response_serializer=loan__pb2.LoanResponse.SerializeToString, - ), - 'getLoanHistory': grpc.unary_unary_rpc_method_handler( - servicer.getLoanHistory, - request_deserializer=loan__pb2.LoansHistoryRequest.FromString, - response_serializer=loan__pb2.LoansHistoryResponse.SerializeToString, - ), + 'process_loan_request': grpc.unary_unary_rpc_method_handler( + servicer.process_loan_request, + request_deserializer=loan__pb2.LoanRequest.FromString, + response_serializer=loan__pb2.LoanResponse.SerializeToString, + ), + 'get_loan_history': grpc.unary_unary_rpc_method_handler( + servicer.get_loan_history, + request_deserializer=loan__pb2.LoansHistoryRequest.FromString, + response_serializer=loan__pb2.LoansHistoryResponse.SerializeToString, + ), } generic_handler = grpc.method_handlers_generic_handler( - 'LoanService', rpc_method_handlers) + 'LoanService', rpc_method_handlers) server.add_generic_rpc_handlers((generic_handler,)) - # This class is part of an EXPERIMENTAL API. -class LoanService(object): - """Missing associated documentation comment in .proto file.""" + +class LoanService: + """ + LoanService class providing static methods for gRPC calls. + """ @staticmethod - def ProcessLoanRequest(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): + def process_loan_request(request, target, options=(), channel_credentials=None, + call_credentials=None, insecure=False, compression=None, + wait_for_ready=None, timeout=None, metadata=None): + """ + Static method to process a loan request via gRPC. + + Args: + request: A LoanRequest object. + target: Target server address. + options, channel_credentials, call_credentials, insecure, compression, + wait_for_ready, timeout, metadata: gRPC call parameters. + """ return grpc.experimental.unary_unary(request, target, '/LoanService/ProcessLoanRequest', - loan__pb2.LoanRequest.SerializeToString, - loan__pb2.LoanResponse.FromString, - options, channel_credentials, - insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + loan__pb2.LoanRequest.SerializeToString, + loan__pb2.LoanResponse.FromString, + options, channel_credentials, + insecure, call_credentials, compression, + wait_for_ready, timeout, metadata) @staticmethod - def getLoanHistory(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): + def get_loan_history(request, target, options=(), channel_credentials=None, + call_credentials=None, insecure=False, compression=None, + wait_for_ready=None, timeout=None, metadata=None): + """ + Static method to retrieve loan history via gRPC. + + Args: + request: A LoansHistoryRequest object. + target: Target server address. + options, channel credentials, call credentials, insecure, compression, + wait for ready, timeout, metadata: gRPC call parameters. + """ return grpc.experimental.unary_unary(request, target, '/LoanService/getLoanHistory', - loan__pb2.LoansHistoryRequest.SerializeToString, - loan__pb2.LoansHistoryResponse.FromString, - options, channel_credentials, - insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + loan__pb2.LoansHistoryRequest.SerializeToString, + loan__pb2.LoansHistoryResponse.FromString, + options, channel_credentials, + insecure, call_credentials, compression, + wait_for_ready, timeout, metadata) diff --git a/dashboard/transaction_pb2.py b/dashboard/transaction_pb2.py index 1696859..6835d91 100644 --- a/dashboard/transaction_pb2.py +++ b/dashboard/transaction_pb2.py @@ -10,34 +10,52 @@ from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool from google.protobuf import symbol_database as _symbol_database + # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() - - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x11transaction.proto\"\xb0\x01\n\x12TransactionRequest\x12\x1d\n\x15sender_account_number\x18\x01 \x01(\t\x12\x1b\n\x13sender_account_type\x18\x02 \x01(\t\x12\x1f\n\x17receiver_account_number\x18\x03 \x01(\t\x12\x1d\n\x15receiver_account_type\x18\x04 \x01(\t\x12\x0e\n\x06\x61mount\x18\x05 \x01(\x01\x12\x0e\n\x06reason\x18\x06 \x01(\t\"8\n\x13TransactionResponse\x12\x10\n\x08\x61pproved\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\"3\n\x19GetALLTransactionsRequest\x12\x16\n\x0e\x61\x63\x63ount_number\x18\x01 \x01(\t\"\x7f\n\x0bTransaction\x12\x16\n\x0e\x61\x63\x63ount_number\x18\x01 \x01(\t\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x01\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x12\n\ntime_stamp\x18\x04 \x01(\t\x12\x0c\n\x04type\x18\x05 \x01(\t\x12\x16\n\x0etransaction_id\x18\x06 \x01(\t\"@\n\x1aGetALLTransactionsResponse\x12\"\n\x0ctransactions\x18\x01 \x03(\x0b\x32\x0c.Transaction\"\\\n\x0cZelleRequest\x12\x14\n\x0csender_email\x18\x01 \x01(\t\x12\x16\n\x0ereceiver_email\x18\x02 \x01(\t\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x01\x12\x0e\n\x06reason\x18\x04 \x01(\t\"0\n\x16TransactionByIDRequest\x12\x16\n\x0etransaction_id\x18\x01 \x01(\t2\x8a\x02\n\x12TransactionService\x12\x36\n\tsendMoney\x12\x13.TransactionRequest\x1a\x14.TransactionResponse\x12Q\n\x16getTransactionsHistory\x12\x1a.GetALLTransactionsRequest\x1a\x1b.GetALLTransactionsResponse\x12,\n\x05Zelle\x12\r.ZelleRequest\x1a\x14.TransactionResponse\x12;\n\x12getTransactionByID\x12\x17.TransactionByIDRequest\x1a\x0c.Transactionb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( + b'\n\x11transaction.proto\"\xb0\x01\n\x12TransactionRequest\x12\x1d\n\x15' + b'sender_account_number\x18\x01 \x01(\t\x12\x1b\n\x13sender_account_type\x18\x02 \x01(\t' + b'\x12\x1f\n\x17receiver_account_number\x18\x03 \x01(\t\x12\x1d\n\x15receiver_account_type' + b'\x18\x04 \x01(\t\x12\x0e\n\x06amount\x18\x05 \x01(\x01\x12\x0e\n\x06reason\x18\x06 \x01(\t' + b'"8\n\x13TransactionResponse\x12\x10\n\x08approved\x18\x01 \x01(\x08\x12\x0f\n\x07message' + b'\x18\x02 \x01(\t"3\n\x19GetALLTransactionsRequest\x12\x16\n\x0eaccount_number\x18\x01 \x01(\t' + b'"\x7f\n\x0bTransaction\x12\x16\n\x0eaccount_number\x18\x01 \x01(\t\x12\x0e\n\x06amount\x18\x02' + b' \x01(\x01\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x12\n\ntime_stamp\x18\x04 \x01(\t\x12\x0c' + b'\n\x04type\x18\x05 \x01(\t\x12\x16\n\x0etransaction_id\x18\x06 \x01(\t"@' + b'\n\x1aGetALLTransactionsResponse\x12"\n\x0ctransactions\x18\x01 \x03(\x0b\x32\x0c.Transaction' + b'"\\\n\x0cZelleRequest\x12\x14\n\x0csender_email\x18\x01 \x01(\t\x12\x16\n\x0ereceiver_email' + b'\x18\x02 \x01(\t\x12\x0e\n\x06amount\x18\x03 \x01(\x01\x12\x0e\n\x06reason\x18\x04 \x01(\t' + b'"0\n\x16TransactionByIDRequest\x12\x16\n\x0etransaction_id\x18\x01 \x01(\t' + b'2\x8a\x02\n\x12TransactionService\x12\x36\n\tsendMoney\x12\x13.TransactionRequest' + b'\x1a\x14.TransactionResponse\x12Q\n\x16getTransactionsHistory\x12\x1a.GetALLTransactionsRequest' + b'\x1a\x1b.GetALLTransactionsResponse\x12,\n\x05Zelle\x12\r.ZelleRequest\x1a\x14.TransactionResponse' + b'\x12;\n\x12getTransactionByID\x12\x17.TransactionByIDRequest\x1a\x0c.Transactionb\x06proto3' +) _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'transaction_pb2', globals()) -if _descriptor._USE_C_DESCRIPTORS == False: - DESCRIPTOR._options = None - _TRANSACTIONREQUEST._serialized_start=22 - _TRANSACTIONREQUEST._serialized_end=198 - _TRANSACTIONRESPONSE._serialized_start=200 - _TRANSACTIONRESPONSE._serialized_end=256 - _GETALLTRANSACTIONSREQUEST._serialized_start=258 - _GETALLTRANSACTIONSREQUEST._serialized_end=309 - _TRANSACTION._serialized_start=311 - _TRANSACTION._serialized_end=438 - _GETALLTRANSACTIONSRESPONSE._serialized_start=440 - _GETALLTRANSACTIONSRESPONSE._serialized_end=504 - _ZELLEREQUEST._serialized_start=506 - _ZELLEREQUEST._serialized_end=598 - _TRANSACTIONBYIDREQUEST._serialized_start=600 - _TRANSACTIONBYIDREQUEST._serialized_end=648 - _TRANSACTIONSERVICE._serialized_start=651 - _TRANSACTIONSERVICE._serialized_end=917 -# @@protoc_insertion_point(module_scope) +if _descriptor._USE_C_DESCRIPTORS is False: + DESCRIPTOR._options = None + + DESCRIPTOR._options = None + _TRANSACTIONREQUEST._serialized_start=22 + _TRANSACTIONREQUEST._serialized_end=198 + _TRANSACTIONRESPONSE._serialized_start=200 + _TRANSACTIONRESPONSE._serialized_end=256 + _GETALLTRANSACTIONSREQUEST._serialized_start=258 + _GETALLTRANSACTIONSREQUEST._serialized_end=309 + _TRANSACTION._serialized_start=311 + _TRANSACTION._serialized_end=438 + _GETALLTRANSACTIONSRESPONSE._serialized_start=440 + _GETALLTRANSACTIONSRESPONSE._serialized_end=504 + _ZELLEREQUEST._serialized_start=506 + _ZELLEREQUEST._serialized_end=598 + _TRANSACTIONBYIDREQUEST._serialized_start=600 + _TRANSACTIONBYIDREQUEST._serialized_end=648 + _TRANSACTIONSERVICE._serialized_start=651 + _TRANSACTIONSERVICE._serialized_end=917 + # @@protoc_insertion_point(module_scope) diff --git a/dashboard/transaction_pb2_grpc.py b/dashboard/transaction_pb2_grpc.py index 0fedc4d..2037e5f 100644 --- a/dashboard/transaction_pb2_grpc.py +++ b/dashboard/transaction_pb2_grpc.py @@ -1,169 +1,263 @@ -# Copyright (c) 2023 Cisco Systems, Inc. and its affiliates All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -"""Client and server classes corresponding to protobuf-defined services.""" +"""Copyright (c) 2023 Cisco Systems, Inc. and its affiliates All rights reserved. + Use of this source code is governed by a BSD-style + license that can be found in the LICENSE file. + Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +Client and server classes corresponding to protobuf-defined services. +Client and server classes corresponding to protobuf-defined services.""" import grpc +import transaction_pb2 -import transaction_pb2 as transaction__pb2 - +class TransactionServiceStub: + """Stub for the TransactionService. -class TransactionServiceStub(object): - """Missing associated documentation comment in .proto file.""" + This class provides methods to call the RPCs provided by the TransactionService. + """ def __init__(self, channel): - """Constructor. + """Construct a stub for the TransactionService. Args: channel: A grpc.Channel. """ - self.sendMoney = channel.unary_unary( - '/TransactionService/sendMoney', - request_serializer=transaction__pb2.TransactionRequest.SerializeToString, - response_deserializer=transaction__pb2.TransactionResponse.FromString, - ) - self.getTransactionsHistory = channel.unary_unary( - '/TransactionService/getTransactionsHistory', - request_serializer=transaction__pb2.GetALLTransactionsRequest.SerializeToString, - response_deserializer=transaction__pb2.GetALLTransactionsResponse.FromString, - ) - self.Zelle = channel.unary_unary( - '/TransactionService/Zelle', - request_serializer=transaction__pb2.ZelleRequest.SerializeToString, - response_deserializer=transaction__pb2.TransactionResponse.FromString, - ) - self.getTransactionByID = channel.unary_unary( - '/TransactionService/getTransactionByID', - request_serializer=transaction__pb2.TransactionByIDRequest.SerializeToString, - response_deserializer=transaction__pb2.Transaction.FromString, - ) - - -class TransactionServiceServicer(object): - """Missing associated documentation comment in .proto file.""" - - def sendMoney(self, request, context): - """Missing associated documentation comment in .proto file.""" + self.send_money = channel.unary_unary( + '/TransactionService/sendMoney', + request_serializer=transaction_pb2.TransactionRequest.SerializeToString, + response_deserializer=transaction_pb2.TransactionResponse.FromString, + ) + self.get_transactions_history = channel.unary_unary( + '/TransactionService/getTransactionsHistory', + request_serializer=transaction_pb2.GetALLTransactionsRequest.SerializeToString, + response_deserializer=transaction_pb2.GetALLTransactionsResponse.FromString, + ) + self.zelle = channel.unary_unary( + '/TransactionService/Zelle', + request_serializer=transaction_pb2.ZelleRequest.SerializeToString, + response_deserializer=transaction_pb2.TransactionResponse.FromString, + ) + self.get_transaction_by_id = channel.unary_unary( + '/TransactionService/getTransactionByID', + request_serializer=transaction_pb2.TransactionByIDRequest.SerializeToString, + response_deserializer=transaction_pb2.Transaction.FromString, + ) + + +class TransactionServiceServicer: + """Servicer for the TransactionService. + + This class implements the service methods defined in the TransactionService. + """ + + def send_money(self, request, context): + """Send money to a specified account. + + This method is not yet implemented. + + Args: + request: The request containing transaction details. + context: The context of the transaction. + + Raises: + NotImplementedError: Indicates method is not implemented. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') - def getTransactionsHistory(self, request, context): - """Missing associated documentation comment in .proto file.""" + def get_transactions_history(self, request, context): + """Get the transaction history of an account. + + This method is not yet implemented. + + Args: + request: The request for transaction history. + context: The context of the transaction. + + Raises: + NotImplementedError: Indicates method is not implemented. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') - def Zelle(self, request, context): - """Missing associated documentation comment in .proto file.""" + def zelle(self, request, context): + """Perform a Zelle transaction. + + This method is not yet implemented. + + Args: + request: The request containing Zelle transaction details. + context: The context of the transaction. + + Raises: + NotImplementedError: Indicates method is not implemented. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') - def getTransactionByID(self, request, context): - """Missing associated documentation comment in .proto file.""" + def get_transaction_by_id(self, request, context): + """Get a transaction by its ID. + + This method is not yet implemented. + + Args: + request: The request containing the transaction ID. + context: The context of the transaction. + + Raises: + NotImplementedError: Indicates method is not implemented. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') -def add_TransactionServiceServicer_to_server(servicer, server): +def add_transaction_service_servicer_to_server(servicer, server): + """Register the TransactionServiceServicer to a gRPC server. + + Args: + servicer: The servicer instance to register. + server: The gRPC server. + """ rpc_method_handlers = { - 'sendMoney': grpc.unary_unary_rpc_method_handler( - servicer.sendMoney, - request_deserializer=transaction__pb2.TransactionRequest.FromString, - response_serializer=transaction__pb2.TransactionResponse.SerializeToString, - ), - 'getTransactionsHistory': grpc.unary_unary_rpc_method_handler( - servicer.getTransactionsHistory, - request_deserializer=transaction__pb2.GetALLTransactionsRequest.FromString, - response_serializer=transaction__pb2.GetALLTransactionsResponse.SerializeToString, - ), - 'Zelle': grpc.unary_unary_rpc_method_handler( - servicer.Zelle, - request_deserializer=transaction__pb2.ZelleRequest.FromString, - response_serializer=transaction__pb2.TransactionResponse.SerializeToString, - ), - 'getTransactionByID': grpc.unary_unary_rpc_method_handler( - servicer.getTransactionByID, - request_deserializer=transaction__pb2.TransactionByIDRequest.FromString, - response_serializer=transaction__pb2.Transaction.SerializeToString, - ), + 'sendMoney': grpc.unary_unary_rpc_method_handler( + servicer.send_money, + request_deserializer=transaction_pb2.TransactionRequest.FromString, + response_serializer=transaction_pb2.TransactionResponse.SerializeToString, + ), + 'getTransactionsHistory': grpc.unary_unary_rpc_method_handler( + servicer.get_transactions_history, + request_deserializer=transaction_pb2.GetALLTransactionsRequest.FromString, + response_serializer=transaction_pb2.GetALLTransactionsResponse.SerializeToString, + ), + 'Zelle': grpc.unary_unary_rpc_method_handler( + servicer.zelle, + request_deserializer=transaction_pb2.ZelleRequest.FromString, + response_serializer=transaction_pb2.TransactionResponse.SerializeToString, + ), + 'getTransactionByID': grpc.unary_unary_rpc_method_handler( + servicer.get_transaction_by_id, + request_deserializer=transaction_pb2.TransactionByIDRequest.FromString, + response_serializer=transaction_pb2.Transaction.SerializeToString, + ), } generic_handler = grpc.method_handlers_generic_handler( - 'TransactionService', rpc_method_handlers) + 'TransactionService', rpc_method_handlers) server.add_generic_rpc_handlers((generic_handler,)) - # This class is part of an EXPERIMENTAL API. -class TransactionService(object): - """Missing associated documentation comment in .proto file.""" + +class TransactionService: + """Provides static methods for client-side gRPC calls to TransactionService.""" @staticmethod - def sendMoney(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary(request, target, '/TransactionService/sendMoney', - transaction__pb2.TransactionRequest.SerializeToString, - transaction__pb2.TransactionResponse.FromString, + def send_money(request, target, options=(), channel_credentials=None, + call_credentials=None, insecure=False, compression=None, + wait_for_ready=None, timeout=None, metadata=None): + """Send money to a specified account. + + Args: + request: An instance of TransactionRequest. + target: The target server to send this request. + options: Optional gRPC call options. + channel_credentials: Channel credentials for secure connection. + call_credentials: Call credentials for the request. + insecure: If set to True, use an insecure channel. + compression: Compression method. + wait_for_ready: If set to True, wait for the channel to be ready. + timeout: Timeout for the request. + metadata: Metadata for the request. + + Returns: + An instance of TransactionResponse. + """ + return grpc.experimental.unary_unary( + request, target, '/TransactionService/sendMoney', + transaction_pb2.TransactionRequest.SerializeToString, + transaction_pb2.TransactionResponse.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod - def getTransactionsHistory(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary(request, target, '/TransactionService/getTransactionsHistory', - transaction__pb2.GetALLTransactionsRequest.SerializeToString, - transaction__pb2.GetALLTransactionsResponse.FromString, + def get_transactions_history(request, target, options=(), channel_credentials=None, + call_credentials=None, insecure=False, compression=None, + wait_for_ready=None, timeout=None, metadata=None): + """Retrieve the transaction history. + + Args: + request: An instance of GetALLTransactionsRequest. + target: The target server to send this request. + options: Optional gRPC call options. + channel_credentials: Channel credentials for secure connection. + call_credentials: Call credentials for the request. + insecure: If set to True, use an insecure channel. + compression: Compression method. + wait_for_ready: If set to True, wait for the channel to be ready. + timeout: Timeout for the request. + metadata: Metadata for the request. + + Returns: + An instance of GetALLTransactionsResponse. + """ + return grpc.experimental.unary_unary( + request, target, '/TransactionService/getTransactionsHistory', + transaction_pb2.GetALLTransactionsRequest.SerializeToString, + transaction_pb2.GetALLTransactionsResponse.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod - def Zelle(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary(request, target, '/TransactionService/Zelle', - transaction__pb2.ZelleRequest.SerializeToString, - transaction__pb2.TransactionResponse.FromString, + def zelle(request, target, options=(), channel_credentials=None, + call_credentials=None, insecure=False, compression=None, + wait_for_ready=None, timeout=None, metadata=None): + """Perform a Zelle transaction. + + Args: + request: An instance of ZelleRequest. + target: The target server to send this request. + options: Optional gRPC call options. + channel_credentials: Channel credentials for secure connection. + call_credentials: Call credentials for the request. + insecure: If set to True, use an insecure channel. + compression: Compression method. + wait_for_ready: If set to True, wait for the channel to be ready. + timeout: Timeout for the request. + metadata: Metadata for the request. + + Returns: + An instance of TransactionResponse. + """ + return grpc.experimental.unary_unary( + request, target, '/TransactionService/Zelle', + transaction_pb2.ZelleRequest.SerializeToString, + transaction_pb2.TransactionResponse.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod - def getTransactionByID(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary(request, target, '/TransactionService/getTransactionByID', - transaction__pb2.TransactionByIDRequest.SerializeToString, - transaction__pb2.Transaction.FromString, + def get_transaction_by_id(request, target, options=(), channel_credentials=None, + call_credentials=None, insecure=False, compression=None, + wait_for_ready=None, timeout=None, metadata=None): + """Get a transaction by its ID. + + Args: + request: An instance of TransactionByIDRequest. + target: The target server to send this request. + options: Optional gRPC call options. + channel_credentials: Channel credentials for secure connection. + call_credentials: Call credentials for the request. + insecure: If set to True, use an insecure channel. + compression: Compression method. + wait_for_ready: If set to True, wait for the channel to be ready. + timeout: Timeout for the request. + metadata: Metadata for the request. + + Returns: + An instance of Transaction. + """ + return grpc.experimental.unary_unary( + request, target, '/TransactionService/getTransactionByID', + transaction_pb2.TransactionByIDRequest.SerializeToString, + transaction_pb2.Transaction.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata) diff --git a/loan/client_api.py b/loan/client_api.py index f4e7aa7..35ad0a3 100644 --- a/loan/client_api.py +++ b/loan/client_api.py @@ -2,16 +2,27 @@ # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. -import grpc +""" +This module implements a gRPC client for interacting with a Loan Service. +It creates a gRPC channel, uses the LoanServiceStub to send a LoanRequest, +and prints the response from the server. +""" +import grpc from loan_pb2_grpc import LoanServiceStub -from loan_pb2 import LoanRequest +from loan_pb2 import LoanRequest +# Create a gRPC channel to connect to the server channel = grpc.insecure_channel('localhost:50053') + +# Create a stub (client) to communicate with the gRPC service client = LoanServiceStub(channel) -reuest = LoanRequest(account_number="3", amount=10.0) +# Creating a loan request +request = LoanRequest(account_number="3", amount=10.0) -response = client.ProcessLoanRequest(reuest) +# Processing the loan request through the client stub +response = client.ProcessLoanRequest(request) -print(response) \ No newline at end of file +# Print the response from the server +print(response) diff --git a/loan/loan.py b/loan/loan.py index 1f57a89..c7b825e 100644 --- a/loan/loan.py +++ b/loan/loan.py @@ -46,7 +46,7 @@ collection_loans = db["loans"] class LoanGeneric: - def ProcessLoanRequest(self, request_data): + def process_loan_request(self, request_data): name = request_data["name"] email = request_data["email"] account_type = request_data["account_type"] @@ -58,9 +58,9 @@ def ProcessLoanRequest(self, request_data): interest_rate = float(request_data["interest_rate"]) time_period = request_data["time_period"] user_account = self.__getAccount(account_number) - # count = collection_loans.count_documents({"email_id": email, 'account_number': account_number}) - count = collection_accounts.count_documents({"email_id": email, 'account_number': account_number}) + count = collection_accounts.count_documents({"email_id": email, + 'account_number': account_number}) logging.debug(f"user account only based on account number search : {user_account}") logging.debug(f"Count whther the email and account exist or not : {count}") @@ -69,7 +69,6 @@ def ProcessLoanRequest(self, request_data): result = self.__approveLoan(user_account, loan_amount) logging.debug(f"Result {result}") message = "Loan Approved" if result else "Loan Rejected" - # insert loan request into db loan_request = { "name": name, @@ -94,7 +93,7 @@ def ProcessLoanRequest(self, request_data): logging.debug(f"Response: {response}") return response - def getLoanHistory(self, request_data): + def get_loan_history(self, request_data): email = request_data["email"] loans = collection_loans.find({"email": email}) loan_history = [] @@ -119,7 +118,7 @@ def getLoanHistory(self, request_data): return loan_history - def __getAccount(self, account_num): + def __get_account(self, account_num): r = None accounts = collection_accounts.find() for acc in accounts: @@ -129,7 +128,7 @@ def __getAccount(self, account_num): # logging.debug(f"Account {r}") return r - def __approveLoan(self, account, amount): + def __approve_loan(self, account, amount): if amount < 1: return False @@ -148,7 +147,7 @@ def __init__(self) -> None: # enable github copiolot self.loan = LoanGeneric() - def ProcessLoanRequest(self, request, context): + def process_loan_request(self, request, context): name = request.name email = request.email account_type = request.account_type @@ -188,7 +187,7 @@ def getLoanHistory(self, request, context): def process_loan_request(): request_data = request.json logging.debug(f"Request: {request_data}") - response = loan_generic.ProcessLoanRequest(request_data) + response = loan_generic.process_loan_requests(request_data) return jsonify(response) @@ -197,7 +196,7 @@ def get_loan_history(): logging.debug("----------------> Request: /loan/history") d = request.json logging.debug(f"Request: {d}") - response = loan_generic.getLoanHistory({"email": d['email']}) + response = loan_generic.get_loan_history({"email": d['email']}) return jsonify(response) diff --git a/loan/loan_pb2.py b/loan/loan_pb2.py index 92e32f9..b37b081 100644 --- a/loan/loan_pb2.py +++ b/loan/loan_pb2.py @@ -17,23 +17,41 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\nloan.proto\"\xda\x01\n\x0bLoanRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05\x65mail\x18\x02 \x01(\t\x12\x14\n\x0c\x61\x63\x63ount_type\x18\x03 \x01(\t\x12\x16\n\x0e\x61\x63\x63ount_number\x18\x04 \x01(\t\x12\x14\n\x0cgovt_id_type\x18\x05 \x01(\t\x12\x16\n\x0egovt_id_number\x18\x06 \x01(\t\x12\x11\n\tloan_type\x18\x07 \x01(\t\x12\x13\n\x0bloan_amount\x18\x08 \x01(\x01\x12\x15\n\rinterest_rate\x18\t \x01(\x01\x12\x13\n\x0btime_period\x18\n \x01(\t\"1\n\x0cLoanResponse\x12\x10\n\x08\x61pproved\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\"$\n\x13LoansHistoryRequest\x12\r\n\x05\x65mail\x18\x01 \x01(\t\"\xf6\x01\n\x04Loan\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05\x65mail\x18\x02 \x01(\t\x12\x14\n\x0c\x61\x63\x63ount_type\x18\x03 \x01(\t\x12\x16\n\x0e\x61\x63\x63ount_number\x18\x04 \x01(\t\x12\x14\n\x0cgovt_id_type\x18\x05 \x01(\t\x12\x16\n\x0egovt_id_number\x18\x06 \x01(\t\x12\x11\n\tloan_type\x18\x07 \x01(\t\x12\x13\n\x0bloan_amount\x18\x08 \x01(\x01\x12\x15\n\rinterest_rate\x18\t \x01(\x01\x12\x13\n\x0btime_period\x18\n \x01(\t\x12\x0e\n\x06status\x18\x0b \x01(\t\x12\x11\n\ttimestamp\x18\x0c \x01(\t\",\n\x14LoansHistoryResponse\x12\x14\n\x05loans\x18\x01 \x03(\x0b\x32\x05.Loan2\x7f\n\x0bLoanService\x12\x31\n\x12ProcessLoanRequest\x12\x0c.LoanRequest\x1a\r.LoanResponse\x12=\n\x0egetLoanHistory\x12\x14.LoansHistoryRequest\x1a\x15.LoansHistoryResponseb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( + b'\n\nloan.proto\"\xda\x01\n\x0bLoanRequest\x12\x0c\n\x04name\x18\x01 \x01(\t' + b'\x12\r\n\x05\x65mail\x18\x02 \x01(\t\x12\x14\n\x0c\x61\x63\x63ount_type\x18\x03 \x01(\t' + b'\x12\x16\n\x0e\x61\x63\x63ount_number\x18\x04 \x01(\t\x12\x14\n\x0cgovt_id_type\x18\x05 \x01(\t' + b'\x12\x16\n\x0egovt_id_number\x18\x06 \x01(\t\x12\x11\n\tloan_type\x18\x07 \x01(\t' + b'\x12\x13\n\x0bloan_amount\x18\x08 \x01(\x01\x12\x15\n\rinterest_rate\x18\t \x01(\x01' + b'\x12\x13\n\x0btime_period\x18\n \x01(\t\"1\n\x0cLoanResponse\x12\x10\n\x08\x61pproved\x18\x01 \x01(\x08' + b'\x12\x0f\n\x07message\x18\x02 \x01(\t\"$\n\x13LoansHistoryRequest\x12\r\n\x05\x65mail\x18\x01 \x01(\t' + b'\"\xf6\x01\n\x04Loan\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05\x65mail\x18\x02 \x01(\t' + b'\x12\x14\n\x0c\x61\x63\x63ount_type\x18\x03 \x01(\t\x12\x16\n\x0e\x61\x63\x63ount_number\x18\x04 \x01(\t' + b'\x12\x14\n\x0cgovt_id_type\x18\x05 \x01(\t\x12\x16\n\x0egovt_id_number\x18\x06 \x01(\t' + b'\x12\x11\n\tloan_type\x18\x07 \x01(\t\x12\x13\n\x0bloan_amount\x18\x08 \x01(\x01' + b'\x12\x15\n\rinterest_rate\x18\t \x01(\x01\x12\x13\n\x0btime_period\x18\n \x01(\t' + b'\x12\x0e\n\x06status\x18\x0b \x01(\t\x12\x11\n\ttimestamp\x18\x0c \x01(\t' + b'\",\n\x14LoansHistoryResponse\x12\x14\n\x05loans\x18\x01 \x03(\x0b\x32\x05.Loan2\x7f\n\x0bLoanService' + b'\x12\x31\n\x12ProcessLoanRequest\x12\x0c.LoanRequest\x1a\r.LoanResponse' + b'\x12=\n\x0egetLoanHistory\x12\x14.LoansHistoryRequest\x1a\x15.LoansHistoryResponseb\x06proto3' +) + _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'loan_pb2', globals()) -if _descriptor._USE_C_DESCRIPTORS == False: - - DESCRIPTOR._options = None - _LOANREQUEST._serialized_start=15 - _LOANREQUEST._serialized_end=233 - _LOANRESPONSE._serialized_start=235 - _LOANRESPONSE._serialized_end=284 - _LOANSHISTORYREQUEST._serialized_start=286 - _LOANSHISTORYREQUEST._serialized_end=322 - _LOAN._serialized_start=325 - _LOAN._serialized_end=571 - _LOANSHISTORYRESPONSE._serialized_start=573 - _LOANSHISTORYRESPONSE._serialized_end=617 - _LOANSERVICE._serialized_start=619 - _LOANSERVICE._serialized_end=746 +if _descriptor._USE_C_DESCRIPTORS is False: + + DESCRIPTOR._options = None + _LOANREQUEST._serialized_start=15 + _LOANREQUEST._serialized_end=233 + _LOANRESPONSE._serialized_start=235 + _LOANRESPONSE._serialized_end=284 + _LOANSHISTORYREQUEST._serialized_start=286 + _LOANSHISTORYREQUEST._serialized_end=322 + _LOAN._serialized_start=325 + _LOAN._serialized_end=571 + _LOANSHISTORYRESPONSE._serialized_start=573 + _LOANSHISTORYRESPONSE._serialized_end=617 + _LOANSERVICE._serialized_start=619 + _LOANSERVICE._serialized_end=746 # @@protoc_insertion_point(module_scope) diff --git a/loan/loan_pb2_grpc.py b/loan/loan_pb2_grpc.py index 4a73bc3..734f2af 100644 --- a/loan/loan_pb2_grpc.py +++ b/loan/loan_pb2_grpc.py @@ -6,98 +6,167 @@ """Client and server classes corresponding to protobuf-defined services.""" import grpc -import loan_pb2 as loan__pb2 +import loan_pb2 +class LoanServiceStub: + """ + Stub for the LoanService gRPC service. -class LoanServiceStub(object): - """Missing associated documentation comment in .proto file.""" + This class provides methods to interact with the gRPC service. + """ def __init__(self, channel): - """Constructor. + """ + Initialize the LoanServiceStub. + + Args: + channel (grpc.Channel): A gRPC channel to the server. + """ + self.process_loan_request = channel.unary_unary( + '/LoanService/ProcessLoanRequest', + request_serializer=loan_pb2.LoanRequest.SerializeToString, + response_deserializer=loan_pb2.LoanResponse.FromString, + ) + self.get_loan_history = channel.unary_unary( + '/LoanService/getLoanHistory', + request_serializer=loan_pb2.LoansHistoryRequest.SerializeToString, + response_deserializer=loan_pb2.LoansHistoryResponse.FromString, + ) + + +class LoanServiceServicer: + """ + Servicer for the LoanService gRPC service. + + This class handles incoming requests and provides responses. + """ + + def process_loan_request(self, request, context): + """ + Process a loan request. Args: - channel: A grpc.Channel. + request: The incoming loan request. + context: The gRPC context. + + Raises: + NotImplementedError: Indicates the method is not implemented. """ - self.ProcessLoanRequest = channel.unary_unary( - '/LoanService/ProcessLoanRequest', - request_serializer=loan__pb2.LoanRequest.SerializeToString, - response_deserializer=loan__pb2.LoanResponse.FromString, - ) - self.getLoanHistory = channel.unary_unary( - '/LoanService/getLoanHistory', - request_serializer=loan__pb2.LoansHistoryRequest.SerializeToString, - response_deserializer=loan__pb2.LoansHistoryResponse.FromString, - ) - - -class LoanServiceServicer(object): - """Missing associated documentation comment in .proto file.""" - - def ProcessLoanRequest(self, request, context): - """Missing associated documentation comment in .proto file.""" context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') - def getLoanHistory(self, request, context): - """Missing associated documentation comment in .proto file.""" + def get_loan_history(self, request, context): + """ + Retrieve loan history. + + Args: + request: The request for loan history. + context: The gRPC context. + + Raises: + NotImplementedError: Indicates the method is not implemented. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') -def add_LoanServiceServicer_to_server(servicer, server): +def add_loan_service_servicer_to_server(servicer, server): + """ + Register the LoanService servicer to a gRPC server. + + Args: + servicer (LoanServiceServicer): The servicer to register. + server (grpc.Server): The gRPC server. + """ rpc_method_handlers = { - 'ProcessLoanRequest': grpc.unary_unary_rpc_method_handler( - servicer.ProcessLoanRequest, - request_deserializer=loan__pb2.LoanRequest.FromString, - response_serializer=loan__pb2.LoanResponse.SerializeToString, - ), - 'getLoanHistory': grpc.unary_unary_rpc_method_handler( - servicer.getLoanHistory, - request_deserializer=loan__pb2.LoansHistoryRequest.FromString, - response_serializer=loan__pb2.LoansHistoryResponse.SerializeToString, - ), + 'ProcessLoanRequest': grpc.unary_unary_rpc_method_handler( + servicer.process_loan_request, + request_deserializer=loan_pb2.LoanRequest.FromString, + response_serializer=loan_pb2.LoanResponse.SerializeToString, + ), + 'getLoanHistory': grpc.unary_unary_rpc_method_handler( + servicer.get_loan_history, + request_deserializer=loan_pb2.LoansHistoryRequest.FromString, + response_serializer=loan_pb2.LoansHistoryResponse.SerializeToString, + ), } generic_handler = grpc.method_handlers_generic_handler( - 'LoanService', rpc_method_handlers) + 'LoanService', rpc_method_handlers) server.add_generic_rpc_handlers((generic_handler,)) + + # This class is part of an EXPERIMENTAL API. -class LoanService(object): - """Missing associated documentation comment in .proto file.""" +import grpc +from typing import Tuple, Any + +# Assuming loan_pb2 is a module containing the necessary gRPC message classes +import loan_pb2 + + +class LoanService: + """ + This class handles loan-related services, including processing loan requests + and fetching loan history. + """ @staticmethod - def ProcessLoanRequest(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary(request, target, '/LoanService/ProcessLoanRequest', - loan__pb2.LoanRequest.SerializeToString, - loan__pb2.LoanResponse.FromString, + def process_loan_request(request: loan_pb2.LoanRequest, target: str, + options: Tuple = (), channel_credentials=None, + call_credentials=None, insecure: bool = False, + compression=None, wait_for_ready=None, + timeout: int = None, metadata: Tuple = None) -> Any: + """ + Processes a loan request. + + :param request: The loan request to be processed. + :param target: The target server. + :param options: Tuple of options. + :param channel_credentials: Channel credentials. + :param call_credentials: Call credentials. + :param insecure: Boolean flag for insecurity. + :param compression: Compression method. + :param wait_for_ready: Waiting parameter. + :param timeout: Timeout for the request. + :param metadata: Additional metadata. + :return: gRPC unary-unary call result. + """ + return grpc.experimental.unary_unary( + request, target, '/LoanService/ProcessLoanRequest', + loan_pb2.LoanRequest.SerializeToString, + loan_pb2.LoanResponse.FromString, options, channel_credentials, - insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + insecure, call_credentials, compression, wait_for_ready, timeout, metadata + ) @staticmethod - def getLoanHistory(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary(request, target, '/LoanService/getLoanHistory', - loan__pb2.LoansHistoryRequest.SerializeToString, - loan__pb2.LoansHistoryResponse.FromString, + def get_loan_history(request: loan_pb2.LoansHistoryRequest, target: str, + options: Tuple = (), channel_credentials=None, + call_credentials=None, insecure: bool = False, + compression=None, wait_for_ready=None, + timeout: int = None, metadata: Tuple = None) -> Any: + """ + Retrieves loan history based on the given request. + + :param request: The request for loan history. + :param target: The target server. + :param options: Tuple of options. + :param channel_credentials: Channel credentials. + :param call_credentials: Call credentials. + :param insecure: Boolean flag for insecurity. + :param compression: Compression method. + :param wait_for_ready: Waiting parameter. + :param timeout: Timeout for the request. + :param metadata: Additional metadata. + :return: gRPC unary-unary call result. + """ + return grpc.experimental.unary_unary( + request, target, '/LoanService/GetLoanHistory', + loan_pb2.LoansHistoryRequest.SerializeToString, + loan_pb2.LoansHistoryResponse.FromString, options, channel_credentials, - insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + insecure, call_credentials, compression, wait_for_ready, timeout, metadata + ) diff --git a/martian-bank-demo b/martian-bank-demo new file mode 160000 index 0000000..85bd240 --- /dev/null +++ b/martian-bank-demo @@ -0,0 +1 @@ +Subproject commit 85bd2403c77e84cfda5014b2174279d7034c3f14 diff --git a/transactions/api_client.py b/transactions/api_client.py index 9233ecd..0b2a0c6 100644 --- a/transactions/api_client.py +++ b/transactions/api_client.py @@ -1,16 +1,18 @@ # Copyright (c) 2023 Cisco Systems, Inc. and its affiliates All rights reserved. -# Use of this source code is governed by a BSD-style +# Use of this source code is governed by a BSD-style. # license that can be found in the LICENSE file. - +""" This module provides a gRPC client for sending transaction requests to a transaction service. +It demonstrates the creation of a gRPC channel, the instantiation of a service stub, and +the execution of a method provided by the transaction service. Specifically, it sends a +request to transfer funds between accounts using the SendMoney method of the TransactionService. +The module is designed to interact with a gRPC server running on localhost at port 50052. +""" import grpc - from transaction_pb2_grpc import TransactionServiceStub from transaction_pb2 import TransactionRequest, TransactionResponse channel = grpc.insecure_channel('localhost:50052') client = TransactionServiceStub(channel) - -request = TransactionRequest(sender_account_number="3", receiver_account_number="2", amount=10.0) - +request =TransactionRequest(sender_account_number="3", receiver_account_number="2", amount=10.0) response = client.SendMoney (request) -print(response) \ No newline at end of file +print(response)