瀏覽代碼

Initial Commit

master
mb 1 年之前
當前提交
7449337c3a
共有 20 個檔案被更改,包括 582 行新增0 行删除
  1. +7
    -0
      .gitignore
  2. +8
    -0
      .idea/.gitignore
  3. +8
    -0
      .idea/invoice_sync.iml
  4. +8
    -0
      .idea/modules.xml
  5. +19
    -0
      .idea/php.xml
  6. +6
    -0
      .idea/vcs.xml
  7. +1
    -0
      README.md
  8. +3
    -0
      invoice_sync/__init__.py
  9. +0
    -0
      invoice_sync/config/__init__.py
  10. +221
    -0
      invoice_sync/hooks.py
  11. +0
    -0
      invoice_sync/invoice_sync/__init__.py
  12. +253
    -0
      invoice_sync/invoice_sync/invoice.py
  13. +1
    -0
      invoice_sync/modules.txt
  14. +6
    -0
      invoice_sync/patches.txt
  15. +0
    -0
      invoice_sync/public/.gitkeep
  16. +0
    -0
      invoice_sync/templates/__init__.py
  17. +0
    -0
      invoice_sync/templates/pages/__init__.py
  18. +0
    -0
      invoice_sync/www/__init__.py
  19. +21
    -0
      license.txt
  20. +20
    -0
      pyproject.toml

+ 7
- 0
.gitignore 查看文件

@@ -0,0 +1,7 @@
.DS_Store
*.pyc
*.egg-info
*.swp
tags
node_modules
__pycache__

+ 8
- 0
.idea/.gitignore 查看文件

@@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

+ 8
- 0
.idea/invoice_sync.iml 查看文件

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

+ 8
- 0
.idea/modules.xml 查看文件

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/invoice_sync.iml" filepath="$PROJECT_DIR$/.idea/invoice_sync.iml" />
</modules>
</component>
</project>

+ 19
- 0
.idea/php.xml 查看文件

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MessDetectorOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PHPCSFixerOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PHPCodeSnifferOptionsConfiguration">
<option name="highlightLevel" value="WARNING" />
<option name="transferred" value="true" />
</component>
<component name="PhpStanOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PsalmOptionsConfiguration">
<option name="transferred" value="true" />
</component>
</project>

+ 6
- 0
.idea/vcs.xml 查看文件

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

+ 1
- 0
README.md 查看文件

@@ -0,0 +1 @@
Invoice Sync

+ 3
- 0
invoice_sync/__init__.py 查看文件

@@ -0,0 +1,3 @@

__version__ = '0.0.1'


+ 0
- 0
invoice_sync/config/__init__.py 查看文件


+ 221
- 0
invoice_sync/hooks.py 查看文件

@@ -0,0 +1,221 @@
app_name = "invoice_sync"
app_title = "Invoice Sync"
app_publisher = "SolutionERP"
app_description = "Syncing invoice with mobile app"
app_email = "support@solutionerp.com"
app_license = "mit"
# required_apps = []

# Includes in <head>
# ------------------

# include js, css files in header of desk.html
# app_include_css = "/assets/invoice_sync/css/invoice_sync.css"
# app_include_js = "/assets/invoice_sync/js/invoice_sync.js"

# include js, css files in header of web template
# web_include_css = "/assets/invoice_sync/css/invoice_sync.css"
# web_include_js = "/assets/invoice_sync/js/invoice_sync.js"

# include custom scss in every website theme (without file extension ".scss")
# website_theme_scss = "invoice_sync/public/scss/website"

# include js, css files in header of web form
# webform_include_js = {"doctype": "public/js/doctype.js"}
# webform_include_css = {"doctype": "public/css/doctype.css"}

# include js in page
# page_js = {"page" : "public/js/file.js"}

# include js in doctype views
# doctype_js = {"doctype" : "public/js/doctype.js"}
# doctype_list_js = {"doctype" : "public/js/doctype_list.js"}
# doctype_tree_js = {"doctype" : "public/js/doctype_tree.js"}
# doctype_calendar_js = {"doctype" : "public/js/doctype_calendar.js"}

# Svg Icons
# ------------------
# include app icons in desk
# app_include_icons = "invoice_sync/public/icons.svg"

# Home Pages
# ----------

# application home page (will override Website Settings)
# home_page = "login"

