├── requirements.txt
├── lazada_erpnext_connector
├── patches.txt
├── config
│ ├── __init__.py
│ ├── desktop.py
│ └── docs.py
├── www
│ └── __init__.py
├── templates
│ ├── __init__.py
│ └── pages
│ │ └── __init__.py
├── lazada_erpnext_connector
│ ├── __init__.py
│ ├── doctype
│ │ ├── __init__.py
│ │ ├── lazada_defaults
│ │ │ ├── __init__.py
│ │ │ ├── lazada_defaults.js
│ │ │ ├── test_lazada_defaults.py
│ │ │ ├── lazada_defaults.py
│ │ │ └── lazada_defaults.json
│ │ ├── lazada_settings
│ │ │ ├── __init__.py
│ │ │ ├── test_lazada_settings.py
│ │ │ ├── lazada_settings.js
│ │ │ ├── lazada_settings.json
│ │ │ └── lazada_settings.py
│ │ ├── shipment_provider
│ │ │ ├── __init__.py
│ │ │ ├── shipment_provider.js
│ │ │ ├── test_shipment_provider.py
│ │ │ ├── shipment_provider.py
│ │ │ └── shipment_provider.json
│ │ └── lazada_connector_error_log
│ │ │ ├── __init__.py
│ │ │ ├── lazada_connector_error_log.js
│ │ │ ├── test_lazada_connector_error_log.py
│ │ │ ├── lazada_connector_error_log.py
│ │ │ └── lazada_connector_error_log.json
│ ├── sales_order.py
│ ├── stock_entry.py
│ └── delivery_note.py
├── modules.txt
├── public
│ ├── lazop
│ │ ├── __init__.py
│ │ ├── logs
│ │ │ └── lazopsdk.log.2018-04-22
│ │ └── base.py
│ └── js
│ │ └── lazada.js
├── __init__.py
├── custom_scripts
│ └── sales_order.js
├── hooks.py
├── utils
│ └── lazada_utils.py
└── fixtures
│ └── custom_field.json
├── .gitignore
├── README.md
├── setup.py
├── MANIFEST.in
└── LICENSE
/requirements.txt:
--------------------------------------------------------------------------------
1 | frappe
--------------------------------------------------------------------------------
/lazada_erpnext_connector/patches.txt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/config/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/www/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/templates/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/templates/pages/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/lazada_erpnext_connector/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/modules.txt:
--------------------------------------------------------------------------------
1 | Lazada ERPNext Connector
--------------------------------------------------------------------------------
/lazada_erpnext_connector/lazada_erpnext_connector/doctype/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/public/lazop/__init__.py:
--------------------------------------------------------------------------------
1 | from lazop.base import *
--------------------------------------------------------------------------------
/lazada_erpnext_connector/lazada_erpnext_connector/doctype/lazada_defaults/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/lazada_erpnext_connector/doctype/lazada_settings/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/lazada_erpnext_connector/doctype/shipment_provider/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/lazada_erpnext_connector/doctype/lazada_connector_error_log/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | *.pyc
3 | *.egg-info
4 | *.swp
5 | tags
6 | lazada_erpnext_connector/docs/current
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Lazada ERPNext Connector
2 |
3 | Lazada Ecommerce Platform Integration with ERPNext
4 |
5 | #### License
6 |
7 | MIT
8 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | __version__ = '0.0.1'
5 |
6 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/lazada_erpnext_connector/doctype/lazada_defaults/lazada_defaults.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Raaj Tailor and contributors
2 | // For license information, please see license.txt
3 |
4 | frappe.ui.form.on('Lazada Defaults', {
5 | // refresh: function(frm) {
6 |
7 | // }
8 | });
9 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/lazada_erpnext_connector/doctype/shipment_provider/shipment_provider.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Raaj Tailor and contributors
2 | // For license information, please see license.txt
3 |
4 | frappe.ui.form.on('Shipment Provider', {
5 | // refresh: function(frm) {
6 |
7 | // }
8 | });
9 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/lazada_erpnext_connector/doctype/lazada_connector_error_log/lazada_connector_error_log.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Raaj Tailor and contributors
2 | // For license information, please see license.txt
3 |
4 | frappe.ui.form.on('Lazada Connector Error Log', {
5 | // refresh: function(frm) {
6 |
7 | // }
8 | });
9 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/lazada_erpnext_connector/doctype/lazada_defaults/test_lazada_defaults.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Copyright (c) 2020, Raaj Tailor and Contributors
3 | # See license.txt
4 | from __future__ import unicode_literals
5 |
6 | # import frappe
7 | import unittest
8 |
9 | class TestLazadaDefaults(unittest.TestCase):
10 | pass
11 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/lazada_erpnext_connector/doctype/lazada_settings/test_lazada_settings.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Copyright (c) 2020, Raaj Tailor and Contributors
3 | # See license.txt
4 | from __future__ import unicode_literals
5 |
6 | # import frappe
7 | import unittest
8 |
9 | class TestLazadaSettings(unittest.TestCase):
10 | pass
11 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/lazada_erpnext_connector/doctype/shipment_provider/test_shipment_provider.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Copyright (c) 2020, Raaj Tailor and Contributors
3 | # See license.txt
4 | from __future__ import unicode_literals
5 |
6 | # import frappe
7 | import unittest
8 |
9 | class TestShipmentProvider(unittest.TestCase):
10 | pass
11 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/lazada_erpnext_connector/doctype/lazada_connector_error_log/test_lazada_connector_error_log.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Copyright (c) 2020, Raaj Tailor and Contributors
3 | # See license.txt
4 | from __future__ import unicode_literals
5 |
6 | # import frappe
7 | import unittest
8 |
9 | class TestLazadaConnectorErrorLog(unittest.TestCase):
10 | pass
11 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/lazada_erpnext_connector/doctype/lazada_defaults/lazada_defaults.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Copyright (c) 2020, Raaj Tailor and contributors
3 | # For license information, please see license.txt
4 |
5 | from __future__ import unicode_literals
6 | # import frappe
7 | from frappe.model.document import Document
8 |
9 | class LazadaDefaults(Document):
10 | pass
11 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/config/desktop.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 | from frappe import _
4 |
5 | def get_data():
6 | return [
7 | {
8 | "module_name": "Lazada ERPNext Connector",
9 | "color": "grey",
10 | "icon": "octicon octicon-file-directory",
11 | "type": "module",
12 | "label": _("Lazada ERPNext Connector")
13 | }
14 | ]
15 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/lazada_erpnext_connector/doctype/shipment_provider/shipment_provider.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Copyright (c) 2020, Raaj Tailor and contributors
3 | # For license information, please see license.txt
4 |
5 | from __future__ import unicode_literals
6 | # import frappe
7 | from frappe.model.document import Document
8 |
9 | class ShipmentProvider(Document):
10 | pass
11 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/lazada_erpnext_connector/doctype/lazada_connector_error_log/lazada_connector_error_log.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Copyright (c) 2020, Raaj Tailor and contributors
3 | # For license information, please see license.txt
4 |
5 | from __future__ import unicode_literals
6 | # import frappe
7 | from frappe.model.document import Document
8 |
9 | class LazadaConnectorErrorLog(Document):
10 | pass
11 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/config/docs.py:
--------------------------------------------------------------------------------
1 | """
2 | Configuration for docs
3 | """
4 |
5 | # source_link = "https://github.com/[org_name]/lazada_erpnext_connector"
6 | # docs_base_url = "https://[org_name].github.io/lazada_erpnext_connector"
7 | # headline = "App that does everything"
8 | # sub_heading = "Yes, you got that right the first time, everything"
9 |
10 | def get_context(context):
11 | context.brand_html = "Lazada ERPNext Connector"
12 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/custom_scripts/sales_order.js:
--------------------------------------------------------------------------------
1 | frappe.ui.form.on("Sales Order", {
2 | refresh: function(frm) {
3 | if(frm.doc.docstatus===1) {
4 | cur_frm.add_custom_button(__('Get ewaybill'), function(){
5 | console.log("here")
6 | });
7 | cur_frm.add_custom_button(__('Get Transaction Details'), function(){
8 | frappe.call({
9 | "method":"",
10 |
11 | })
12 | });
13 | }
14 | }
15 | })
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from setuptools import setup, find_packages
3 |
4 | with open('requirements.txt') as f:
5 | install_requires = f.read().strip().split('\n')
6 |
7 | # get version from __version__ variable in lazada_erpnext_connector/__init__.py
8 | from lazada_erpnext_connector import __version__ as version
9 |
10 | setup(
11 | name='lazada_erpnext_connector',
12 | version=version,
13 | description='Lazada Ecommerce Platform Integration witH E',
14 | author='Raaj Tailor',
15 | author_email='tailorraj111@gmail.com',
16 | packages=find_packages(),
17 | zip_safe=False,
18 | include_package_data=True,
19 | install_requires=install_requires
20 | )
21 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include MANIFEST.in
2 | include requirements.txt
3 | include *.json
4 | include *.md
5 | include *.py
6 | include *.txt
7 | recursive-include lazada_erpnext_connector *.css
8 | recursive-include lazada_erpnext_connector *.csv
9 | recursive-include lazada_erpnext_connector *.html
10 | recursive-include lazada_erpnext_connector *.ico
11 | recursive-include lazada_erpnext_connector *.js
12 | recursive-include lazada_erpnext_connector *.json
13 | recursive-include lazada_erpnext_connector *.md
14 | recursive-include lazada_erpnext_connector *.png
15 | recursive-include lazada_erpnext_connector *.py
16 | recursive-include lazada_erpnext_connector *.svg
17 | recursive-include lazada_erpnext_connector *.txt
18 | recursive-exclude lazada_erpnext_connector *.pyc
--------------------------------------------------------------------------------
/lazada_erpnext_connector/public/lazop/logs/lazopsdk.log.2018-04-22:
--------------------------------------------------------------------------------
1 | 2018-04-22 15:53:49,044 - lazop.base - ERROR - 192.168.31.103^_^Darwin-17.5.0-x86_64-i386-64bit^_^https://auth.lazada.com/rest/auth/token/create?app_key=100627&sign_method=sha256×tamp=1524383629000&partner_id=lazop-sdk-python-20180422&code=0_1VD1csgglmJhiCks6GrblB0A2&sign=A3D8AD2A6F52D7F87769312EC0BF81AEDEF4CD5A3CB6A122F77B307112F0028E^_^InvalidCode^_^Invalid authorization code
2 | 192.168.31.103^_^Darwin-17.5.0-x86_64-i386-64bit^_^https://auth.lazada.com/rest/auth/token/create?app_key=100627&sign_method=sha256×tamp=1524383748000&partner_id=lazop-sdk-python-20180422&code=0_1VD1csgglmJhiCks6GrblB0A2&sign=520B38C698EF4AA678353C22D2E134AD1DF4005A88E025C69519AA38C89B42C4^_^InvalidCode^_^Invalid authorization code
3 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/lazada_erpnext_connector/doctype/lazada_settings/lazada_settings.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Raaj Tailor and contributors
2 | // For license information, please see license.txt
3 |
4 | frappe.ui.form.on('Lazada Settings', {
5 | // refresh: function(frm) {
6 |
7 | // }
8 | from_date:function(frm){
9 | if(frm.doc.from_date && frm.doc.to_date){
10 | check_date(frm.doc.from_date,frm.doc.to_date)
11 | }
12 |
13 | },
14 | to_date:function(frm){
15 | if(frm.doc.from_date && frm.doc.to_date){
16 | check_date(frm.doc.from_date,frm.doc.to_date)
17 | }
18 | },
19 | authorize_lazada:function(frm){
20 | var auth_url = "https://auth.lazada.com/oauth/authorize?response_type=code&force_auth=true&redirect_uri="+frm.doc.callback_url+"&client_id="+frm.doc.api_key
21 | console.log(location.origin)
22 | window.open(auth_url);
23 | }
24 | });
25 |
26 | function check_date(from_date,to_date){
27 | if(from_date > to_date){
28 | frappe.throw("Please Enter Correct From Date and To Date!")
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 ERPNext Apps
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/lazada_erpnext_connector/doctype/lazada_defaults/lazada_defaults.json:
--------------------------------------------------------------------------------
1 | {
2 | "creation": "2020-07-16 23:11:59.736177",
3 | "doctype": "DocType",
4 | "editable_grid": 1,
5 | "engine": "InnoDB",
6 | "field_order": [
7 | "customer",
8 | "default_warehouse"
9 | ],
10 | "fields": [
11 | {
12 | "fieldname": "customer",
13 | "fieldtype": "Link",
14 | "label": "Customer",
15 | "options": "Customer"
16 | },
17 | {
18 | "fieldname": "default_warehouse",
19 | "fieldtype": "Link",
20 | "label": "Default Warehouse",
21 | "options": "Warehouse"
22 | }
23 | ],
24 | "issingle": 1,
25 | "modified": "2020-07-16 23:29:58.345986",
26 | "modified_by": "Administrator",
27 | "module": "Lazada ERPNext Connector",
28 | "name": "Lazada Defaults",
29 | "owner": "Administrator",
30 | "permissions": [
31 | {
32 | "create": 1,
33 | "delete": 1,
34 | "email": 1,
35 | "print": 1,
36 | "read": 1,
37 | "role": "System Manager",
38 | "share": 1,
39 | "write": 1
40 | }
41 | ],
42 | "quick_entry": 1,
43 | "sort_field": "modified",
44 | "sort_order": "DESC",
45 | "track_changes": 1
46 | }
--------------------------------------------------------------------------------
/lazada_erpnext_connector/lazada_erpnext_connector/sales_order.py:
--------------------------------------------------------------------------------
1 | from __future__ import unicode_literals
2 | import frappe
3 | from lazada_erpnext_connector.lazada_erpnext_connector.doctype.lazada_settings.lazada_settings import LazopClient,LazopRequest
4 |
5 | def submit(self,method):
6 | item_ids = []
7 | for item in self.items:
8 | item_ids.append(item.order_item_id)
9 | client = LazopClient(frappe.db.get_value("Lazada Settings",None,"url"), frappe.db.get_value("Lazada Settings",None,"api_key") ,frappe.db.get_value("Lazada Settings",None,"api_secret"))
10 | request = LazopRequest('/order/rts')
11 | request.add_api_param('delivery_type', 'dropship')
12 | request.add_api_param('order_item_ids', str(item_ids))
13 | request.add_api_param('shipment_provider', self.shipment_provider)
14 | request.add_api_param('tracking_number', '12345678')
15 | response = client.execute(request, frappe.db.get_value("Lazada Settings",None,"access_token"))
16 | # response = client.execute(request, frappe.db.get_value("Lazada Settings",None,"access_token"))
17 | frappe.msgprint(str(response.body))
18 |
19 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/lazada_erpnext_connector/doctype/shipment_provider/shipment_provider.json:
--------------------------------------------------------------------------------
1 | {
2 | "autoname": "field:shipment_provider",
3 | "creation": "2020-07-31 15:50:01.002580",
4 | "doctype": "DocType",
5 | "editable_grid": 1,
6 | "engine": "InnoDB",
7 | "field_order": [
8 | "shipment_provider",
9 | "is_cod"
10 | ],
11 | "fields": [
12 | {
13 | "fieldname": "shipment_provider",
14 | "fieldtype": "Data",
15 | "label": "Shipment Provider ",
16 | "unique": 1
17 | },
18 | {
19 | "default": "0",
20 | "fieldname": "is_cod",
21 | "fieldtype": "Check",
22 | "label": "Is COD"
23 | }
24 | ],
25 | "modified": "2020-07-31 16:10:11.307509",
26 | "modified_by": "Administrator",
27 | "module": "Lazada ERPNext Connector",
28 | "name": "Shipment Provider",
29 | "owner": "Administrator",
30 | "permissions": [
31 | {
32 | "create": 1,
33 | "delete": 1,
34 | "email": 1,
35 | "export": 1,
36 | "print": 1,
37 | "read": 1,
38 | "report": 1,
39 | "role": "System Manager",
40 | "share": 1,
41 | "write": 1
42 | }
43 | ],
44 | "sort_field": "modified",
45 | "sort_order": "DESC",
46 | "track_changes": 1
47 | }
--------------------------------------------------------------------------------
/lazada_erpnext_connector/lazada_erpnext_connector/doctype/lazada_connector_error_log/lazada_connector_error_log.json:
--------------------------------------------------------------------------------
1 | {
2 | "autoname": "LER.####",
3 | "creation": "2020-07-03 17:40:11.130237",
4 | "doctype": "DocType",
5 | "editable_grid": 1,
6 | "engine": "InnoDB",
7 | "field_order": [
8 | "call",
9 | "error_code",
10 | "error_log"
11 | ],
12 | "fields": [
13 | {
14 | "fieldname": "call",
15 | "fieldtype": "Data",
16 | "in_list_view": 1,
17 | "label": "Call",
18 | "read_only": 1
19 | },
20 | {
21 | "fieldname": "error_log",
22 | "fieldtype": "Text",
23 | "in_list_view": 1,
24 | "label": "Error Log",
25 | "read_only": 1
26 | },
27 | {
28 | "fieldname": "error_code",
29 | "fieldtype": "Data",
30 | "in_list_view": 1,
31 | "label": "Error Code",
32 | "read_only": 1
33 | }
34 | ],
35 | "modified": "2020-07-03 18:08:45.959024",
36 | "modified_by": "Administrator",
37 | "module": "Lazada ERPNext Connector",
38 | "name": "Lazada Connector Error Log",
39 | "owner": "Administrator",
40 | "permissions": [
41 | {
42 | "create": 1,
43 | "delete": 1,
44 | "email": 1,
45 | "export": 1,
46 | "print": 1,
47 | "read": 1,
48 | "report": 1,
49 | "role": "System Manager",
50 | "share": 1,
51 | "write": 1
52 | }
53 | ],
54 | "quick_entry": 1,
55 | "sort_field": "modified",
56 | "sort_order": "DESC",
57 | "track_changes": 1
58 | }
--------------------------------------------------------------------------------
/lazada_erpnext_connector/public/js/lazada.js:
--------------------------------------------------------------------------------
1 | var jsElm = document.createElement("script");
2 | jsElm.type = "application/javascript";
3 | jsElm.src = "//laz-g-cdn.alicdn.com/sj/securesdk/0.0.3/securesdk_lzd_v1.js";
4 | jsElm.id = "J_secure_sdk_v2";
5 | jsElm.setAttribute("data-appkey", "120609")
6 |
7 | $( document ).ready(function() {
8 | var code = getUrlParameter('code');
9 | if(code){
10 | frappe.db.set_value("Lazada Settings",null,"code",code).then((res)=>{
11 | if(res.message.code){
12 | frappe.msgprint("Lazada is Authorized Sucessfully!")
13 | // window.location = window.location.href.split("?")[0];
14 | window.location.replace(window.location.href.split("?")[0]);
15 | }
16 | })
17 | }
18 | document.body.appendChild(jsElm);
19 | });
20 |
21 | var getUrlParameter = function getUrlParameter(sParam) {
22 | var sPageURL = window.location.search.substring(1),
23 | sURLVariables = sPageURL.split('&'),
24 | sParameterName,
25 | i;
26 |
27 | for (i = 0; i < sURLVariables.length; i++) {
28 | sParameterName = sURLVariables[i].split('=');
29 |
30 | if (sParameterName[0] === sParam) {
31 | return sParameterName[1] === undefined ? true : decodeURIComponent(sParameterName[1]);
32 | }
33 | }
34 | };
--------------------------------------------------------------------------------
/lazada_erpnext_connector/lazada_erpnext_connector/stock_entry.py:
--------------------------------------------------------------------------------
1 | from __future__ import unicode_literals
2 | import frappe
3 | from lazada_erpnext_connector.lazada_erpnext_connector.doctype.lazada_settings.lazada_settings import LazopClient,LazopRequest
4 |
5 | def get_pw(doctype,field_name):
6 | docSettings = frappe.get_single(doctype)
7 | strPassword = docSettings.get_password(field_name)
8 | return strPassword
9 |
10 | api_secret = get_pw("Lazada Settings","api_secret")
11 | access_token = get_pw("Lazada Settings","access_token")
12 |
13 | def submit(self,method):
14 | # frappe.msgprint("in_submit")
15 | if self.update_on_lazada == 1:
16 | # frappe.msgprint("here")
17 | lazada_warehouse = frappe.db.get_value("Lazada Defaults",None,"default_warehouse")
18 | for item in self.items:
19 | if item.t_warehouse == lazada_warehouse:
20 | new_stock = frappe.get_value("Bin",{"warehouse":lazada_warehouse,"item_code":item.item_code},"actual_qty")
21 | # frappe.msgprint(str(new_stock))
22 | set_stock_lazada(item.item_code,int(new_stock))
23 | # item_ids.append(item.order_item_id)
24 |
25 | # # response = client.execute(request, frappe.db.get_value("Lazada Settings",None,"access_token"))
26 | # frappe.msgprint(str(response.body))
27 | def set_stock_lazada(sku_id,qty):
28 | client = LazopClient(frappe.db.get_value("Lazada Settings",None,"url"), frappe.db.get_value("Lazada Settings",None,"api_key") ,api_secret)
29 | request = LazopRequest('/product/price_quantity/update')
30 | request.add_api_param('payload', """
31 |
32 |
33 |
34 | {sku}
35 | {qty}
36 |
37 |
38 |
39 | """.format(sku=sku_id,qty=qty))
40 | response = client.execute(request, access_token)
41 | if str(response.body['code']) == '0':
42 | frappe.msgprint("Stock has been updated to Lazada Seller!")
43 | else:
44 | # create_error_log('/order/rts',response.code,response.message)
45 | frappe.throw("Error Occured While updating Stock on Lazada. Error: {}".format(response.message))
46 | # frappe.throw("Can't find Order with order id {}".format(self.lazada_order_id))
47 |
48 | def create_error_log(call,error_code,error):
49 | doc = frappe.new_doc("Lazada Connector Error Log")
50 | doc.call=call
51 | doc.error_code=error_code
52 | doc.error_log=error
53 | doc.insert(ignore_permissions=True)
54 |
55 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/lazada_erpnext_connector/delivery_note.py:
--------------------------------------------------------------------------------
1 | from __future__ import unicode_literals
2 | import frappe
3 | from lazada_erpnext_connector.lazada_erpnext_connector.doctype.lazada_settings.lazada_settings import LazopClient,LazopRequest
4 |
5 |
6 | def get_pw(doctype,field_name):
7 | docSettings = frappe.get_single(doctype)
8 | strPassword = docSettings.get_password(field_name)
9 | return strPassword
10 |
11 | api_secret = get_pw("Lazada Settings","api_secret")
12 | access_token = get_pw("Lazada Settings","access_token")
13 |
14 | def submit(self,method):
15 | if self.update_lazada_status:
16 | item_ids = []
17 | for item in self.items:
18 | item_ids.append(item.order_item_id)
19 | client = LazopClient(frappe.db.get_value("Lazada Settings",None,"url"), frappe.db.get_value("Lazada Settings",None,"api_key") ,api_secret)
20 | request = LazopRequest('/order/rts')
21 | request.add_api_param('delivery_type', 'dropship')
22 | request.add_api_param('order_item_ids', str(item_ids))
23 | request.add_api_param('shipment_provider', self.shipment_provider)
24 | request.add_api_param('tracking_number', '12345678')
25 | response = client.execute(request, access_token)
26 | # response = client.execute(request, frappe.db.get_value("Lazada Settings",None,"access_token"))
27 | if response.code == '0':
28 | frappe.msgprint("Sales Order is Ready to Ship!")
29 | else:
30 | create_error_log('/order/rts',response.code,response.message)
31 | frappe.msgprint("Error Occured While updating status on Lazada. Please Check Lazada Connector Error Log")
32 | frappe.msgprint(str(response.body))
33 | def validate(self,method):
34 | if self.update_lazada_status:
35 | request = LazopRequest('/order/get','GET')
36 | request.add_api_param('order_id', str(self.lazada_order_id))
37 | client = LazopClient(frappe.db.get_value("Lazada Settings",None,"url"), frappe.db.get_value("Lazada Settings",None,"api_key") ,api_secret)
38 | response = client.execute(request, access_token)
39 | # frappe.msgprint(str(response))
40 | if str(response.body['code']) == '0':
41 | # frappe.msgprint(str(response.body['data']['statuses']))
42 | if "canceled" in list(response.body['data']['statuses']):
43 | frappe.throw("This Sales Order id Cancelled in Lazada Seller!")
44 | else:
45 | # create_error_log('/order/rts',response.code,response.message)
46 | frappe.throw("Error Occured While creating Delivery Note. Error: {}".format(response.message))
47 | # frappe.throw("Can't find Order with order id {}".format(self.lazada_order_id))
48 |
49 | def create_error_log(call,error_code,error):
50 | doc = frappe.new_doc("Lazada Connector Error Log")
51 | doc.call=call
52 | doc.error_code=error_code
53 | doc.error_log=error
54 | doc.insert(ignore_permissions=True)
55 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/hooks.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 | from . import __version__ as app_version
4 |
5 | app_name = "lazada_erpnext_connector"
6 | app_title = "Lazada ERPNext Connector"
7 | app_publisher = "Raaj Tailor"
8 | app_description = "Lazada Ecommerce Platform Integration witH E"
9 | app_icon = "octicon octicon-file-directory"
10 | app_color = "grey"
11 | app_email = "tailorraj111@gmail.com"
12 | app_license = "MIT"
13 |
14 | fixtures = ["Custom Field"]
15 | # Includes in
16 | # ------------------
17 |
18 | # include js, css files in header of desk.html
19 | # app_include_css = "/assets/lazada_erpnext_connector/css/lazada_erpnext_connector.css"
20 | # app_include_js = "/assets/lazada_erpnext_connector/js/lazada_erpnext_connector.js"
21 | app_include_js = ["/assets/lazada_erpnext_connector/js/lazada.js"]
22 |
23 | # include js, css files in header of web template
24 | # web_include_css = "/assets/lazada_erpnext_connector/css/lazada_erpnext_connector.css"
25 | # web_include_js = "/assets/lazada_erpnext_connector/js/lazada_erpnext_connector.js"
26 |
27 | # include js in page
28 | # page_js = {"page" : "public/js/file.js"}
29 | doctype_js = {
30 | "Sales Order": ["custom_scripts/sales_order.js"],
31 | }
32 | # include js in doctype views
33 | # doctype_js = {"doctype" : "public/js/doctype.js"}
34 | # doctype_list_js = {"doctype" : "public/js/doctype_list.js"}
35 | # doctype_tree_js = {"doctype" : "public/js/doctype_tree.js"}
36 | # doctype_calendar_js = {"doctype" : "public/js/doctype_calendar.js"}
37 |
38 | # Home Pages
39 | # ----------
40 |
41 | # application home page (will override Website Settings)
42 | # home_page = "login"
43 |
44 | # website user home page (by Role)
45 | # role_home_page = {
46 | # "Role": "home_page"
47 | # }
48 |
49 | # Website user home page (by function)
50 | # get_website_user_home_page = "lazada_erpnext_connector.utils.get_home_page"
51 |
52 | # Generators
53 | # ----------
54 |
55 | # automatically create page for each record of this doctype
56 | # website_generators = ["Web Page"]
57 |
58 | # Installation
59 | # ------------
60 |
61 | # before_install = "lazada_erpnext_connector.install.before_install"
62 | # after_install = "lazada_erpnext_connector.install.after_install"
63 |
64 | # Desk Notifications
65 | # ------------------
66 | # See frappe.core.notifications.get_notification_config
67 |
68 | # notification_config = "lazada_erpnext_connector.notifications.get_notification_config"
69 |
70 | # Permissions
71 | # -----------
72 | # Permissions evaluated in scripted ways
73 |
74 | # permission_query_conditions = {
75 | # "Event": "frappe.desk.doctype.event.event.get_permission_query_conditions",
76 | # }
77 | #
78 | # has_permission = {
79 | # "Event": "frappe.desk.doctype.event.event.has_permission",
80 | # }
81 |
82 | # Document Events
83 | # ---------------
84 | # Hook on document methods and events
85 | doc_events = {
86 |
87 | "Delivery Note" :{
88 | "on_submit": "lazada_erpnext_connector.lazada_erpnext_connector.delivery_note.submit",
89 | "validate": "lazada_erpnext_connector.lazada_erpnext_connector.delivery_note.validate",
90 |
91 | }
92 | ,
93 | "Stock Entry":{
94 | "on_submit":"lazada_erpnext_connector.lazada_erpnext_connector.stock_entry.submit"
95 | }
96 | }
97 | # doc_events = {
98 | # "*": {
99 | # "on_update": "method",
100 | # "on_cancel": "method",
101 | # "on_trash": "method"
102 | # }
103 | # }
104 |
105 | # Scheduled Tasks
106 | # ---------------
107 |
108 | scheduler_events = {
109 | # "cron": {
110 | # "*/1 * * * *":[
111 | # "lazada_erpnext_connector.lazada_erpnext_connector.doctype.lazada_settings.lazada_settings.get_refresh"
112 | # ]
113 | # }
114 | "daily": [
115 | "lazada_erpnext_connector.lazada_erpnext_connector.doctype.lazada_settings.lazada_settings.get_refresh"
116 | ],
117 | "hourly": [
118 | "lazada_erpnext_connector.lazada_erpnext_connector.doctype.lazada_settings.lazada_settings.get_orders"
119 | ]
120 |
121 | }
122 |
123 | # scheduler_events = {
124 | # "all": [
125 | # "lazada_erpnext_connector.tasks.all"
126 | # ],
127 | # "daily": [
128 | # "lazada_erpnext_connector.tasks.daily"
129 | # ],
130 | # "hourly": [
131 | # "lazada_erpnext_connector.tasks.hourly"
132 | # ],
133 | # "weekly": [
134 | # "lazada_erpnext_connector.tasks.weekly"
135 | # ]
136 | # "monthly": [
137 | # "lazada_erpnext_connector.tasks.monthly"
138 | # ]
139 | # }
140 |
141 | # Testing
142 | # -------
143 |
144 | # before_tests = "lazada_erpnext_connector.install.before_tests"
145 |
146 | # Overriding Methods
147 | # ------------------------------
148 | #
149 | # override_whitelisted_methods = {
150 | # "frappe.desk.doctype.event.event.get_events": "lazada_erpnext_connector.event.get_events"
151 | # }
152 | #
153 | # each overriding function accepts a `data` argument;
154 | # generated from the base implementation of the doctype dashboard,
155 | # along with any modifications made in other Frappe apps
156 | # override_doctype_dashboards = {
157 | # "Task": "lazada_erpnext_connector.task.get_dashboard_data"
158 | # }
159 |
160 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/public/lazop/base.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | '''
3 | Created on 2018-03-21
4 |
5 | @author: xuteng.xt
6 | '''
7 |
8 | import requests
9 | import time
10 | import hmac
11 | import hashlib
12 | import json
13 | import mimetypes
14 | import itertools
15 | import random
16 | import logging
17 | import os
18 | from os.path import expanduser
19 | import socket
20 | import platform
21 |
22 | # dir = os.getenv('HOME')
23 | dir = expanduser("~")
24 | isExists = os.path.exists(dir + "/logs")
25 | if not isExists:
26 | os.makedirs(dir + "/logs")
27 | logger = logging.getLogger(__name__)
28 | logger.setLevel(level = logging.ERROR)
29 | handler = logging.FileHandler(dir + "/logs/lazopsdk.log." + time.strftime("%Y-%m-%d", time.localtime()))
30 | handler.setLevel(logging.ERROR)
31 | # formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
32 | formatter = logging.Formatter('%(message)s')
33 | handler.setFormatter(formatter)
34 | logger.addHandler(handler)
35 |
36 | P_SDK_VERSION = "lazop-sdk-python-20181207"
37 |
38 | P_APPKEY = "app_key"
39 | P_ACCESS_TOKEN = "access_token"
40 | P_TIMESTAMP = "timestamp"
41 | P_SIGN = "sign"
42 | P_SIGN_METHOD = "sign_method"
43 | P_PARTNER_ID = "partner_id"
44 | P_DEBUG = "debug"
45 |
46 | P_CODE = 'code'
47 | P_TYPE = 'type'
48 | P_MESSAGE = 'message'
49 | P_REQUEST_ID = 'request_id'
50 |
51 | P_API_GATEWAY_URL_SG = 'https://api.lazada.sg/rest'
52 | P_API_GATEWAY_URL_MY = 'https://api.lazada.com.my/rest'
53 | P_API_GATEWAY_URL_VN = 'https://api.lazada.vn/rest'
54 | P_API_GATEWAY_URL_TH = 'https://api.lazada.co.th/rest'
55 | P_API_GATEWAY_URL_PH = 'https://api.lazada.com.ph/rest'
56 | P_API_GATEWAY_URL_ID = 'https://api.lazada.co.id/rest'
57 | P_API_AUTHORIZATION_URL = 'https://auth.lazada.com/rest'
58 |
59 | P_LOG_LEVEL_DEBUG = "DEBUG"
60 | P_LOG_LEVEL_INFO = "INFO"
61 | P_LOG_LEVEL_ERROR = "ERROR"
62 |
63 |
64 | def sign(secret,api, parameters):
65 | #===========================================================================
66 | # @param secret
67 | # @param parameters
68 | #===========================================================================
69 | sort_dict = sorted(parameters)
70 |
71 | parameters_str = "%s%s" % (api,
72 | str().join('%s%s' % (key, parameters[key]) for key in sort_dict))
73 |
74 | h = hmac.new(secret.encode(encoding="utf-8"), parameters_str.encode(encoding="utf-8"), digestmod=hashlib.sha256)
75 |
76 | return h.hexdigest().upper()
77 |
78 |
79 | def mixStr(pstr):
80 | if(isinstance(pstr, str)):
81 | return pstr
82 | elif(isinstance(pstr, unicode)):
83 | return pstr.encode('utf-8')
84 | else:
85 | return str(pstr)
86 |
87 | def logApiError(appkey, sdkVersion, requestUrl, code, message):
88 | localIp = socket.gethostbyname(socket.gethostname())
89 | platformType = platform.platform()
90 | logger.error("%s^_^%s^_^%s^_^%s^_^%s^_^%s^_^%s^_^%s" % (
91 | appkey, sdkVersion,
92 | time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
93 | localIp, platformType, requestUrl, code, message))
94 |
95 | class LazopRequest(object):
96 | def __init__(self,api_pame,http_method = 'POST'):
97 | self._api_params = {}
98 | self._file_params = {}
99 | self._api_pame = api_pame
100 | self._http_method = http_method
101 |
102 | def add_api_param(self,key,value):
103 | self._api_params[key] = value
104 |
105 | def add_file_param(self,key,value):
106 | self._file_params[key] = value
107 |
108 |
109 | class LazopResponse(object):
110 | def __init__(self):
111 | self.type = None
112 | self.code = None
113 | self.message = None
114 | self.request_id = None
115 | self.body = None
116 |
117 | def __str__(self, *args, **kwargs):
118 | sb = "type=" + mixStr(self.type) +\
119 | " code=" + mixStr(self.code) +\
120 | " message=" + mixStr(self.message) +\
121 | " requestId=" + mixStr(self.request_id)
122 | return sb
123 |
124 | class LazopClient(object):
125 |
126 | log_level = P_LOG_LEVEL_ERROR
127 | def __init__(self, server_url,app_key,app_secret,timeout=30):
128 | self._server_url = server_url
129 | self._app_key = app_key
130 | self._app_secret = app_secret
131 | self._timeout = timeout
132 |
133 | def execute(self, request,access_token = None):
134 |
135 | sys_parameters = {
136 | P_APPKEY: self._app_key,
137 | P_SIGN_METHOD: "sha256",
138 | P_TIMESTAMP: str(int(round(time.time()))) + '000',
139 | P_PARTNER_ID: P_SDK_VERSION
140 | }
141 |
142 | if(self.log_level == P_LOG_LEVEL_DEBUG):
143 | sys_parameters[P_DEBUG] = 'true'
144 |
145 | if(access_token):
146 | sys_parameters[P_ACCESS_TOKEN] = access_token
147 |
148 | application_parameter = request._api_params;
149 |
150 | sign_parameter = sys_parameters.copy()
151 | sign_parameter.update(application_parameter)
152 |
153 | sign_parameter[P_SIGN] = sign(self._app_secret,request._api_pame,sign_parameter)
154 |
155 | api_url = "%s%s" % (self._server_url,request._api_pame)
156 |
157 | full_url = api_url + "?";
158 | for key in sign_parameter:
159 | full_url += key + "=" + str(sign_parameter[key]) + "&";
160 | full_url = full_url[0:-1]
161 |
162 | try:
163 | if(request._http_method == 'POST' or len(request._file_params) != 0) :
164 | r = requests.post(api_url,sign_parameter,files=request._file_params, timeout=self._timeout)
165 | else:
166 | r = requests.get(api_url,sign_parameter, timeout=self._timeout)
167 | except Exception as err:
168 | logApiError(self._app_key, P_SDK_VERSION, full_url, "HTTP_ERROR", str(err))
169 | raise err
170 |
171 | response = LazopResponse()
172 |
173 | jsonobj = r.json()
174 |
175 | if P_CODE in jsonobj:
176 | response.code = jsonobj[P_CODE]
177 | if P_TYPE in jsonobj:
178 | response.type = jsonobj[P_TYPE]
179 | if P_MESSAGE in jsonobj:
180 | response.message = jsonobj[P_MESSAGE]
181 | if P_REQUEST_ID in jsonobj:
182 | response.request_id = jsonobj[P_REQUEST_ID]
183 |
184 | if response.code is not None and response.code != "0":
185 | logApiError(self._app_key, P_SDK_VERSION, full_url, response.code, response.message)
186 | else:
187 | if(self.log_level == P_LOG_LEVEL_DEBUG or self.log_level == P_LOG_LEVEL_INFO):
188 | logApiError(self._app_key, P_SDK_VERSION, full_url, "", "")
189 |
190 | response.body = jsonobj
191 |
192 | return response
193 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/utils/lazada_utils.py:
--------------------------------------------------------------------------------
1 | from __future__ import unicode_literals
2 | import frappe
3 | from frappe.model.document import Document
4 | import requests
5 | import time
6 | import hmac
7 | import hashlib
8 | import json
9 | import mimetypes
10 | import itertools
11 | import random
12 | import logging
13 | import os
14 | from os.path import expanduser
15 | import socket
16 | import platform
17 | from datetime import datetime
18 | from frappe.utils import now,getdate,add_days
19 |
20 |
21 | dir = expanduser("~")
22 | isExists = os.path.exists(dir + "/logs")
23 | if not isExists:
24 | os.makedirs(dir + "/logs")
25 | logger = logging.getLogger(__name__)
26 | logger.setLevel(level = logging.ERROR)
27 | handler = logging.FileHandler(dir + "/logs/lazopsdk.log." + time.strftime("%Y-%m-%d", time.localtime()))
28 | handler.setLevel(logging.ERROR)
29 |
30 | formatter = logging.Formatter('%(message)s')
31 | handler.setFormatter(formatter)
32 | logger.addHandler(handler)
33 |
34 | P_SDK_VERSION = "lazop-sdk-python-20181207"
35 |
36 | P_APPKEY = "app_key"
37 | P_ACCESS_TOKEN = "access_token"
38 | P_TIMESTAMP = "timestamp"
39 | P_SIGN = "sign"
40 | P_SIGN_METHOD = "sign_method"
41 | P_PARTNER_ID = "partner_id"
42 | P_DEBUG = "debug"
43 |
44 | P_CODE = 'code'
45 | P_TYPE = 'type'
46 | P_MESSAGE = 'message'
47 | P_REQUEST_ID = 'request_id'
48 |
49 | P_API_GATEWAY_URL_SG = 'https://api.lazada.sg/rest'
50 | P_API_GATEWAY_URL_MY = 'https://api.lazada.com.my/rest'
51 | P_API_GATEWAY_URL_VN = 'https://api.lazada.vn/rest'
52 | P_API_GATEWAY_URL_TH = 'https://api.lazada.co.th/rest'
53 | P_API_GATEWAY_URL_PH = 'https://api.lazada.com.ph/rest'
54 | P_API_GATEWAY_URL_ID = 'https://api.lazada.co.id/rest'
55 | P_API_AUTHORIZATION_URL = 'https://auth.lazada.com/rest'
56 |
57 | P_LOG_LEVEL_DEBUG = "DEBUG"
58 | P_LOG_LEVEL_INFO = "INFO"
59 | P_LOG_LEVEL_ERROR = "ERROR"
60 |
61 |
62 | def sign(secret,api, parameters):
63 | #===========================================================================
64 | # @param secret
65 | # @param parameters
66 | #===========================================================================
67 | sort_dict = sorted(parameters)
68 |
69 | parameters_str = "%s%s" % (api,
70 | str().join('%s%s' % (key, parameters[key]) for key in sort_dict))
71 |
72 | h = hmac.new(secret.encode(encoding="utf-8"), parameters_str.encode(encoding="utf-8"), digestmod=hashlib.sha256)
73 |
74 | return h.hexdigest().upper()
75 |
76 |
77 | def mixStr(pstr):
78 | if(isinstance(pstr, str)):
79 | return pstr
80 | elif(isinstance(pstr, str)):
81 | return pstr.encode('utf-8')
82 | else:
83 | return str(pstr)
84 |
85 | def logApiError(appkey, sdkVersion, requestUrl, code, message):
86 | localIp = socket.gethostbyname(socket.gethostname())
87 | platformType = platform.platform()
88 | logger.error("%s^_^%s^_^%s^_^%s^_^%s^_^%s^_^%s^_^%s" % (
89 | appkey, sdkVersion,
90 | time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
91 | localIp, platformType, requestUrl, code, message))
92 |
93 | class LazopRequest(object):
94 | def __init__(self,api_pame,http_method = 'POST'):
95 | self._api_params = {}
96 | self._file_params = {}
97 | self._api_pame = api_pame
98 | self._http_method = http_method
99 |
100 | def add_api_param(self,key,value):
101 | self._api_params[key] = value
102 |
103 | def add_file_param(self,key,value):
104 | self._file_params[key] = value
105 |
106 |
107 | class LazopResponse(object):
108 | def __init__(self):
109 | self.type = None
110 | self.code = None
111 | self.message = None
112 | self.request_id = None
113 | self.body = None
114 |
115 | def __str__(self, *args, **kwargs):
116 | sb = "type=" + mixStr(self.type) +\
117 | " code=" + mixStr(self.code) +\
118 | " message=" + mixStr(self.message) +\
119 | " requestId=" + mixStr(self.request_id)
120 | return sb
121 |
122 | class LazopClient(object):
123 |
124 | log_level = P_LOG_LEVEL_ERROR
125 | def __init__(self, server_url,app_key,app_secret,timeout=30):
126 | self._server_url = server_url
127 | self._app_key = app_key
128 | self._app_secret = app_secret
129 | self._timeout = timeout
130 |
131 | def execute(self, request,access_token = None):
132 |
133 | sys_parameters = {
134 | P_APPKEY: self._app_key,
135 | P_SIGN_METHOD: "sha256",
136 | P_TIMESTAMP: str(int(round(time.time()))) + '000',
137 | P_PARTNER_ID: P_SDK_VERSION
138 | }
139 |
140 | if(self.log_level == P_LOG_LEVEL_DEBUG):
141 | sys_parameters[P_DEBUG] = 'true'
142 |
143 | if(access_token):
144 | sys_parameters[P_ACCESS_TOKEN] = access_token
145 |
146 | application_parameter = request._api_params;
147 |
148 | sign_parameter = sys_parameters.copy()
149 | sign_parameter.update(application_parameter)
150 |
151 | sign_parameter[P_SIGN] = sign(self._app_secret,request._api_pame,sign_parameter)
152 |
153 | api_url = "%s%s" % (self._server_url,request._api_pame)
154 |
155 | full_url = api_url + "?";
156 | for key in sign_parameter:
157 | full_url += key + "=" + str(sign_parameter[key]) + "&";
158 | full_url = full_url[0:-1]
159 |
160 | try:
161 | if(request._http_method == 'POST' or len(request._file_params) != 0) :
162 | r = requests.post(api_url,sign_parameter,files=request._file_params, timeout=self._timeout)
163 | else:
164 | r = requests.get(api_url,sign_parameter, timeout=self._timeout)
165 | except Exception as err:
166 | logApiError(self._app_key, P_SDK_VERSION, full_url, "HTTP_ERROR", str(err))
167 | raise err
168 |
169 | response = LazopResponse()
170 |
171 | jsonobj = r.json()
172 |
173 | if P_CODE in jsonobj:
174 | response.code = jsonobj[P_CODE]
175 | if P_TYPE in jsonobj:
176 | response.type = jsonobj[P_TYPE]
177 | if P_MESSAGE in jsonobj:
178 | response.message = jsonobj[P_MESSAGE]
179 | if P_REQUEST_ID in jsonobj:
180 | response.request_id = jsonobj[P_REQUEST_ID]
181 |
182 | if response.code is not None and response.code != "0":
183 | logApiError(self._app_key, P_SDK_VERSION, full_url, response.code, response.message)
184 | else:
185 | if(self.log_level == P_LOG_LEVEL_DEBUG or self.log_level == P_LOG_LEVEL_INFO):
186 | logApiError(self._app_key, P_SDK_VERSION, full_url, "", "")
187 |
188 | response.body = jsonobj
189 |
190 | return response
--------------------------------------------------------------------------------
/lazada_erpnext_connector/lazada_erpnext_connector/doctype/lazada_settings/lazada_settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "creation": "2020-06-30 17:18:08.240751",
3 | "doctype": "DocType",
4 | "editable_grid": 1,
5 | "engine": "InnoDB",
6 | "field_order": [
7 | "url",
8 | "api_key",
9 | "api_secret",
10 | "column_break_4",
11 | "code",
12 | "callback_url",
13 | "authorize_lazada",
14 | "section_break_7",
15 | "access_token",
16 | "refresh_token",
17 | "column_break_10",
18 | "last_sync_access_token",
19 | "get_refresh_token",
20 | "get_access_token",
21 | "functions_call_section",
22 | "search_item",
23 | "created_after",
24 | "sync_limit",
25 | "column_break_14",
26 | "synced_items",
27 | "product_last_sync",
28 | "remaining_items",
29 | "total_lazada_item",
30 | "get_products",
31 | "section_break_15",
32 | "get_transactions",
33 | "column_break_18",
34 | "from_date",
35 | "to_date",
36 | "transaction_last_sync",
37 | "section_break_20",
38 | "get_orders",
39 | "column_break_22",
40 | "order_last_sync",
41 | "section_break_24",
42 | "get_category",
43 | "get_shipment_provider",
44 | "column_break_27",
45 | "last_shipment_provider_sync"
46 | ],
47 | "fields": [
48 | {
49 | "fieldname": "api_key",
50 | "fieldtype": "Data",
51 | "label": "API Key"
52 | },
53 | {
54 | "fieldname": "api_secret",
55 | "fieldtype": "Password",
56 | "label": "API Secret"
57 | },
58 | {
59 | "fieldname": "callback_url",
60 | "fieldtype": "Data",
61 | "label": "Callback URL"
62 | },
63 | {
64 | "fieldname": "code",
65 | "fieldtype": "Data",
66 | "label": "Code"
67 | },
68 | {
69 | "fieldname": "url",
70 | "fieldtype": "Data",
71 | "label": "URL"
72 | },
73 | {
74 | "fieldname": "access_token",
75 | "fieldtype": "Password",
76 | "label": "Access Token"
77 | },
78 | {
79 | "fieldname": "refresh_token",
80 | "fieldtype": "Password",
81 | "label": "Refresh Token"
82 | },
83 | {
84 | "fieldname": "get_access_token",
85 | "fieldtype": "Button",
86 | "label": "Get Access Token",
87 | "options": "get_access_token"
88 | },
89 | {
90 | "fieldname": "get_products",
91 | "fieldtype": "Button",
92 | "label": "Get Products",
93 | "options": "get_products"
94 | },
95 | {
96 | "fieldname": "get_refresh_token",
97 | "fieldtype": "Button",
98 | "label": "Get Refresh Token",
99 | "options": "get_refresh_token"
100 | },
101 | {
102 | "fieldname": "get_orders",
103 | "fieldtype": "Button",
104 | "label": "Get Orders",
105 | "options": "get_orders"
106 | },
107 | {
108 | "fieldname": "get_transactions",
109 | "fieldtype": "Button",
110 | "label": "Get Transactions",
111 | "options": "get_transactions"
112 | },
113 | {
114 | "fieldname": "column_break_4",
115 | "fieldtype": "Column Break"
116 | },
117 | {
118 | "fieldname": "functions_call_section",
119 | "fieldtype": "Section Break",
120 | "label": "Product Sync"
121 | },
122 | {
123 | "fieldname": "last_sync_access_token",
124 | "fieldtype": "Datetime",
125 | "label": "Last Sync Access Token",
126 | "read_only": 1
127 | },
128 | {
129 | "fieldname": "product_last_sync",
130 | "fieldtype": "Data",
131 | "label": "Product Last Sync",
132 | "read_only": 1
133 | },
134 | {
135 | "fieldname": "order_last_sync",
136 | "fieldtype": "Data",
137 | "label": "Order Last Sync"
138 | },
139 | {
140 | "fieldname": "get_category",
141 | "fieldtype": "Button",
142 | "hidden": 1,
143 | "label": "Get Category",
144 | "options": "get_category"
145 | },
146 | {
147 | "fieldname": "get_shipment_provider",
148 | "fieldtype": "Button",
149 | "label": "Get Shipment Provider",
150 | "options": "get_shippment_pro"
151 | },
152 | {
153 | "fieldname": "section_break_15",
154 | "fieldtype": "Section Break"
155 | },
156 | {
157 | "fieldname": "column_break_14",
158 | "fieldtype": "Column Break"
159 | },
160 | {
161 | "fieldname": "transaction_last_sync",
162 | "fieldtype": "Data",
163 | "label": "Transaction Last Sync",
164 | "read_only": 1
165 | },
166 | {
167 | "fieldname": "column_break_18",
168 | "fieldtype": "Column Break"
169 | },
170 | {
171 | "fieldname": "section_break_20",
172 | "fieldtype": "Section Break"
173 | },
174 | {
175 | "fieldname": "column_break_22",
176 | "fieldtype": "Column Break"
177 | },
178 | {
179 | "fieldname": "section_break_24",
180 | "fieldtype": "Section Break"
181 | },
182 | {
183 | "fieldname": "column_break_27",
184 | "fieldtype": "Column Break"
185 | },
186 | {
187 | "fieldname": "last_shipment_provider_sync",
188 | "fieldtype": "Data",
189 | "label": "Last Shipment Provider Sync",
190 | "read_only": 1
191 | },
192 | {
193 | "fieldname": "section_break_7",
194 | "fieldtype": "Section Break"
195 | },
196 | {
197 | "fieldname": "column_break_10",
198 | "fieldtype": "Column Break"
199 | },
200 | {
201 | "fieldname": "from_date",
202 | "fieldtype": "Date",
203 | "label": "From Date"
204 | },
205 | {
206 | "fieldname": "to_date",
207 | "fieldtype": "Date",
208 | "label": "To Date"
209 | },
210 | {
211 | "fieldname": "authorize_lazada",
212 | "fieldtype": "Button",
213 | "label": "Authorize Lazada"
214 | },
215 | {
216 | "description": "Minimum Sync limit 20 - Maximum Sync Limit 100",
217 | "fieldname": "sync_limit",
218 | "fieldtype": "Int",
219 | "label": "Sync Limit"
220 | },
221 | {
222 | "fieldname": "synced_items",
223 | "fieldtype": "Int",
224 | "label": "Synced Items",
225 | "read_only": 1
226 | },
227 | {
228 | "fieldname": "remaining_items",
229 | "fieldtype": "Int",
230 | "hidden": 1,
231 | "label": "Remaining Items"
232 | },
233 | {
234 | "fieldname": "total_lazada_item",
235 | "fieldtype": "Int",
236 | "hidden": 1,
237 | "label": "Total Lazada Item"
238 | },
239 | {
240 | "description": "Enter the Items You want to fetch from Lazada.\nNote: Enter Seller SKU of Item. Add Item in Comma-separated format.",
241 | "fieldname": "search_item",
242 | "fieldtype": "Small Text",
243 | "label": "Search Item"
244 | },
245 | {
246 | "fieldname": "created_after",
247 | "fieldtype": "Date",
248 | "label": "Created After"
249 | }
250 | ],
251 | "issingle": 1,
252 | "modified": "2021-01-04 20:30:01.268501",
253 | "modified_by": "Administrator",
254 | "module": "Lazada ERPNext Connector",
255 | "name": "Lazada Settings",
256 | "owner": "Administrator",
257 | "permissions": [
258 | {
259 | "create": 1,
260 | "delete": 1,
261 | "email": 1,
262 | "print": 1,
263 | "read": 1,
264 | "role": "System Manager",
265 | "share": 1,
266 | "write": 1
267 | }
268 | ],
269 | "quick_entry": 1,
270 | "sort_field": "modified",
271 | "sort_order": "DESC",
272 | "track_changes": 1
273 | }
274 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/fixtures/custom_field.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "allow_in_quick_entry": 0,
4 | "allow_on_submit": 0,
5 | "bold": 0,
6 | "collapsible": 0,
7 | "collapsible_depends_on": null,
8 | "columns": 0,
9 | "default": null,
10 | "depends_on": null,
11 | "description": null,
12 | "docstatus": 0,
13 | "doctype": "Custom Field",
14 | "dt": "Sales Order Item",
15 | "fetch_from": null,
16 | "fetch_if_empty": 0,
17 | "fieldname": "order_item_id",
18 | "fieldtype": "Data",
19 | "hidden": 0,
20 | "ignore_user_permissions": 0,
21 | "ignore_xss_filter": 0,
22 | "in_global_search": 0,
23 | "in_list_view": 0,
24 | "in_standard_filter": 0,
25 | "insert_after": "item_code",
26 | "label": "Order Item ID",
27 | "length": 0,
28 | "modified": "2020-07-31 21:48:22.672522",
29 | "name": "Sales Order Item-order_item_id",
30 | "no_copy": 0,
31 | "options": null,
32 | "parent": null,
33 | "parentfield": null,
34 | "parenttype": null,
35 | "permlevel": 0,
36 | "precision": "",
37 | "print_hide": 0,
38 | "print_hide_if_no_value": 0,
39 | "print_width": null,
40 | "read_only": 0,
41 | "report_hide": 0,
42 | "reqd": 0,
43 | "search_index": 0,
44 | "translatable": 0,
45 | "unique": 0,
46 | "width": null
47 | },
48 | {
49 | "allow_in_quick_entry": 0,
50 | "allow_on_submit": 0,
51 | "bold": 0,
52 | "collapsible": 0,
53 | "collapsible_depends_on": null,
54 | "columns": 0,
55 | "default": null,
56 | "depends_on": null,
57 | "description": null,
58 | "docstatus": 0,
59 | "doctype": "Custom Field",
60 | "dt": "Item Group",
61 | "fetch_from": null,
62 | "fetch_if_empty": 0,
63 | "fieldname": "lazada_category_name",
64 | "fieldtype": "Data",
65 | "hidden": 0,
66 | "ignore_user_permissions": 0,
67 | "ignore_xss_filter": 0,
68 | "in_global_search": 0,
69 | "in_list_view": 0,
70 | "in_standard_filter": 0,
71 | "insert_after": "item_group_name",
72 | "label": "Lazada Category Name",
73 | "length": 0,
74 | "modified": "2020-07-29 23:59:06.752220",
75 | "name": "Item Group-lazada_category_name",
76 | "no_copy": 0,
77 | "options": null,
78 | "parent": null,
79 | "parentfield": null,
80 | "parenttype": null,
81 | "permlevel": 0,
82 | "precision": "",
83 | "print_hide": 0,
84 | "print_hide_if_no_value": 0,
85 | "print_width": null,
86 | "read_only": 0,
87 | "report_hide": 0,
88 | "reqd": 0,
89 | "search_index": 0,
90 | "translatable": 0,
91 | "unique": 0,
92 | "width": null
93 | },
94 | {
95 | "allow_in_quick_entry": 0,
96 | "allow_on_submit": 0,
97 | "bold": 0,
98 | "collapsible": 0,
99 | "collapsible_depends_on": null,
100 | "columns": 0,
101 | "default": null,
102 | "depends_on": null,
103 | "description": null,
104 | "docstatus": 0,
105 | "doctype": "Custom Field",
106 | "dt": "Delivery Note Item",
107 | "fetch_from": null,
108 | "fetch_if_empty": 0,
109 | "fieldname": "order_item_id",
110 | "fieldtype": "Data",
111 | "hidden": 0,
112 | "ignore_user_permissions": 0,
113 | "ignore_xss_filter": 0,
114 | "in_global_search": 0,
115 | "in_list_view": 0,
116 | "in_standard_filter": 0,
117 | "insert_after": "item_code",
118 | "label": "Order Item ID",
119 | "length": 0,
120 | "modified": "2020-07-31 21:48:59.807423",
121 | "name": "Delivery Note Item-order_item_id",
122 | "no_copy": 0,
123 | "options": null,
124 | "parent": null,
125 | "parentfield": null,
126 | "parenttype": null,
127 | "permlevel": 0,
128 | "precision": "",
129 | "print_hide": 0,
130 | "print_hide_if_no_value": 0,
131 | "print_width": null,
132 | "read_only": 0,
133 | "report_hide": 0,
134 | "reqd": 0,
135 | "search_index": 0,
136 | "translatable": 0,
137 | "unique": 0,
138 | "width": null
139 | },
140 | {
141 | "allow_in_quick_entry": 0,
142 | "allow_on_submit": 0,
143 | "bold": 0,
144 | "collapsible": 0,
145 | "collapsible_depends_on": null,
146 | "columns": 0,
147 | "default": null,
148 | "depends_on": null,
149 | "description": null,
150 | "docstatus": 0,
151 | "doctype": "Custom Field",
152 | "dt": "Sales Invoice Item",
153 | "fetch_from": null,
154 | "fetch_if_empty": 0,
155 | "fieldname": "order_item_id",
156 | "fieldtype": "Data",
157 | "hidden": 0,
158 | "ignore_user_permissions": 0,
159 | "ignore_xss_filter": 0,
160 | "in_global_search": 0,
161 | "in_list_view": 0,
162 | "in_standard_filter": 0,
163 | "insert_after": "item_code",
164 | "label": "Order Item ID",
165 | "length": 0,
166 | "modified": "2020-07-31 21:53:09.179524",
167 | "name": "Sales Invoice Item-order_item_id",
168 | "no_copy": 0,
169 | "options": null,
170 | "parent": null,
171 | "parentfield": null,
172 | "parenttype": null,
173 | "permlevel": 0,
174 | "precision": "",
175 | "print_hide": 0,
176 | "print_hide_if_no_value": 0,
177 | "print_width": null,
178 | "read_only": 0,
179 | "report_hide": 0,
180 | "reqd": 0,
181 | "search_index": 0,
182 | "translatable": 0,
183 | "unique": 0,
184 | "width": null
185 | },
186 | {
187 | "allow_in_quick_entry": 0,
188 | "allow_on_submit": 0,
189 | "bold": 0,
190 | "collapsible": 0,
191 | "collapsible_depends_on": null,
192 | "columns": 0,
193 | "default": null,
194 | "depends_on": null,
195 | "description": null,
196 | "docstatus": 0,
197 | "doctype": "Custom Field",
198 | "dt": "Stock Entry",
199 | "fetch_from": null,
200 | "fetch_if_empty": 0,
201 | "fieldname": "update_on_lazada",
202 | "fieldtype": "Check",
203 | "hidden": 0,
204 | "ignore_user_permissions": 0,
205 | "ignore_xss_filter": 0,
206 | "in_global_search": 0,
207 | "in_list_view": 0,
208 | "in_standard_filter": 0,
209 | "insert_after": "stock_entry_type",
210 | "label": "Update On Lazada",
211 | "length": 0,
212 | "modified": "2020-08-02 11:46:44.842752",
213 | "name": "Stock Entry-update_on_lazada",
214 | "no_copy": 0,
215 | "options": null,
216 | "parent": null,
217 | "parentfield": null,
218 | "parenttype": null,
219 | "permlevel": 0,
220 | "precision": "",
221 | "print_hide": 0,
222 | "print_hide_if_no_value": 0,
223 | "print_width": null,
224 | "read_only": 0,
225 | "report_hide": 0,
226 | "reqd": 0,
227 | "search_index": 0,
228 | "translatable": 0,
229 | "unique": 0,
230 | "width": null
231 | },
232 | {
233 | "allow_in_quick_entry": 0,
234 | "allow_on_submit": 0,
235 | "bold": 0,
236 | "collapsible": 0,
237 | "collapsible_depends_on": null,
238 | "columns": 0,
239 | "default": null,
240 | "depends_on": null,
241 | "description": null,
242 | "docstatus": 0,
243 | "doctype": "Custom Field",
244 | "dt": "Delivery Note",
245 | "fetch_from": null,
246 | "fetch_if_empty": 0,
247 | "fieldname": "shipment_provider",
248 | "fieldtype": "Link",
249 | "hidden": 0,
250 | "ignore_user_permissions": 0,
251 | "ignore_xss_filter": 0,
252 | "in_global_search": 0,
253 | "in_list_view": 0,
254 | "in_standard_filter": 0,
255 | "insert_after": "customer_name",
256 | "label": "Shipment Provider",
257 | "length": 0,
258 | "modified": "2020-07-31 16:17:32.606523",
259 | "name": "Delivery Note-shipment_provider",
260 | "no_copy": 0,
261 | "options": "Shipment Provider",
262 | "parent": null,
263 | "parentfield": null,
264 | "parenttype": null,
265 | "permlevel": 0,
266 | "precision": "",
267 | "print_hide": 0,
268 | "print_hide_if_no_value": 0,
269 | "print_width": null,
270 | "read_only": 0,
271 | "report_hide": 0,
272 | "reqd": 0,
273 | "search_index": 0,
274 | "translatable": 0,
275 | "unique": 0,
276 | "width": null
277 | },
278 | {
279 | "allow_in_quick_entry": 0,
280 | "allow_on_submit": 0,
281 | "bold": 0,
282 | "collapsible": 0,
283 | "collapsible_depends_on": null,
284 | "columns": 0,
285 | "default": null,
286 | "depends_on": null,
287 | "description": null,
288 | "docstatus": 0,
289 | "doctype": "Custom Field",
290 | "dt": "Sales Order",
291 | "fetch_from": null,
292 | "fetch_if_empty": 0,
293 | "fieldname": "cash_direct_sales_name",
294 | "fieldtype": "Data",
295 | "hidden": 0,
296 | "ignore_user_permissions": 0,
297 | "ignore_xss_filter": 0,
298 | "in_global_search": 0,
299 | "in_list_view": 0,
300 | "in_standard_filter": 0,
301 | "insert_after": "customer_name",
302 | "label": "Lazada Customer Name",
303 | "length": 0,
304 | "modified": "2020-08-31 18:42:18.509040",
305 | "name": "Sales Order-cash_direct_sales_name",
306 | "no_copy": 0,
307 | "options": null,
308 | "parent": null,
309 | "parentfield": null,
310 | "parenttype": null,
311 | "permlevel": 0,
312 | "precision": "",
313 | "print_hide": 0,
314 | "print_hide_if_no_value": 0,
315 | "print_width": null,
316 | "read_only": 0,
317 | "report_hide": 0,
318 | "reqd": 0,
319 | "search_index": 0,
320 | "translatable": 0,
321 | "unique": 0,
322 | "width": null
323 | },
324 | {
325 | "allow_in_quick_entry": 0,
326 | "allow_on_submit": 0,
327 | "bold": 0,
328 | "collapsible": 0,
329 | "collapsible_depends_on": null,
330 | "columns": 0,
331 | "default": null,
332 | "depends_on": null,
333 | "description": null,
334 | "docstatus": 0,
335 | "doctype": "Custom Field",
336 | "dt": "Delivery Note",
337 | "fetch_from": null,
338 | "fetch_if_empty": 0,
339 | "fieldname": "lazada_order_id",
340 | "fieldtype": "Data",
341 | "hidden": 0,
342 | "ignore_user_permissions": 0,
343 | "ignore_xss_filter": 0,
344 | "in_global_search": 0,
345 | "in_list_view": 0,
346 | "in_standard_filter": 0,
347 | "insert_after": "shipment_provider",
348 | "label": "Lazada Order ID",
349 | "length": 0,
350 | "modified": "2020-11-25 20:34:10.553211",
351 | "name": "Delivery Note-lazada_order_id",
352 | "no_copy": 0,
353 | "options": null,
354 | "parent": null,
355 | "parentfield": null,
356 | "parenttype": null,
357 | "permlevel": 0,
358 | "precision": "",
359 | "print_hide": 0,
360 | "print_hide_if_no_value": 0,
361 | "print_width": null,
362 | "read_only": 0,
363 | "report_hide": 0,
364 | "reqd": 0,
365 | "search_index": 0,
366 | "translatable": 0,
367 | "unique": 0,
368 | "width": null
369 | },
370 | {
371 | "allow_in_quick_entry": 0,
372 | "allow_on_submit": 0,
373 | "bold": 0,
374 | "collapsible": 0,
375 | "collapsible_depends_on": null,
376 | "columns": 0,
377 | "default": null,
378 | "depends_on": null,
379 | "description": null,
380 | "docstatus": 0,
381 | "doctype": "Custom Field",
382 | "dt": "Sales Order",
383 | "fetch_from": null,
384 | "fetch_if_empty": 0,
385 | "fieldname": "lazada_order_id",
386 | "fieldtype": "Data",
387 | "hidden": 0,
388 | "ignore_user_permissions": 0,
389 | "ignore_xss_filter": 0,
390 | "in_global_search": 0,
391 | "in_list_view": 0,
392 | "in_standard_filter": 0,
393 | "insert_after": "order_type",
394 | "label": "Lazada Order ID",
395 | "length": 0,
396 | "modified": "2020-11-25 20:33:40.761037",
397 | "name": "Sales Order-lazada_order_id",
398 | "no_copy": 0,
399 | "options": null,
400 | "parent": null,
401 | "parentfield": null,
402 | "parenttype": null,
403 | "permlevel": 0,
404 | "precision": "",
405 | "print_hide": 0,
406 | "print_hide_if_no_value": 0,
407 | "print_width": null,
408 | "read_only": 1,
409 | "report_hide": 0,
410 | "reqd": 0,
411 | "search_index": 0,
412 | "translatable": 0,
413 | "unique": 0,
414 | "width": null
415 | },
416 | {
417 | "allow_in_quick_entry": 0,
418 | "allow_on_submit": 0,
419 | "bold": 0,
420 | "collapsible": 0,
421 | "collapsible_depends_on": null,
422 | "columns": 0,
423 | "default": null,
424 | "depends_on": null,
425 | "description": null,
426 | "docstatus": 0,
427 | "doctype": "Custom Field",
428 | "dt": "Sales Invoice",
429 | "fetch_from": null,
430 | "fetch_if_empty": 0,
431 | "fieldname": "je_created",
432 | "fieldtype": "Check",
433 | "hidden": 0,
434 | "ignore_user_permissions": 0,
435 | "ignore_xss_filter": 0,
436 | "in_global_search": 0,
437 | "in_list_view": 0,
438 | "in_standard_filter": 0,
439 | "insert_after": "is_return",
440 | "label": "JE Created",
441 | "length": 0,
442 | "modified": "2020-08-21 19:57:35.636165",
443 | "name": "Sales Invoice-je_created",
444 | "no_copy": 0,
445 | "options": null,
446 | "parent": null,
447 | "parentfield": null,
448 | "parenttype": null,
449 | "permlevel": 0,
450 | "precision": "",
451 | "print_hide": 0,
452 | "print_hide_if_no_value": 0,
453 | "print_width": null,
454 | "read_only": 0,
455 | "report_hide": 0,
456 | "reqd": 0,
457 | "search_index": 0,
458 | "translatable": 0,
459 | "unique": 0,
460 | "width": null
461 | }
462 | ]
463 |
--------------------------------------------------------------------------------
/lazada_erpnext_connector/lazada_erpnext_connector/doctype/lazada_settings/lazada_settings.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Copyright (c) 2020, Raaj Tailor and contributors
3 | # For license information, please see license.txt
4 |
5 | from __future__ import unicode_literals
6 | import frappe
7 | from frappe.model.document import Document
8 | import requests
9 | import time
10 | import hmac
11 | import hashlib
12 | import json
13 | import mimetypes
14 | import itertools
15 | import random
16 | import logging
17 | import os
18 | from os.path import expanduser
19 | import socket
20 | import platform
21 | from datetime import datetime
22 | from frappe.utils import now,getdate,add_days
23 | from frappe import enqueue
24 | from lazada_erpnext_connector.utils.lazada_utils import LazopClient,LazopRequest,LazopResponse
25 |
26 |
27 | class LazadaSettings(Document):
28 |
29 | def get_access_token(self):
30 | auth = Authentication()
31 | auth.get_access_token()
32 | def get_refresh_token(self):
33 | auth = Authentication()
34 | auth.get_refresh_token()
35 | def get_products(self):
36 | prod = Products()
37 | prod.create_erpnext_items()
38 | def get_orders(self):
39 | ord = Orders()
40 | ord.create_erpnext_order()
41 | def get_transactions(self):
42 | trans = Transaction()
43 | trans.create_erpnext_jornal_entry()
44 | def get_shippment_pro(self):
45 | ship_pro = Delivery()
46 | frappe.msgprint(str(ship_pro.get_shippment_provider()))
47 |
48 | # *****************************************************************************************************************
49 | # Defaults Global Variables
50 | # *****************************************************************************************************************
51 |
52 | def get_pw(doctype,field_name):
53 | docSettings = frappe.get_single(doctype)
54 | strPassword = docSettings.get_password(field_name)
55 | return strPassword
56 |
57 | # try:
58 | # # api_key = frappe.db.get_value("Lazada Settings",None,"api_key")
59 | # # api_secret = get_pw("Lazada Settings","api_secret")
60 | # # access_token = get_pw("Lazada Settings","access_token")
61 | # # url = frappe.db.get_value("Lazada Settings",None,"url")
62 | # except Exception as e:
63 | # print(e)
64 | # pass
65 |
66 | # *****************************************************************************************************************
67 | # API Functions Classes
68 | # *****************************************************************************************************************
69 |
70 | class Products(LazadaSettings):
71 | def __init__(self):
72 | self.api_key = frappe.db.get_value("Lazada Settings",None,"api_key")
73 | self.api_secret = get_pw("Lazada Settings","api_secret")
74 | self.url = frappe.db.get_value("Lazada Settings",None,"url")
75 | self.last_sync_prod = frappe.db.get_value("Lazada Settings",None,"product_last_sync")
76 | self.sync_limit = frappe.db.get_value("Lazada Settings",None,"sync_limit")
77 | self.synced_items = frappe.db.get_value("Lazada Settings",None,"synced_items")
78 | self.created_after = frappe.db.get_value("Lazada Settings",None,"created_after")
79 | self.search_item = frappe.db.get_value("Lazada Settings",None,"search_item")
80 | self.access_token = get_pw("Lazada Settings","access_token")
81 |
82 | def get_all_products(self,limit,offset):
83 | client = LazopClient(self.url, self.api_key ,self.api_secret)
84 | request = LazopRequest('/products/get','GET')
85 | request.add_api_param('filter', 'all')
86 | request.add_api_param('offset', offset)
87 | request.add_api_param('limit', limit)
88 |
89 | if self.search_item:
90 | sku_list = json.dumps(self.search_item.split(","))
91 | frappe.msgprint(str(sku_list))
92 | request.add_api_param('sku_seller_list', sku_list)
93 |
94 | if self.created_after:
95 | created_after = datetime.strptime(str(self.created_after),"%Y-%m-%d").isoformat()
96 | request.add_api_param('create_after', created_after)
97 |
98 | response = client.execute(request, self.access_token)
99 | if response.code != '0':
100 | # frappe.msgprint("Call is not sucessful")
101 | create_error_log('/products/get',response.code,response.message)
102 | frappe.msgprint("There is some error while creating Items. Please Check Lazada Error Log!")
103 | return False
104 | else:
105 | # frappe.msgprint(str(response.code))
106 | # frappe.msgprint(str(response.body))
107 | if bool(response.body['data']):
108 | return (response.body['data']['total_products'],response.body)
109 | else:
110 | frappe.msgprint("No Item Found to Sync!")
111 | frappe.db.set_value("Lazada Settings",None,"synced_items",0)
112 | return False
113 |
114 | # frappe.msgprint(str(bool(response.body['data'])))
115 |
116 |
117 |
118 |
119 | def create_erpnext_items(self):
120 | lazada_product = self.get_all_products(self.sync_limit,self.synced_items)
121 | # frappe.throw(str(lazada_product))
122 | if lazada_product:
123 | # frappe.db.set_value("Lazada Settings",None,"total_lazada_item",int(lazada_product[0]))
124 | products = lazada_product[1]
125 |
126 | if products and products['data']:
127 | count = 0
128 | for product in products['data']['products']:
129 | for sku in product['skus']:
130 | count = count + 1
131 | if not frappe.db.exists("Item", sku['SellerSku']):
132 | if not frappe.db.exists("Item Group", product['primary_category']):
133 | item_group = frappe.new_doc("Item Group")
134 | item_group.item_group_name = str(product['primary_category'])
135 | item_group.is_group = 0
136 | item_group.parent_item_group = "Lazada Item Category"
137 | item_group.insert(ignore_permissions=True)
138 |
139 | item_doc = frappe.new_doc("Item")
140 | item_doc.item_code = str(sku['SellerSku'])
141 | item_doc.item_name = product['attributes']['name']
142 | if 'short_description' in (product['attributes'].keys()):
143 | item_doc.description = product['attributes']['short_description']
144 | item_doc.item_group = product['primary_category']
145 | item_doc.stock_uom = "Nos"
146 | item_doc.is_stock_item = 1
147 | item_doc.valuation_rate = 1
148 | item_doc.opening_stock = sku['quantity']
149 | item_doc.insert(ignore_permissions=True)
150 | item_doc.item_defaults = [{
151 | "company":frappe.db.get_value("Global Defaults",None,"default_company"),
152 | "default_warehouse":frappe.db.get_value("Lazada Defaults",None,"default_warehouse")
153 | }]
154 | frappe.msgprint(str(item_doc.name)+" Created!")
155 | frappe.db.set_value("Lazada Settings",None,"product_last_sync",datetime.now().replace(microsecond=0).isoformat())
156 |
157 | else:
158 | frappe.msgprint("Item {} is already created".format(sku['SellerSku']))
159 | frappe.db.set_value("Lazada Settings",None,"synced_items",int(frappe.db.get_value("Lazada Settings",None,"synced_items")) + count)
160 | # frappe.db.set_value("Lazada Settings",None,"remaining_items",int(frappe.db.get_value("Lazada Settings",None,"total_lazada_item")) -int(frappe.db.get_value("Lazada Settings",None,"synced_items")))
161 |
162 | # else:
163 | # frappe.msgprint("There is some error while creating Items. Please Check Lazada Error Log!")
164 |
165 | class Delivery(object):
166 | def __init__(self):
167 | self.api_key = frappe.db.get_value("Lazada Settings",None,"api_key")
168 | self.api_secret = get_pw("Lazada Settings","api_secret")
169 | self.access_token = get_pw("Lazada Settings","access_token")
170 | self.url = frappe.db.get_value("Lazada Settings",None,"url")
171 | # pass
172 | def get_shippment_provider(self):
173 | client = LazopClient(self.url, self.api_key ,self.api_secret)
174 | request = LazopRequest('/shipment/providers/get','GET')
175 |
176 | response = client.execute(request, self.access_token)
177 | data = response.body['data']['shipment_providers']
178 | for ship in data:
179 | shipment_provider = {
180 | "doctype":"Shipment Provider",
181 | "shipment_provider":ship['name'],
182 | "is_cod":ship['cod']
183 | }
184 | if not frappe.db.exists("Shipment Provider", ship['name']):
185 | frappe.get_doc(shipment_provider).insert(ignore_permissions=True)
186 | frappe.db.set_value("Lazada Settings",None,"last_shipment_provider_sync",datetime.now().replace(microsecond=0).isoformat())
187 | return response.body
188 | # print(response.type)
189 | # print(response.body)
190 |
191 | class Orders(object):
192 | def __init__(self):
193 | self.api_key = frappe.db.get_value("Lazada Settings",None,"api_key")
194 | self.api_secret = get_pw("Lazada Settings","api_secret")
195 | self.access_token = get_pw("Lazada Settings","access_token")
196 | self.default_customer = frappe.db.get_value("Lazada Defaults",None,"customer")
197 | self.default_warehouse = frappe.db.get_value("Lazada Defaults",None,"default_warehouse")
198 | self.last_sync = frappe.db.get_value("Lazada Settings",None,"order_last_sync")
199 | self.url = frappe.db.get_value("Lazada Settings",None,"url")
200 |
201 | def get_all_orders(self):
202 | client = LazopClient(self.url, self.api_key ,self.api_secret)
203 | request = LazopRequest('/orders/get','GET')
204 | if self.last_sync:
205 | request.add_api_param('created_after', self.last_sync)
206 | request.add_api_param('status', 'pending')
207 | request.add_api_param('limit', 99)
208 | request.add_api_param('sort_direction', 'DESC')
209 | # frappe.msgprint(str(access_token))
210 | response = client.execute(request,self.access_token)
211 | # frappe.msgprint(str(response.type))
212 | # frappe.msgprint(str(response.body))
213 | if response.code != '0':
214 | # frappe.msgprint("Call is not sucessful")
215 | create_error_log('/orders/get',response.code,response.message)
216 | return False
217 | else:
218 | # frappe.msgprint(str(response.code))
219 | # frappe.msgprint(str(response.body))
220 | return response.body
221 |
222 |
223 | def get_order_items(self,order_id):
224 | client = LazopClient(self.url, self.api_key ,self.api_secret)
225 | request = LazopRequest('/orders/items/get','GET')
226 | request.add_api_param('order_ids', order_id)
227 | response = client.execute(request, self.access_token)
228 | if response.code != '0':
229 | # frappe.msgprint("Call is not sucessful")
230 | create_error_log('/orders/items/get',response.code,response.message)
231 | return False
232 | else:
233 | # frappe.msgprint(str(response.code))
234 | # frappe.msgprint(str(response))
235 | # res_body = response.body
236 | return response.body
237 | # return response.body
238 |
239 |
240 |
241 | def create_erpnext_order(self):
242 | orders_list = self.get_all_orders()
243 | orders_ids=[]
244 | if orders_list:
245 | for order in orders_list['data']['orders']:
246 | orders_ids.append(str(order['order_id']))
247 | order_items = self.get_order_items(str(orders_ids))
248 | if order_items:
249 | for order in orders_list['data']['orders']:
250 | for order_item in order_items['data']:
251 | if order['order_id'] == order_item['order_id']:
252 | items = []
253 | for item in order_item['order_items']:
254 | items.append({
255 | "item_code":item['sku'],
256 | "item_name":item["name"],
257 | "rate":item['item_price'],
258 | "qty":1,
259 | "order_item_id":item['order_item_id']
260 | })
261 | sales_order = {
262 | "doctype":"Sales Order",
263 | "customer":self.default_customer,
264 | "set_warehouse":self.default_warehouse,
265 | "transaction_date":getdate(datetime.strptime(order['created_at'], "%Y-%m-%d %H:%M:%S %z")),
266 | "delivery_date":add_days(getdate(datetime.strptime(order['created_at'], "%Y-%m-%d %H:%M:%S %z")),2),
267 | "lazada_order_id":order['order_id'],
268 | "po_no":order['order_number'],
269 | "items":items,
270 | "cash_direct_sales_name":order['address_shipping']['first_name'],
271 | "order_type":"Sales"}
272 | if not frappe.db.exists("Sales Order", frappe.db.get_value("Sales Order",{"po_no":order['order_number']},"name")):
273 | # frappe.msgprint(str(items))
274 | # frappe.msgprint(str(sales_order))
275 | res_doc = frappe.get_doc(sales_order).insert(ignore_permissions=True)
276 | frappe.msgprint("Sales Order Created {}".format(res_doc.name))
277 |
278 | frappe.db.set_value("Lazada Settings",None,"order_last_sync",datetime.now().replace(microsecond=0).isoformat())
279 |
280 | class OrdersDoc(object):
281 | def __init__(self):
282 | self.api_key = frappe.db.get_value("Lazada Settings",None,"api_key")
283 | self.api_secret = get_pw("Lazada Settings","api_secret")
284 | self.access_token = get_pw("Lazada Settings","access_token")
285 | self.url = frappe.db.get_value("Lazada Settings",None,"url")
286 |
287 | def get_oreder_doc(self,order_item_ids):
288 | client = LazopClient(self.url, self.api_key ,self.api_secret)
289 | request = LazopRequest('/order/document/get','GET')
290 | request.add_api_param('doc_type', 'invoice')
291 | request.add_api_param('order_item_ids', order_item_ids)
292 |
293 | response = client.execute(request, self.access_token)
294 | # frappe.msgprint(str(response.type))
295 | # frappe.msgprint(str(response.body))
296 | return response.body
297 |
298 | def attach_to_erpnext_invoice(self):
299 | pass
300 |
301 | class Transaction(object):
302 | def __init__(self):
303 | self.api_key = frappe.db.get_value("Lazada Settings",None,"api_key")
304 | self.api_secret = get_pw("Lazada Settings","api_secret")
305 | self.access_token = get_pw("Lazada Settings","access_token")
306 | self.company = frappe.db.get_value("Global Defaults",None,"default_company")
307 | self.cash_account = frappe.db.get_value("Company",self.company,"default_cash_account")
308 | self.receivalble = frappe.db.get_value("Company",self.company,"default_receivable_account")
309 | self.customer = frappe.db.get_value("Lazada Defaults",None,"customer")
310 | self.last_transc_sync = frappe.db.get_value("Lazada Defaults",None,"transaction_last_sync")
311 | self.from_date = frappe.db.get_value("Lazada Settings",None,"from_date")
312 | self.to_date = frappe.db.get_value("Lazada Settings",None,"to_date")
313 | self.url = frappe.db.get_value("Lazada Settings",None,"url")
314 |
315 | def get_all_transaction(self):
316 | # frappe.msgprint(str(self.from_date))
317 | # frappe.throw(str(self.to_date))
318 | if not self.from_date or not self.to_date:
319 | frappe.throw("Please Enter From Date and To Date to get Transaction.")
320 | client = LazopClient(self.url, self.api_key ,self.api_secret)
321 | request = LazopRequest('/finance/transaction/detail/get','GET')
322 | request.add_api_param('trans_type', '13')
323 | request.add_api_param('end_time', str(self.to_date))
324 | request.add_api_param('start_time',str(self.from_date))
325 | response = client.execute(request, self.access_token)
326 | # frappe.msgprint(str(response.type))
327 | # frappe.msgprint(str(response.body))
328 | return response.body
329 |
330 | def create_erpnext_jornal_entry(self):
331 | transaction_list = self.get_all_transaction()
332 | account_entry = []
333 | invoice_list = []
334 |
335 | for transc in transaction_list['data']:
336 | sales_invoice = frappe.db.get_value("Sales Invoice",{"po_no":transc["order_no"],"je_created":0},"name")
337 | if sales_invoice:
338 | account_entry.append({
339 | "account":self.receivalble,
340 | "party_type":"Customer",
341 | "party":self.customer,
342 | "credit_in_account_currency":float(transc['amount']),
343 | "reference_type":"Sales Invoice",
344 | "reference_name":sales_invoice
345 | })
346 | account_entry.append({
347 | "account":self.cash_account,
348 | "debit_in_account_currency":float(transc['amount']),
349 |
350 | })
351 | invoice_list.append(sales_invoice)
352 |
353 | if len(account_entry) != 0:
354 | frappe.msgprint(str(account_entry))
355 | self.creat_je(account_entry,invoice_list)
356 | frappe.db.set_value("Lazada Settings",None,"transaction_last_sync",datetime.now().replace(microsecond=0).isoformat())
357 |
358 | def creat_je(self,account_entry,invoice_list):
359 | je_doc ={
360 | "doctype":"Journal Entry",
361 | "voucher_type":"Journal Entry",
362 | "posting_date":frappe.utils.now(),
363 | "accounts":account_entry
364 | }
365 | frappe.get_doc(je_doc).insert(ignore_permissions=True)
366 |
367 | for inv in invoice_list:
368 | frappe.db.set_value("Sales Invoice",inv,"je_created",1)
369 | frappe.msgprint("Payment Created For Invoice {}".format(inv))
370 |
371 | class Authentication(object):
372 | def __init__(self):
373 | self.api_key = frappe.db.get_value("Lazada Settings",None,"api_key")
374 | self.api_secret = get_pw("Lazada Settings","api_secret")
375 | self.url = frappe.db.get_value("Lazada Settings",None,"url")
376 | # self.access_token = get_pw("Lazada Settings","access_token")
377 | self.callback_url = frappe.db.get_value("Lazada Settings",None,"callback_url")
378 |
379 |
380 | def get_code(self):
381 | res = frappe.db.get_value("Lazada Settings",None,"code")
382 | # res = requests.get("https://auth.lazada.com/oauth/authorize?response_type=code&force_auth=true&redirect_uri={call_back_url}&client_id={appkey}".format(call_back_url=self.callback_url,appkey=self.api_key))
383 | # frappe.msgprint(str(res))
384 | return res
385 |
386 | def get_access_token(self):
387 | client = LazopClient("https://auth.lazada.com/rest", self.api_key ,self.api_secret)
388 | request = LazopRequest('/auth/token/create')
389 | request.add_api_param("code", self.get_code())
390 | response = client.execute(request)
391 | # frappe.msgprint(str(response.body))
392 | if response.body['code'] != '0':
393 | frappe.msgprint("Access token is Already Generated. Please Use Refresh Token Button!")
394 | else:
395 | frappe.db.set_value("Lazada Settings",None,"access_token",response.body["access_token"])
396 | frappe.db.set_value("Lazada Settings",None,"refresh_token",response.body['refresh_token'])
397 | frappe.msgprint("Access Token has been successfully Genrated. Please Reload Page.")
398 |
399 | def get_refresh_token(self):
400 | refresh_t = get_pw("Lazada Settings","refresh_token")
401 | client = LazopClient("https://auth.lazada.com/rest", self.api_key ,self.api_secret)
402 | request = LazopRequest('/auth/token/refresh')
403 | request.add_api_param("refresh_token", refresh_t)
404 | response = client.execute(request)
405 | # frappe.msgprint(str(response.body))
406 | # frappe.msgprint(str(now()))
407 | if response.body['code'] == '0':
408 | frappe.db.set_value("Lazada Settings",None,"access_token",response.body["access_token"])
409 | frappe.db.set_value("Lazada Settings",None,"refresh_token",response.body['refresh_token'])
410 | frappe.db.set_value("Lazada Settings",None,"last_sync_access_token",now())
411 | frappe.msgprint("Access Token has been refreshed successfully. Please Reload Page!")
412 | else:
413 | frappe.msgprint("Error Occured While Refreshing Acces token.")
414 |
415 | # *********************************************************************************************************************
416 | # FunctionS called By Scheduler
417 | # *********************************************************************************************************************
418 |
419 | def create_error_log(call,error_code,error):
420 | doc = frappe.new_doc("Lazada Connector Error Log")
421 | doc.call=call
422 | doc.error_code=error_code
423 | doc.error_log=error
424 | doc.insert(ignore_permissions=True)
425 |
426 | frappe.whitelist()
427 | def get_refresh():
428 | auth = Authentication()
429 | auth.get_refresh_token()
430 |
431 | frappe.whitelist()
432 | def get_orders():
433 | ord = Orders()
434 | ord.create_erpnext_order()
435 |
436 | frappe.whitelist()
437 | def get_items_back():
438 | prod = Products()
439 | prod.create_erpnext_items()
440 |
441 |
442 |
443 |
--------------------------------------------------------------------------------