# website user home page (by Role)
# role_home_page = {
# "Role": "home_page"
# }

# Generators
# ----------

# automatically create page for each record of this doctype
# website_generators = ["Web Page"]

# Jinja
# ----------

# add methods and filters to jinja environment
# jinja = {
# "methods": "invoice_sync.utils.jinja_methods",
# "filters": "invoice_sync.utils.jinja_filters"
# }

# Installation
# ------------

# before_install = "invoice_sync.install.before_install"
# after_install = "invoice_sync.install.after_install"

# Uninstallation
# ------------

# before_uninstall = "invoice_sync.uninstall.before_uninstall"
# after_uninstall = "invoice_sync.uninstall.after_uninstall"

# Integration Setup
# ------------------
# To set up dependencies/integrations with other apps
# Name of the app being installed is passed as an argument

# before_app_install = "invoice_sync.utils.before_app_install"
# after_app_install = "invoice_sync.utils.after_app_install"

# Integration Cleanup
# -------------------
# To clean up dependencies/integrations with other apps
# Name of the app being uninstalled is passed as an argument

# before_app_uninstall = "invoice_sync.utils.before_app_uninstall"
# after_app_uninstall = "invoice_sync.utils.after_app_uninstall"

# Desk Notifications
# ------------------
# See xhiveframework.core.notifications.get_notification_config

# notification_config = "invoice_sync.notifications.get_notification_config"

# Permissions
# -----------
# Permissions evaluated in scripted ways

# permission_query_conditions = {
# "Event": "xhiveframework.desk.doctype.event.event.get_permission_query_conditions",
# }
#
# has_permission = {
# "Event": "xhiveframework.desk.doctype.event.event.has_permission",
# }

# DocType Class
# ---------------
# Override standard doctype classes

# override_doctype_class = {
# "ToDo": "custom_app.overrides.CustomToDo"
# }

# Document Events
# ---------------
# Hook on document methods and events

# doc_events = {
# "*": {
# "on_update": "method",
# "on_cancel": "method",
# "on_trash": "method"
# }
# }

# Scheduled Tasks
# ---------------

# scheduler_events = {
# "all": [
# "invoice_sync.tasks.all"
# ],
# "daily": [
# "invoice_sync.tasks.daily"
# ],
# "hourly": [
# "invoice_sync.tasks.hourly"
# ],
# "weekly": [
# "invoice_sync.tasks.weekly"
# ],
# "monthly": [
# "invoice_sync.tasks.monthly"
# ],
# }

# Testing
# -------

# before_tests = "invoice_sync.install.before_tests"

# Overriding Methods
# ------------------------------
#
# override_whitelisted_methods = {
# "xhiveframework.desk.doctype.event.event.get_events": "invoice_sync.event.get_events"
# }
#
# each overriding function accepts a `data` argument;
# generated from the base implementation of the doctype dashboard,
# along with any modifications made in other Xhive apps
# override_doctype_dashboards = {
# "Task": "invoice_sync.task.get_dashboard_data"
# }

# exempt linked doctypes from being automatically cancelled
#
# auto_cancel_exempted_doctypes = ["Auto Repeat"]

# Ignore links to specified DocTypes when deleting documents
# -----------------------------------------------------------

# ignore_links_on_delete = ["Communication", "ToDo"]

# Request Events
# ----------------
# before_request = ["invoice_sync.utils.before_request"]
# after_request = ["invoice_sync.utils.after_request"]

# Job Events
# ----------
# before_job = ["invoice_sync.utils.before_job"]
# after_job = ["invoice_sync.utils.after_job"]

# User Data Protection
# --------------------

# user_data_fields = [
# {
# "doctype": "{doctype_1}",
# "filter_by": "{filter_by}",
# "redact_fields": ["{field_1}", "{field_2}"],
# "partial": 1,
# },
# {
# "doctype": "{doctype_2}",
# "filter_by": "{filter_by}",
# "partial": 1,
# },
# {
# "doctype": "{doctype_3}",
# "strict": False,
# },
# {
# "doctype": "{doctype_4}"
# }
# ]

# Authentication and authorization
# --------------------------------

# auth_hooks = [
# "invoice_sync.auth.validate"
# ]

+ 0
- 0
invoice_sync/invoice_sync/__init__.py 查看文件


+ 253
- 0
invoice_sync/invoice_sync/invoice.py 查看文件

@@ -0,0 +1,253 @@
import requests
import json
import xhiveframework
import json
import urllib.parse;
import base64
from werkzeug.wrappers import Response


@xhiveframework.whitelist(allow_guest=True)
def generate_token_secure( api_key, api_secret, app_key):


try:
try:
app_key = base64.b64decode(app_key).decode("utf-8")
except Exception as e:
return Response(json.dumps({"message": "Security Parameters are not valid" , "user_count": 0}), status=401, mimetype='application/json')
clientID, clientSecret, clientUser = xhiveframework.db.get_value('OAuth Client', {'app_name': app_key}, ['client_id', 'client_secret','user'])

if clientID is None:
# return app_key
return Response(json.dumps({"message": "Security Parameters are not valid" , "user_count": 0}), status=401, mimetype='application/json')

client_id = clientID # Replace with your OAuth client ID
client_secret = clientSecret # Replace with your OAuth client secret
url = xhiveframework.local.conf.host_name + "/api/method/xhiveframework.integrations.oauth2.get_token"
payload = {
"username": api_key,
"password": api_secret,
"grant_type": "password",
"client_id": client_id,
"client_secret": client_secret,

}
files = []
headers = {"Content-Type": "application/json"}
response = requests.request("POST", url, data=payload, files=files)
if response.status_code == 200:
result_data = json.loads(response.text)
return Response(json.dumps({"data":result_data}), status=200, mimetype='application/json')


else:

xhiveframework.local.response.http_status_code = 401
return json.loads(response.text)


except Exception as e:


return Response(json.dumps({"message": e , "user_count": 0}), status=500, mimetype='application/json')






@xhiveframework.whitelist(allow_guest=True)
def create_refresh_token(refresh_token):
url = xhiveframework.local.conf.host_name + "/api/method/xhiveframework.integrations.oauth2.get_token"
payload = f'grant_type=refresh_token&refresh_token={refresh_token}'
headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}
files = []

response = requests.post(url, headers=headers, data=payload, files=files)


if response.status_code == 200:
try:

message_json = json.loads(response.text)


new_message = {
"access_token": message_json["access_token"],
"expires_in": message_json["expires_in"],
"token_type": message_json["token_type"],
"scope": message_json["scope"],
"refresh_token": message_json["refresh_token"]
}


return Response(json.dumps({"data": new_message}), status=200, mimetype='application/json')
except json.JSONDecodeError as e:
return Response(json.dumps({"data": f"Error decoding JSON: {e}"}), status=401, mimetype='application/json')
else:

return Response(json.dumps({"data": response.text}), status=401, mimetype='application/json')





@xhiveframework.whitelist()
def customer(customer, customer_type, phone, email,is_supplier=False):
response_content =xhiveframework.session.user
is_supplier = is_supplier.lower() in ['true', '1', 'yes'] if isinstance(is_supplier, str) else bool(is_supplier)

if not is_supplier:

email_result = []


if email is not None:
email_result = xhiveframework.get_all("Customer", fields=["name as id", "customer_name", "customer_type", "mobile_no", "custom_email as email"],
filters={'custom_email': ['like', email]})

if not email_result:
customer_doc = xhiveframework.get_doc({
"doctype": "Customer",
"customer_name": customer,
"customer_type": customer_type,
"mobile_no": phone,
"custom_email": email,

})

customer_doc.insert(ignore_permissions=True)
customer_doc.save()

details = xhiveframework.get_all("Customer", fields=["name as id", "customer_name", "customer_type", "mobile_no", "custom_email as email",],
filters={'name': ['like', customer_doc.name]})

data = {
"message": "Customer created successfully.",
"Details": details,
}


return Response(json.dumps({"data":data}), status=200, mimetype='application/json')


else:
data = {
"message": "Customer already exists",
"Details": email_result
}


return Response(json.dumps({"data":data}), status=200, mimetype='application/json')

else:
suplr_already_exist=xhiveframework.get_all("Supplier", fields=["name as id", "supplier_name", "custom_email as email", "custom_mobileno as phone"],
filters={'name': ['like',customer]})
details={
"message":"Already exists",
"Details":suplr_already_exist
}
if suplr_already_exist:
return Response(json.dumps({"data":details }), status=409, mimetype='application/json')
supplier_doc = xhiveframework.get_doc({
"doctype": "Supplier",
"supplier_name": customer,
"custom_mobileno": phone,
"custom_email": email,
})
supplier_doc.insert(ignore_permissions=True)

supplier_details = xhiveframework.get_all("Supplier", fields=["name as id", "supplier_name", "custom_email as email", "custom_mobileno as phone"],
filters={'name': ['like', supplier_doc.name]})
suplr={
"Details":supplier_details
}
return Response(json.dumps({"data":suplr}), status=200, mimetype='application/json')






@xhiveframework.whitelist()
def create_invoice(customer_id, supplier_id, payment_method, items):
invoice_items = []

for item in items:
item_code = item["item_name"]

item_exists = xhiveframework.get_value("Item", {"name": item_code}, "name")

if not item_exists:
invoice_item = {
"item_name": item_code,
"qty": item.get("quantity", 0),
"rate": item.get("rate", 0),
"uom": item.get("uom", "Nos"),
"income_account": item.get("income_account", "Sales - erp")
}
else:
invoice_item = {
"item_code": item_code,
"qty": item.get("quantity", 0),
"rate": item.get("rate", 0),

}

invoice_items.append(invoice_item)

new_invoice = xhiveframework.get_doc({
"doctype": "Sales Invoice",
"customer": customer_id,
"custom_supplier_id": supplier_id,
"custom_payment_method": payment_method,
"items": invoice_items
})

new_invoice.insert(ignore_permissions=True)
new_invoice.save()
iitem = xhiveframework.get_doc("Sales Invoice", new_invoice.name)

attribute_dict = []
for attribute in iitem.items:
attribute_data = {
"item_name": attribute.item_name,
"item_code": attribute.item_code,
"quantity": attribute.qty,
"rate": attribute.rate,
"uom": attribute.uom,
"income_account": attribute.income_account
}
attribute_dict.append(attribute_data)

customer_info = {
"id": new_invoice.name,
"customer_id": new_invoice.customer,
"customer_name": new_invoice.customer_name,
"supplier_id": new_invoice.custom_supplier_id,
"payment_method": new_invoice.custom_payment_method,
"total_quantity": new_invoice.total_qty,
"total": new_invoice.total,
"grand_total": new_invoice.grand_total,
"items": attribute_dict
}

return Response(json.dumps({"data":customer_info}), status=200, mimetype='application/json')





@xhiveframework.whitelist()
def customer1(customer, phone, email, is_supplier=False, user_id=None):
try:
return "hello"

except xhiveframework.exceptions.PermissionError as e:
return Response(json.dumps({"message": "Permission error"}), status=401, mimetype='application/json')
except Exception as e:
# Handle other exceptions if needed
return Response(json.dumps({"message": str(e)}), status=500, mimetype='application/json')

+ 1
- 0
invoice_sync/modules.txt 查看文件

@@ -0,0 +1 @@
Invoice Sync

+ 6
- 0
invoice_sync/patches.txt 查看文件

@@ -0,0 +1,6 @@
[pre_model_sync]
# Patches added in this section will be executed before doctypes are migrated
# Read docs to understand patches: https://xhiveframework.com/docs/v14/user/en/database-migrations

[post_model_sync]
# Patches added in this section will be executed after doctypes are migrated

+ 0
- 0
invoice_sync/public/.gitkeep 查看文件


+ 0
- 0
invoice_sync/templates/__init__.py 查看文件


+ 0
- 0
invoice_sync/templates/pages/__init__.py 查看文件


+ 0
- 0
invoice_sync/www/__init__.py 查看文件


+ 21
- 0
license.txt 查看文件

@@ -0,0 +1,21 @@
MIT License

Copyright (c) [year] [fullname]

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

+ 20
- 0
pyproject.toml 查看文件

@@ -0,0 +1,20 @@
[project]
name = "invoice_sync"
authors = [
{ name = "SolutionERP", email = "support@solutionerp.com"}
]
description = "Syncing invoice with mobile app"
requires-python = ">=3.10"
readme = "README.md"
dynamic = ["version"]
dependencies = [
# "xhiveframework~=15.0.0" # Installed and managed by bench.
]

[build-system]
requires = ["flit_core >=3.4,<4"]
build-backend = "flit_core.buildapi"

# These dependencies are only installed when developer mode is enabled
[tool.bench.dev-dependencies]
# package_name = "~=1.1.0"

Loading…
取消
儲存