├── .env
├── .gitignore
├── .vscode
├── extensions.json
├── launch.json
├── settings.json
└── tasks.json
├── README.md
├── client
├── .env
├── .gitignore
├── README.md
├── babel.config.js
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ └── staticwebapp.config.json
├── src
│ ├── App.vue
│ ├── assets
│ │ ├── images
│ │ │ ├── tc-logo.png
│ │ │ └── yellow-pillow-bedside-table_1920x.jpg
│ │ ├── logo.png
│ │ └── style.css
│ ├── auth
│ │ ├── authGuard.js
│ │ └── index.js
│ ├── components
│ │ ├── Footer.vue
│ │ └── Header.vue
│ ├── main.js
│ ├── plugins
│ │ └── vuetify.js
│ ├── router
│ │ └── index.js
│ ├── services
│ │ ├── consignorService.js
│ │ ├── payoutService.js
│ │ └── productService.js
│ ├── store
│ │ └── index.js
│ └── views
│ │ ├── ConsignorDatatable.vue
│ │ ├── ConsignorDetail.vue
│ │ ├── Consignors.vue
│ │ ├── CreateConsignor.vue
│ │ ├── CreateProduct.vue
│ │ ├── Datatable.vue
│ │ ├── Home.vue
│ │ ├── PayoutDatatable.vue
│ │ ├── PayoutDetail.vue
│ │ ├── Payouts.vue
│ │ ├── ProductDatatable.vue
│ │ ├── ProductDetail.vue
│ │ ├── Products.vue
│ │ └── ProductsByVendor.vue
└── yarn.lock
├── database
├── config.js
└── db.js
├── db_backup
├── 2021-08-18-tconsigndb.bacpac
├── 2021-08-19_backup.bacpac
└── 2021-08-22-backup.bak
├── middleware
├── auth.js
└── permission.js
├── models
├── consignor-model.js
├── order-model.js
├── payout-model.js
└── product-model.js
├── package-lock.json
├── package.json
├── public
└── products
│ ├── photo_2021-08-19_18-51-02.jpg
│ └── photo_2021-08-19_18-51-12.jpg
├── routes
├── consignors.js
├── index.js
├── orders.js
├── payouts.js
└── products.js
├── server.js
├── server
├── .env
├── .gitignore
├── database
│ ├── config.js
│ └── db.js
├── middleware
│ ├── auth.js
│ └── permission.js
├── models
│ ├── consignor-model.js
│ ├── order-model.js
│ ├── payout-model.js
│ └── product-model.js
├── package-lock.json
├── package.json
├── public
│ └── products
│ │ ├── photo_2021-08-19_18-51-02.jpg
│ │ └── photo_2021-08-19_18-51-12.jpg
├── routes
│ ├── consignors.js
│ ├── index.js
│ ├── orders.js
│ ├── payouts.js
│ └── products.js
├── server.js
├── services
│ ├── consignorService.js
│ ├── orderService.js
│ ├── payoutService.js
│ ├── productService.js
│ └── shopify.js
└── yarn.lock
├── services
├── consignorService.js
├── orderService.js
├── payoutService.js
├── productService.js
└── shopify.js
├── theme_source
├── figma-ui-kit-main.zip
└── materio-v1.0.zip
└── yarn.lock
/.env:
--------------------------------------------------------------------------------
1 | # MSSQL config
2 | DB_HOST=tconsign21.database.windows.net
3 | DB_USER=tcadmin
4 | DB_PASS=Over 12,000 sq. ft. of finds!
5 | DB_NAME=tconsign
6 | PORT=8000
7 |
8 | # Auth0 config
9 | AUTH0_DOMAIN=eclectico.us.auth0.com
10 | AUTH0_AUDIENCE=https://tacomaconsignment.com
11 |
12 | # Azure blob config
13 | AZURE_ACCOUNT_NAME=cs410032000dc000ac4
14 | AZURE_ACCOUNT_KEY=Rk5OZVd7RIUSZjHt1yg/YGRVgnf+NzM33hyNWvC3SOJQgiPBktph+G9DBTN+jPQzP+3cCCdutyYg1cbKGoIUrw==
15 | AZURE_BLOB_URL=https://cs410032000dc000ac4.blob.core.windows.net
16 | AZURE_CONTAINER_NAME=testcontainer
17 |
18 | # Shopify config
19 | SHOPIFY_API_KEY=fa4f8443ab7b37f4803230a8aebbb7b2
20 | SHOPIFY_PASSWORD=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
21 | SHOPIFY_SHOP_NAME=spfy-connection-app-store.myshopify.com
22 | SHOPIFY_ACCESS_TOKEN=prtapi_66df9304cda675601c68025aeac9a208
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/Release
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # TypeScript v1 declaration files
45 | typings/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Microbundle cache
57 | .rpt2_cache/
58 | .rts2_cache_cjs/
59 | .rts2_cache_es/
60 | .rts2_cache_umd/
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | .env.test
73 |
74 | # parcel-bundler cache (https://parceljs.org/)
75 | .cache
76 |
77 | # Next.js build output
78 | .next
79 |
80 | # Nuxt.js build / generate output
81 | .nuxt
82 | dist
83 |
84 | # Gatsby files
85 | .cache/
86 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
87 | # https://nextjs.org/blog/next-9-1#public-directory-support
88 | # public
89 |
90 | # vuepress build output
91 | .vuepress/dist
92 |
93 | # Serverless directories
94 | .serverless/
95 |
96 | # FuseBox cache
97 | .fusebox/
98 |
99 | # DynamoDB Local files
100 | .dynamodb/
101 |
102 | # TernJS port file
103 | .tern-port
104 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "ms-azuretools.vscode-azurefunctions"
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | "name": "Attach to Node Functions",
6 | "type": "node",
7 | "request": "attach",
8 | "port": 9229,
9 | "preLaunchTask": "func: host start"
10 | }
11 | ]
12 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "azureFunctions.deploySubpath": "api",
3 | "azureFunctions.postDeployTask": "npm install (functions)",
4 | "azureFunctions.projectLanguage": "JavaScript",
5 | "azureFunctions.projectRuntime": "~3",
6 | "debug.internalConsoleOptions": "neverOpen",
7 | "azureFunctions.preDeployTask": "npm prune (functions)",
8 | "appService.defaultWebAppToDeploy": "/subscriptions/45a29aab-8b41-4d5a-8809-08ed170c5b7d/resourceGroups/appsvc_linux_centralus_premium/providers/Microsoft.Web/sites/tconsign-appservice",
9 | "appService.deploySubpath": "."
10 | }
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "2.0.0",
3 | "tasks": [
4 | {
5 | "type": "func",
6 | "command": "host start",
7 | "problemMatcher": "$func-node-watch",
8 | "isBackground": true,
9 | "dependsOn": "npm install (functions)",
10 | "options": {
11 | "cwd": "${workspaceFolder}/server"
12 | }
13 | },
14 | {
15 | "type": "shell",
16 | "label": "npm install (functions)",
17 | "command": "npm install",
18 | "options": {
19 | "cwd": "${workspaceFolder}/server"
20 | }
21 | },
22 | {
23 | "type": "shell",
24 | "label": "npm prune (functions)",
25 | "command": "npm prune --production",
26 | "problemMatcher": [],
27 | "options": {
28 | "cwd": "${workspaceFolder}/server"
29 | }
30 | }
31 | ]
32 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Tacoma Consignment Project Overview
2 |
3 | Tacoma Consignment is a "brick-and-mortar" retail consignment business specializing in furniture and art. It is transitioning from a in-person based Quickbooks POS system to a joint online/in-person commerce system based on the following technologies:
4 |
5 | * Shopify (eCommerce and POS)
6 | * Stripe for consignor payout
7 | * Azure SQL Server as master database and "source of truth" (open to discussion, but relational db preferred)
8 | * Auth0 for identity management of:
9 | * consignors
10 | * customers
11 | * store staff
12 | * store admins
13 | * Vuetify as a web front-end
14 | * Segment for referral tracking and customer insights
15 | * Axios for API management
16 | * Mailchimp for email management and marketing campaigns
17 |
18 | ## MVP Feature Overview
19 |
20 | The core system needs to enable the following roles and activities:
21 |
22 | * Vuetify front-end based Store management single-page application including product onboarding with proper commission attribution and financial treatment of vendors and consignors
23 | * Product creation page and product-image upload via Vuetify web front-end, published to Shopify
24 | * Wishlist management via customer signup (Vuetify front-end) and product tagging on Shopify website
25 | * Print QR-code based product tag with product description, price, sku on Zebra, Epson, or other wireless label printer
26 | * Open-ended wishlist form analogous to product creation flow
27 | * Customer signup flow that uses [Auth0](https://auth0.com/docs/quickstart/spa/vuejs) Shopify and other social connectors (Google, Facebook, Amazon, and [magic email links](https://auth0.com/docs/connections/passwordless/guides/email-magic-link)) to authorize customer, create an account in Azure and publish the results to appropriate Shopify and Mailchimp campaigns
28 | * New accounts trigger appropriate discount assignments and Mailchimp campaigncustomer discount via mailchimp email signup
29 | * Customer management including authentication via Auth0, referral tracking via Segment, and appropriate updating of relevant Mailchimp campaigns
30 | * New consignor onboarding system, including invite system to transition existing merchants to new portal and payout alternatives
31 | * commission structures
32 | * active and sold products
33 | * billing address
34 | * PDF versions of contracts
35 | * Vendor and consignor payout via automated payout on Stripe or manual checks generated from a PDF template and printed; Azure system must enforce proper accounting
36 | * Synching transactions within and across systems:
37 | * Products, consignors, and staff store management functionality within Azure
38 | * Automated synchronization with Shopify via Webhooks
39 | * Communicate with web front-end via Vuetify/Axios/Azure/Auth0
40 | * Job execution of automatic discounting functionality
41 | * Publishing and synching data to Shopify via Shopify REST (or Graph) API
42 |
43 | The Tacoma Consignment SQL Server database is the source of truth for all data. To do so it has to also capture all the external transactions that occur in the Shopify and Stripe systems, as well as integrate into the Vuetify front-end to enable the management of the store.
44 |
45 |
46 | ## Project setup
47 |
48 | First, clone this repo and switch into the repo folder:
49 |
50 | ```bash
51 | git clone git@github.com:auth0-blog/vue-express-auth.git
52 | cd vue-express-auth
53 | ```
54 |
55 | Now you need to install the dependencies for the client and server code.
56 |
57 | ### Set up the Express server
58 |
59 | ```bash
60 | cd server
61 | npm install
62 | ```
63 |
64 | ### Set up the Vue client
65 |
66 | In a new terminal tab:
67 |
68 | ```bash
69 | cd ../client
70 | npm install
71 | ```
72 |
73 | Now click into "Settings" and fill in some information that Auth0 needs to configure authentication:
74 |
75 | **Allowed Callback URLs** — `http://localhost:8080`
76 |
77 | **Allowed Logout URLs** — `http://localhost:8080`
78 |
79 | **Allowed Web Origins** — `http://localhost:8080`
80 |
81 | Scroll down and click "Save Changes".
82 |
83 | ### Create the Auth0 API
84 |
85 | Next, click on "APIs" on the left menu. Click "Create API" and call it "Vue Express API" (or anything you'd like). For "Identifier", we recommend a URL such as `https://vue-express-api.com`. It doesn't have to be a publicly available URL and we'll never call it, it's just for naming purposes. You can leave "Signing algorithm" as is and then press "Create".
86 |
87 | That's all you need from the dashboard for now, but don't click out yet. You'll need to pull some of these values from the dashboard into your application soon.
88 |
89 | In the `client` directory, create a file for the config values:
90 |
91 | ```bash
92 | touch auth_config.json
93 | ```
94 |
95 | > **Important:** Make sure you add `auth_config.json` to your `.gitignore` file!
96 |
97 | ### Connecting with Auth0
98 |
99 | Now open up `auth_config.json` and paste in:
100 |
101 | ```js
102 | {
103 | "domain": "your-domain.auth0.com",
104 | "clientId": "your-client-id",
105 | "audience": "https://your-identifier.com"
106 | }
107 | ```
108 |
109 | **Finding your `auth_config` values:**
110 |
111 | * Head to the [Auth0 dashboard](https://manage.auth0.com/dashboard)
112 | * Click on "APIs" and select your API
113 | * Copy the value for "Identifier" and paste it into `audience` in `auth_config.json`
114 | * Click on "Applications" and select your application (Vue Events)
115 | * Click on "Settings"
116 | * Copy the value for "Domain" and paste it into `domain` in `auth_config.json`
117 | * Copy the value for "Client ID" and paste it into `clientId` in `auth_config.json`
118 |
119 | Now you should be able to sign in to the application, but you still won't be able to access single event details because you need to add this information to the server side where the API access token is validated.
120 |
121 | Open up `server/server.js` and find:
122 |
123 | ```js
124 | const authConfig = {
125 | domain: "YOUR-DOMAIN",
126 | audience: "YOUR-IDENTIFIER"
127 | };
128 | ```
129 |
130 | Replace the `domain` and `audience` placeholders with the values listed above.
131 |
132 | ### Testing the app
133 |
134 | Now that everything is set up, you can test the app.
135 |
136 | **Run the server**
137 |
138 | Make sure you're in the `server` directory in your terminal and start the server with:
139 |
140 | ```bash
141 | npm start
142 | ```
143 |
144 | Server is running at [http://localhost:8000](http://localhost:8000).
145 |
146 | **Run the client**
147 |
148 | In your other tab, make sure you're in `client` and run:
149 |
150 | ```bash
151 | npm run serve
152 | ```
153 |
154 | You can view the Vue app in the browser at [http://localhost:8080](http://localhost:8080).
155 |
156 | You can now also sign in, receive an API access token, and view an event's details page at [http://localhost:8080/event/1](http://localhost:8080/event/1).
157 |
158 | Be sure to [check out the full tutorial](https://auth0.com/blog/how-to-make-secure-http-requests-with-vue-and-express/) to see how this process works.
159 |
--------------------------------------------------------------------------------
/client/.env:
--------------------------------------------------------------------------------
1 | VUE_APP_API_URL=https://tconsignappservice.azurewebsites.net/
--------------------------------------------------------------------------------
/client/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 | auth_config.json
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 | pnpm-debug.log*
15 |
16 | # Editor directories and files
17 | .idea
18 | .vscode
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
--------------------------------------------------------------------------------
/client/README.md:
--------------------------------------------------------------------------------
1 | # vuetify
2 |
3 | ## Project setup
4 | ```
5 | npm install
6 | ```
7 |
8 | ### Compiles and hot-reloads for development
9 | ```
10 | npm run serve
11 | ```
12 |
13 | ### Compiles and minifies for production
14 | ```
15 | npm run build
16 | ```
17 |
18 | ### Lints and fixes files
19 | ```
20 | npm run lint
21 | ```
22 |
23 | ### Customize configuration
24 | See [Configuration Reference](https://cli.vuejs.org/config/).
25 |
--------------------------------------------------------------------------------
/client/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ["@vue/cli-plugin-babel/preset"],
3 | };
4 |
--------------------------------------------------------------------------------
/client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vuetify",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint"
9 | },
10 | "dependencies": {
11 | "@auth0/auth0-spa-js": "^1.17.0",
12 | "@babel/polyfill": "^7.4.4",
13 | "@mdi/js": "^5.9.55",
14 | "axios": "^0.21.1",
15 | "core-js": "^3.6.5",
16 | "jspdf": "^2.3.1",
17 | "jspdf-autotable": "^3.5.20",
18 | "moment-timezone": "^0.5.33",
19 | "number-to-words": "^1.2.4",
20 | "vee-validate": "^3.4.11",
21 | "vue": "^2.6.11",
22 | "vue-router": "^3.2.0",
23 | "vuetify": "^2.4.0",
24 | "vuex": "^3.4.0"
25 | },
26 | "devDependencies": {
27 | "@vue/cli-plugin-babel": "~4.5.0",
28 | "@vue/cli-plugin-eslint": "~4.5.0",
29 | "@vue/cli-plugin-router": "~4.5.0",
30 | "@vue/cli-plugin-vuex": "~4.5.0",
31 | "@vue/cli-service": "~4.5.0",
32 | "@vue/eslint-config-prettier": "^6.0.0",
33 | "babel-eslint": "^10.1.0",
34 | "eslint": "^6.7.2",
35 | "eslint-plugin-prettier": "^3.3.1",
36 | "eslint-plugin-vue": "^6.2.2",
37 | "prettier": "^2.2.1",
38 | "vue-cli-plugin-vuetify": "~2.4.2",
39 | "vue-template-compiler": "^2.6.11"
40 | },
41 | "eslintConfig": {
42 | "root": true,
43 | "env": {
44 | "node": true
45 | },
46 | "extends": [
47 | "plugin:vue/essential",
48 | "eslint:recommended",
49 | "@vue/prettier"
50 | ],
51 | "parserOptions": {
52 | "parser": "babel-eslint"
53 | },
54 | "rules": {}
55 | },
56 | "browserslist": [
57 | "> 1%",
58 | "last 2 versions",
59 | "not dead",
60 | "not ie <= 10"
61 | ]
62 | }
63 |
--------------------------------------------------------------------------------
/client/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elitedev201/Vue-shopify-api-integration/18111e9aa61c28c0034c4cae1f190d6972d3af84/client/public/favicon.ico
--------------------------------------------------------------------------------
/client/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Tconsign-portal
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/client/public/staticwebapp.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationFallback": {
3 | "rewrite": "index.html",
4 | "exclude": ["/images/*.{png,jpg,gif,ico}", "/*.{css,scss,js}"]
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/client/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/client/src/assets/images/tc-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elitedev201/Vue-shopify-api-integration/18111e9aa61c28c0034c4cae1f190d6972d3af84/client/src/assets/images/tc-logo.png
--------------------------------------------------------------------------------
/client/src/assets/images/yellow-pillow-bedside-table_1920x.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elitedev201/Vue-shopify-api-integration/18111e9aa61c28c0034c4cae1f190d6972d3af84/client/src/assets/images/yellow-pillow-bedside-table_1920x.jpg
--------------------------------------------------------------------------------
/client/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elitedev201/Vue-shopify-api-integration/18111e9aa61c28c0034c4cae1f190d6972d3af84/client/src/assets/logo.png
--------------------------------------------------------------------------------
/client/src/assets/style.css:
--------------------------------------------------------------------------------
1 | .custom-title .v-app-bar-title__content {
2 | width: max-content !important;
3 | }
4 |
5 | .grey-col {
6 | color: rgba(0, 0, 0, 0.87) !important;
7 | }
8 |
9 | .tc-title {
10 | color: #fff !important;
11 | font-weight: 700;
12 | font-size: 4rem !important;
13 | text-transform: uppercase;
14 | line-height: 1.1;
15 | text-shadow: 1px 1px 7px transparent;
16 | display: flex;
17 | justify-content: center;
18 | margin-top: 18rem;
19 | background: rgb(255, 255, 255, 0.1);
20 | }
21 |
22 | .tc-footer-layout {
23 | padding: 2rem !important;
24 | }
25 |
26 | .v-application .mb-12 {
27 | border-radius: 0px !important;
28 | margin-bottom: 0px !important;
29 | }
30 |
31 | .v-toolbar {
32 | flex: 0;
33 | }
34 |
35 | .icon-space {
36 | padding: 1rem;
37 | margin: 1rem;
38 | }
39 |
40 | .custom-spacing {
41 | margin: 2rem 4rem;
42 | }
43 |
44 | .create-button {
45 | margin: 3rem 4rem 0rem 0rem;
46 | }
47 |
48 | .create-product {
49 | padding: 1rem 4rem 2rem 4rem;
50 | }
51 |
52 | .create-title {
53 | padding: 2rem 0rem 0rem 3rem;
54 | }
55 |
56 | .tc-appbar {
57 | background: rgb(255, 255, 255, 0.93) !important;
58 | }
59 |
60 | .icon-width {
61 | width: 170px !important;
62 | }
63 |
64 | .right-space {
65 | padding-right: 8px !important;
66 | }
67 |
68 | .white-col {
69 | color: white !important;
70 | }
71 |
72 | .create-card {
73 | margin: 6rem 33% 2rem 33%;
74 | }
75 |
76 | .create-consignor {
77 | margin: 6rem 20% 2rem 20%;
78 | }
79 |
80 | .width-30 {
81 | width: 30%;
82 | }
83 |
84 | .create-footer {
85 | text-align: right;
86 | margin-top: 2rem;
87 | }
88 |
89 | .loading-button {
90 | margin-bottom: 2rem;
91 | }
92 |
93 | .custom-link{
94 | color: rgba(0, 0, 0, 0.87) !important;
95 | text-decoration: none;
96 | }
97 |
98 | .image-label {
99 | margin: 2rem 0rem;
100 | }
101 |
102 | .payout-layout {
103 | margin: 1rem 6rem;
104 | }
105 |
106 | .p-title {
107 | padding: 1rem 1rem 3rem 0rem;
108 | }
109 |
110 | .p-sub-title {
111 | padding: 0rem 0rem 1rem 2rem;
112 | }
--------------------------------------------------------------------------------
/client/src/auth/authGuard.js:
--------------------------------------------------------------------------------
1 | import { getInstance } from "./index";
2 |
3 | export const authGuard = (to, from, next) => {
4 | const authService = getInstance();
5 |
6 | const fn = () => {
7 | // If the user is authenticated, continue with the route
8 | if (authService.isAuthenticated) {
9 | return next();
10 | }
11 |
12 | // Otherwise, log in
13 | authService.loginWithRedirect({ appState: { targetUrl: to.fullPath } });
14 | };
15 |
16 | // If loading has already finished, check our auth state using `fn()`
17 | if (!authService.loading) {
18 | return fn();
19 | }
20 |
21 | // Watch for the loading property to change before we check isAuthenticated
22 | authService.$watch("loading", loading => {
23 | if (loading === false) {
24 | return fn();
25 | }
26 | });
27 | };
--------------------------------------------------------------------------------
/client/src/auth/index.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import createAuth0Client from "@auth0/auth0-spa-js";
3 |
4 | /** Define a default action to perform after authentication */
5 | const DEFAULT_REDIRECT_CALLBACK = () =>
6 | window.history.replaceState({}, document.title, window.location.pathname);
7 |
8 | let instance;
9 |
10 | /** Returns the current instance of the SDK */
11 | export const getInstance = () => instance;
12 |
13 | /** Creates an instance of the Auth0 SDK. If one has already been created, it returns that instance */
14 | export const useAuth0 = ({
15 | onRedirectCallback = DEFAULT_REDIRECT_CALLBACK,
16 | redirectUri = window.location.origin + "/products",
17 | ...options
18 | }) => {
19 | if (instance) return instance;
20 |
21 | // The 'instance' is simply a Vue object
22 | instance = new Vue({
23 | data() {
24 | return {
25 | loading: true,
26 | isAuthenticated: false,
27 | user: {},
28 | auth0Client: null,
29 | popupOpen: false,
30 | error: null
31 | };
32 | },
33 | methods: {
34 | /** Authenticates the user using a popup window */
35 | async loginWithPopup(o) {
36 | this.popupOpen = true;
37 |
38 | try {
39 | await this.auth0Client.loginWithPopup(o);
40 | } catch (e) {
41 | // eslint-disable-next-line
42 | console.error(e);
43 | } finally {
44 | this.popupOpen = false;
45 | }
46 |
47 | this.user = await this.auth0Client.getUser();
48 | this.isAuthenticated = true;
49 | },
50 | /** Handles the callback when logging in using a redirect */
51 | async handleRedirectCallback() {
52 | this.loading = true;
53 | try {
54 | await this.auth0Client.handleRedirectCallback();
55 | this.user = await this.auth0Client.getUser();
56 | this.isAuthenticated = true;
57 | } catch (e) {
58 | this.error = e;
59 | } finally {
60 | this.loading = false;
61 | }
62 | },
63 | /** Authenticates the user using the redirect method */
64 | loginWithRedirect(o) {
65 | return this.auth0Client.loginWithRedirect(o);
66 | },
67 | /** Returns all the claims present in the ID token */
68 | getIdTokenClaims(o) {
69 | return this.auth0Client.getIdTokenClaims(o);
70 | },
71 | /** Returns the access token. If the token is invalid or missing, a new one is retrieved */
72 | getTokenSilently(o) {
73 | return this.auth0Client.getTokenSilently(o);
74 | },
75 | /** Gets the access token using a popup window */
76 |
77 | getTokenWithPopup(o) {
78 | return this.auth0Client.getTokenWithPopup(o);
79 | },
80 | /** Logs the user out and removes their session on the authorization server */
81 | logout(o) {
82 | return this.auth0Client.logout(o);
83 | }
84 | },
85 | /** Use this lifecycle method to instantiate the SDK client */
86 | async created() {
87 | // Create a new instance of the SDK client using members of the given options object
88 | this.auth0Client = await createAuth0Client({
89 | domain: options.domain,
90 | client_id: options.clientId,
91 | audience: options.audience,
92 | redirect_uri: redirectUri
93 | });
94 |
95 | try {
96 | // If the user is returning to the app after authentication...
97 | if (
98 | window.location.search.includes("code=") &&
99 | window.location.search.includes("state=")
100 | ) {
101 | // handle the redirect and retrieve tokens
102 | const { appState } = await this.auth0Client.handleRedirectCallback();
103 |
104 | // Notify subscribers that the redirect callback has happened, passing the appState
105 | // (useful for retrieving any pre-authentication state)
106 | onRedirectCallback(appState);
107 | }
108 | } catch (e) {
109 | this.error = e;
110 | } finally {
111 | // Initialize our internal authentication state
112 | this.isAuthenticated = await this.auth0Client.isAuthenticated();
113 | this.user = await this.auth0Client.getUser();
114 | this.loading = false;
115 | }
116 | }
117 | });
118 |
119 | return instance;
120 | };
121 |
122 | // Create a simple Vue plugin to expose the wrapper object throughout the application
123 | export const Auth0Plugin = {
124 | install(Vue, options) {
125 | Vue.prototype.$auth = useAuth0(options);
126 | }
127 | };
--------------------------------------------------------------------------------
/client/src/components/Footer.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
14 |
15 |
16 |
21 |
--------------------------------------------------------------------------------
/client/src/components/Header.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | mdi-cloud-upload
4 | Tacoma Consignment Portal
7 |
8 | Consignors
9 | Catalog
10 |
11 | mdi-cloud-upload {{ $auth.user.name }}
13 | Sign in
15 |
16 | Log out
18 |
19 |
20 |
21 |
22 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/client/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue"
2 | import App from "./App.vue"
3 | import router from "./router"
4 | import store from "./store"
5 | import vuetify from "./plugins/vuetify"
6 | import "@babel/polyfill"
7 | import "./assets/style.css"
8 | import moment from "moment-timezone"
9 |
10 | // Import the Auth0 configuration
11 | import { domain, clientId, audience } from "../auth_config.json"
12 |
13 | // Import the plugin here
14 | import { Auth0Plugin } from "./auth"
15 |
16 | // Install the authentication plugin here
17 | Vue.use(Auth0Plugin, {
18 | domain,
19 | clientId,
20 | audience,
21 | onRedirectCallback: appState => {
22 | router.push(
23 | appState && appState.targetUrl
24 | ? appState.targetUrl
25 | : window.location.pathname
26 | )
27 | },
28 | })
29 |
30 | Vue.filter("formatDate", function (value) {
31 | if (value) {
32 | return moment(String(value)).format("MM/DD/YYYY hh:mm")
33 | }
34 | })
35 |
36 | Vue.config.productionTip = false
37 |
38 | new Vue({
39 | router,
40 | store,
41 | vuetify,
42 | render: h => h(App),
43 | }).$mount("#app")
44 |
--------------------------------------------------------------------------------
/client/src/plugins/vuetify.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import Vuetify from "vuetify";
3 | import "vuetify/dist/vuetify.min.css";
4 |
5 | Vue.use(Vuetify);
6 |
7 | export default new Vuetify({});
8 |
--------------------------------------------------------------------------------
/client/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue"
2 | import VueRouter from "vue-router"
3 | import Home from "../views/Home.vue"
4 | import { authGuard } from "../auth/authGuard"
5 |
6 | Vue.use(VueRouter)
7 |
8 | const routes = [
9 | {
10 | path: "/",
11 | name: "Home",
12 | component: Home,
13 | },
14 | {
15 | path: "/products",
16 | name: "Products",
17 | component: () => import("../views/Products.vue"),
18 | beforeEnter: authGuard,
19 | },
20 | {
21 | path: "/products/:vendor",
22 | name: "ProductsByVendor",
23 | component: () => import("../views/ProductsByVendor.vue"),
24 | beforeEnter: authGuard,
25 | },
26 | {
27 | path: "/create_product",
28 | name: "CreateProduct",
29 | component: () => import("../views/CreateProduct.vue"),
30 | beforeEnter: authGuard,
31 | },
32 | {
33 | path: "/product/:productid",
34 | name: "ProductDetail",
35 | component: () => import("../views/ProductDetail.vue"),
36 | beforeEnter: authGuard,
37 | },
38 | {
39 | path: "/payouts",
40 | name: "Payouts",
41 | component: () => import("../views/Payouts.vue"),
42 | beforeEnter: authGuard,
43 | },
44 | {
45 | path: "/beforepayouts",
46 | name: "BeforePayouts",
47 | component: () => import("../views/Payouts.vue"),
48 | beforeEnter: authGuard,
49 | },
50 | {
51 | path: "/payout/:vendor",
52 | name: "PayoutDetail",
53 | component: () => import("../views/PayoutDetail.vue"),
54 | beforeEnter: authGuard,
55 | },
56 | {
57 | path: "/consignors",
58 | name: "Consignors",
59 | component: () => import("../views/Consignors.vue"),
60 | beforeEnter: authGuard,
61 | },
62 | {
63 | path: "/create_consignor",
64 | name: "CreateConsignor",
65 | component: () => import("../views/CreateConsignor.vue"),
66 | beforeEnter: authGuard,
67 | },
68 | {
69 | path: "/consignor/:id",
70 | name: "ConsignorDetail",
71 | component: () => import("../views/ConsignorDetail.vue"),
72 | beforeEnter: authGuard,
73 | },
74 | ]
75 |
76 | const router = new VueRouter({
77 | mode: "history",
78 | base: process.env.BASE_URL,
79 | routes,
80 | })
81 |
82 | export default router
83 |
--------------------------------------------------------------------------------
/client/src/services/consignorService.js:
--------------------------------------------------------------------------------
1 | import axios from "axios"
2 |
3 | export default {
4 | async getConsignors() {
5 | let res = await axios.get(process.env.VUE_APP_API_URL + "consignors")
6 | return res.data
7 | },
8 |
9 | async addConsignor(data) {
10 | let res = await axios.post(process.env.VUE_APP_API_URL + "consignor", data)
11 | return res.data
12 | },
13 |
14 | async updateConsignor(data) {
15 | let res = await axios.put(process.env.VUE_APP_API_URL + "consignor", data)
16 | return res.data
17 | },
18 |
19 | async deleteConsignor(id) {
20 | let res = await axios.delete(process.env.VUE_APP_API_URL + "consignor", {
21 | params: {
22 | id: id,
23 | },
24 | })
25 | return res.data
26 | },
27 |
28 | async getConsignorById(id) {
29 | let res = await axios.get(process.env.VUE_APP_API_URL + "consignorbyid", {
30 | params: {
31 | id: id,
32 | },
33 | })
34 | return res.data
35 | },
36 |
37 | async getConsignorByVendor(vendor) {
38 | let res = await axios.get(process.env.VUE_APP_API_URL + "consignor", {
39 | params: {
40 | vendor: vendor,
41 | },
42 | })
43 | return res.data
44 | },
45 | }
46 |
--------------------------------------------------------------------------------
/client/src/services/payoutService.js:
--------------------------------------------------------------------------------
1 | import axios from "axios"
2 |
3 | export default {
4 | async getPayouts(accessToken, flag) {
5 | let res = await axios.get(process.env.VUE_APP_API_URL + "payouts", {
6 | headers: {
7 | Authorization: `Bearer ${accessToken}`,
8 | },
9 | params: {
10 | flag: flag,
11 | },
12 | })
13 | return res.data
14 | },
15 | async getPayoutDetails(vendor) {
16 | let res = await axios.get(process.env.VUE_APP_API_URL + "payout_details", {
17 | params: {
18 | vendor: vendor,
19 | },
20 | })
21 | return res.data
22 | },
23 | async getPayoutByVendor(vendor) {
24 | let res = await axios.get(process.env.VUE_APP_API_URL + "payout", {
25 | params: {
26 | vendor: vendor,
27 | },
28 | })
29 | return res.data
30 | },
31 | }
32 |
--------------------------------------------------------------------------------
/client/src/services/productService.js:
--------------------------------------------------------------------------------
1 | import axios from "axios"
2 |
3 | export default {
4 | async getProducts(accessToken) {
5 | let res = await axios.get(process.env.VUE_APP_API_URL + "products", {
6 | headers: {
7 | Authorization: `Bearer ${accessToken}`,
8 | },
9 | })
10 | return res.data
11 | },
12 |
13 | async getProductById(product_id) {
14 | let res = await axios.get(process.env.VUE_APP_API_URL + "product", {
15 | params: {
16 | product_id: product_id,
17 | },
18 | })
19 | return res.data
20 | },
21 |
22 | async getProductsByVendor(vendor) {
23 | let res = await axios.get(process.env.VUE_APP_API_URL + "productsbyvendor", {
24 | params: {
25 | vendor: vendor,
26 | },
27 | })
28 | return res.data
29 | },
30 |
31 | async addProduct(formData) {
32 | let res = await axios.post(
33 | process.env.VUE_APP_API_URL + "products",
34 | formData
35 | )
36 | return res.data
37 | },
38 |
39 | async updateProduct(formData) {
40 | let res = await axios.put(
41 | process.env.VUE_APP_API_URL + "products",
42 | formData
43 | )
44 | return res.data
45 | },
46 |
47 | async deleteProduct(product_id, title) {
48 | let res = await axios.delete(process.env.VUE_APP_API_URL + "products", {
49 | params: {
50 | title: title,
51 | product_id: product_id,
52 | },
53 | })
54 | return res.data
55 | },
56 |
57 | async getEventSingle(eventId, accessToken) {
58 | let res = await axios.get(
59 | process.env.VUE_APP_API_URL + "events/" + eventId,
60 | {
61 | headers: {
62 | Authorization: `Bearer ${accessToken}`,
63 | },
64 | }
65 | )
66 | return res.data
67 | },
68 | }
69 |
--------------------------------------------------------------------------------
/client/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import Vuex from "vuex";
3 |
4 | Vue.use(Vuex);
5 |
6 | export default new Vuex.Store({
7 | state: {},
8 | mutations: {},
9 | actions: {},
10 | modules: {},
11 | });
12 |
--------------------------------------------------------------------------------
/client/src/views/ConsignorDatatable.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Consignors
5 |
6 |
13 |
14 |
15 |
16 |
17 | {{item.id}}
20 |
21 |
22 |
27 |
28 |
29 | {{item.qbStAddress1}}
32 |
33 |
34 | {{item.qbStAddress2}}
37 |
38 |
39 | {{item.qbCity}}
42 |
43 |
44 | {{item.qbState}}
47 |
48 |
49 | {{item.qbZip}}
52 |
53 |
54 | {{item.qbPhone}}
57 |
58 |
59 | {{item.qbEmail}}
62 |
63 |
64 |
65 | mdi-delete
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | Are you sure you want to delete this item?
75 |
76 |
77 |
78 |
79 | Cancel
80 |
81 |
82 | OK
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
195 |
--------------------------------------------------------------------------------
/client/src/views/ConsignorDetail.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Consignor Detail
5 |
112 |
113 |
114 |
119 | Adding Product...
120 |
121 |
122 |
123 |
124 |
254 |
--------------------------------------------------------------------------------
/client/src/views/Consignors.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | View Payouts
10 |
11 |
12 |
13 |
14 |
15 |
16 | mdi-plus
17 | Create Consignor
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
43 |
--------------------------------------------------------------------------------
/client/src/views/CreateConsignor.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Create Consignor
5 |
6 |
7 |
96 |
97 |
98 |
99 |
100 |
105 | Adding Product...
106 |
107 |
108 |
109 |
110 |
225 |
--------------------------------------------------------------------------------
/client/src/views/CreateProduct.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Create Product
5 |
6 |
7 |
105 |
106 |
107 |
108 |
109 |
114 | Adding Product...
115 |
116 |
117 |
118 |
119 |
251 |
--------------------------------------------------------------------------------
/client/src/views/Datatable.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ProductList
5 |
6 |
13 |
14 |
15 |
16 |
17 | {{ item.shopify_id }}
18 |
19 |
20 |
23 |
24 |
25 | {{ item.title }}
26 |
27 |
28 | {{ item.description }}
29 |
30 |
31 | {{ item.vendor }}
32 |
33 |
34 | {{ item.consignorID }}
35 |
36 |
37 | ${{ item.price }}
38 |
39 |
40 | {{ item.color }}
41 |
42 |
43 | {{ item.material }}
44 |
45 |
46 | {{ item.size }}
47 |
48 |
49 | {{ item.product_type }}
50 |
51 |
52 | {{ item.qb_sku }}
53 |
54 |
55 | {{ item.barcode }}
56 |
57 |
58 | {{ item.sale_price }}
59 |
60 |
61 | {{ item.sale_price_set | formatDate }}
62 |
63 |
64 | {{ item.sale_price_system }}
65 |
66 |
67 |
68 |
69 | mdi-pencil
70 |
71 | mdi-delete
72 |
73 |
74 |
75 |
76 |
77 | Edit Product
78 |
79 |
80 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 | Are you sure you want to delete this item?
188 |
189 |
190 |
191 |
192 | Cancel
193 |
194 |
195 | OK
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
428 |
--------------------------------------------------------------------------------
/client/src/views/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Tacoma Consignment Management Portal
4 |
5 |
6 |
7 |
15 |
--------------------------------------------------------------------------------
/client/src/views/PayoutDatatable.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Consignor Payouts for August
5 |
6 |
13 |
14 |
15 |
16 |
17 |
22 |
23 |
24 |
29 |
30 |
31 |
36 |
37 |
38 |
43 |
44 |
45 |
50 |
51 |
59 |
60 |
61 |
62 |
63 |
97 |
--------------------------------------------------------------------------------
/client/src/views/PayoutDetail.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | mdi-file-pdf
8 | PDF Generate
9 |
10 |
11 |
12 |
13 |
14 | {{ company }}
15 |
16 |
17 |
18 |
{{ date }}
19 |
20 |
21 |
22 |
{{ company }}
23 |
24 | {{ streetAddress1 }}
25 |
26 |
27 | {{ streetAddress2 }}
28 |
29 |
30 | {{ bottom_line }}
31 |
32 |
33 |
34 |
35 | PayoutDetails
36 |
37 |
44 |
45 |
50 |
51 |
52 |
53 | {{ item.spfy_order_id }}
54 |
55 |
56 |
57 |
58 | {{ item.spfy_line_item_name }}
59 |
60 |
61 |
62 |
63 | {{ item.spfy_line_item_qty }}
64 |
65 |
66 |
67 |
68 | {{ item.spfy_line_item_price }}
69 |
70 |
71 |
72 |
73 | {{ item.total_amount }}
74 |
75 |
76 |
77 |
78 | {{ item.defaultPercentage }}
79 |
80 |
81 |
82 |
83 | {{ item.net_amount }}
84 |
85 |
86 |
87 |
88 |
89 |
90 |
Total Items: {{ totalItems }}
91 |
Total Due: {{ totalSales }}
92 |
93 |
94 |
97 |
98 |
99 |
100 |
101 |
102 |
246 |
--------------------------------------------------------------------------------
/client/src/views/Payouts.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 |
12 |
15 |
16 |
17 |
18 |
19 |
37 |
--------------------------------------------------------------------------------
/client/src/views/ProductDetail.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Product Detail
5 |
150 |
151 |
152 |
157 | Adding Product...
158 |
159 |
160 |
161 |
162 |
330 |
--------------------------------------------------------------------------------
/client/src/views/Products.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | mdi-plus
8 | Create Product
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
29 |
--------------------------------------------------------------------------------
/client/src/views/ProductsByVendor.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | ProductList
10 |
11 |
18 |
19 |
24 |
25 |
26 | {{ item.shopify_id }}
29 |
30 |
31 |
36 |
37 |
38 | {{ item.title }}
41 |
42 |
43 | {{ item.description }}
46 |
47 |
48 | {{ item.vendor }}
51 |
52 |
53 | {{ item.consignorID }}
56 |
57 |
58 | ${{ item.price }}
61 |
62 |
63 | {{ item.color }}
66 |
67 |
68 | {{ item.material }}
71 |
72 |
73 | {{ item.size }}
76 |
77 |
78 | {{ item.product_type }}
81 |
82 |
83 | {{ item.qb_sku }}
86 |
87 |
88 | {{ item.barcode }}
91 |
92 |
93 | {{ item.sale_price }}
96 |
97 |
98 | {{
100 | item.sale_price_set | formatDate
101 | }}
103 |
104 |
105 | {{
107 | item.sale_price_system
108 | }}
110 |
111 |
112 |
113 |
114 |
117 |
118 |
119 |
120 |
121 |
182 |
--------------------------------------------------------------------------------
/database/config.js:
--------------------------------------------------------------------------------
1 |
2 | // config for your mssql
3 | const config = {
4 | user: process.env.DB_USER,
5 | password: process.env.DB_PASS,
6 | server: process.env.DB_HOST,
7 | database: process.env.DB_NAME,
8 | options: {
9 | trustedConnection: true,
10 | encrypt: true,
11 | enableArithAbort: true,
12 | trustServerCertificate: true,
13 | },
14 | }
15 |
16 | module.exports = config
--------------------------------------------------------------------------------
/database/db.js:
--------------------------------------------------------------------------------
1 | const sql = require("mssql")
2 | const databaseConfig = require('./config')
3 |
4 | sql.connect(databaseConfig)
5 |
6 | module.exports = sql
7 |
--------------------------------------------------------------------------------
/db_backup/2021-08-18-tconsigndb.bacpac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elitedev201/Vue-shopify-api-integration/18111e9aa61c28c0034c4cae1f190d6972d3af84/db_backup/2021-08-18-tconsigndb.bacpac
--------------------------------------------------------------------------------
/db_backup/2021-08-19_backup.bacpac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elitedev201/Vue-shopify-api-integration/18111e9aa61c28c0034c4cae1f190d6972d3af84/db_backup/2021-08-19_backup.bacpac
--------------------------------------------------------------------------------
/db_backup/2021-08-22-backup.bak:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elitedev201/Vue-shopify-api-integration/18111e9aa61c28c0034c4cae1f190d6972d3af84/db_backup/2021-08-22-backup.bak
--------------------------------------------------------------------------------
/middleware/auth.js:
--------------------------------------------------------------------------------
1 | const jwt = require("express-jwt")
2 | const jwksRsa = require("jwks-rsa")
3 |
4 | // Create middleware to validate the JWT using express-jwt
5 | const checkJwt = jwt({
6 | // Provide a signing key based on the key identifier in the header and the signing keys provided by your Auth0 JWKS endpoint.
7 | secret: jwksRsa.expressJwtSecret({
8 | cache: true,
9 | rateLimit: true,
10 | jwksRequestsPerMinute: 5,
11 | jwksUri: `https://${process.env.AUTH0_DOMAIN}/.well-known/jwks.json`,
12 | }),
13 |
14 | // Validate the audience (Identifier) and the issuer (Domain).
15 | audience: process.env.AUTH0_AUDIENCE,
16 | issuer: `https://${process.env.AUTH0_DOMAIN}/`,
17 | algorithms: ["RS256"],
18 | })
19 |
20 | module.exports = checkJwt
--------------------------------------------------------------------------------
/middleware/permission.js:
--------------------------------------------------------------------------------
1 | const jwtAuthz = require("express-jwt-authz")
2 |
3 | const checkPermissions = jwtAuthz(["manage:users"], {
4 | customScopeKey: "permissions",
5 | })
6 |
7 | module.exports = checkPermissions
--------------------------------------------------------------------------------
/models/consignor-model.js:
--------------------------------------------------------------------------------
1 | const db = require("../database/db")
2 |
3 | const consignorModel = {
4 | getAllConsignors: getAllConsignors,
5 | addConsignor: addConsignor,
6 | updateConsignor: updateConsignor,
7 | getConsignorById: getConsignorById,
8 | getConsignorByVendor: getConsignorByVendor,
9 | delConsignor: delConsignor,
10 | }
11 |
12 | function getAllConsignors() {
13 | return new Promise((resolve, reject) => {
14 | var request = new db.Request()
15 | let query = "SELECT * FROM consignors"
16 |
17 | request.query(query, (error, rows) => {
18 | if (error) {
19 | reject(error.message)
20 | } else {
21 | resolve(rows.recordset)
22 | }
23 | })
24 | })
25 | }
26 |
27 | function addConsignor(data) {
28 | var request = new db.Request()
29 | request.input("qbCompany", db.VarChar, data.company)
30 | request.input("defaultPercentage", db.Numeric, 50)
31 | request.input("qbFirst", db.VarChar, data.first)
32 | request.input("qbLast", db.VarChar, data.last)
33 | request.input("qbStAddress1", db.VarChar, data.stAddress1)
34 | request.input("qbStAddress2", db.VarChar, data.stAddress2)
35 | request.input("qbCity", db.VarChar, data.city)
36 | request.input("qbState", db.VarChar, data.state)
37 | request.input("qbZip", db.VarChar, data.zip)
38 | request.input("qbEmail", db.VarChar, data.email)
39 | request.input("qbPhone", db.VarChar, data.phone)
40 | let query =
41 | "INSERT INTO consignors(qbCompany, defaultPercentage, qbFirst, qbLast, qbStAddress1, qbStAddress2, qbCity, qbState, qbZip, qbEmail, qbPhone ) VALUES (@qbCompany, @defaultPercentage, @qbFirst, @qbLast, @qbStAddress1, @qbStAddress2, @qbCity, @qbState, @qbZip, @qbEmail, @qbPhone)"
42 |
43 | return new Promise((resolve, reject) => {
44 | request.query(query, (error, rows) => {
45 | if (error) {
46 | reject(error.message)
47 | } else {
48 | resolve({ code: 200 })
49 | }
50 | })
51 | })
52 | }
53 |
54 | function updateConsignor(data) {
55 | var request = new db.Request()
56 | request.input("id", db.VarChar, data.id)
57 | request.input("qbCompany", db.VarChar, data.company)
58 | request.input("qbFirst", db.VarChar, data.first)
59 | request.input("qbLast", db.VarChar, data.last)
60 | request.input("qbStAddress1", db.VarChar, data.stAddress1)
61 | request.input("qbStAddress2", db.VarChar, data.stAddress2)
62 | request.input("qbCity", db.VarChar, data.city)
63 | request.input("qbState", db.VarChar, data.state)
64 | request.input("qbZip", db.VarChar, data.zip)
65 | request.input("qbEmail", db.VarChar, data.email)
66 | request.input("qbPhone", db.VarChar, data.phone)
67 | let query =
68 | "UPDATE consignors SET qbCompany=@qbCompany, qbFirst=@qbFirst, qbLast=@qbLast, qbStAddress1=@qbStAddress1, qbStAddress2=@qbStAddress2, qbCity=@qbCity, qbState=@qbState, qbZip=@qbZip, qbEmail=@qbEmail, qbPhone=@qbPhone WHERE id=@id"
69 |
70 | return new Promise((resolve, reject) => {
71 | request.query(query, (error, rows) => {
72 | if (error) {
73 | reject(error.message)
74 | } else {
75 | resolve({ code: 200 })
76 | }
77 | })
78 | })
79 | }
80 |
81 | function delConsignor(id) {
82 | return new Promise((resolve, reject) => {
83 | var request = new db.Request()
84 | request.input("id", db.Int, id)
85 | let query = "DELETE FROM consignors WHERE id=@id"
86 |
87 | request.query(query, (error, rows) => {
88 | if (error) {
89 | reject(error.message)
90 | } else {
91 | resolve(rows.recordset)
92 | }
93 | })
94 | })
95 | }
96 |
97 | function getConsignorById(id) {
98 | return new Promise((resolve, reject) => {
99 | var request = new db.Request()
100 | request.input("id", db.Int, id)
101 | let query =
102 | "SELECT * FROM consignors WHERE id=@id"
103 |
104 | request.query(query, (error, rows) => {
105 | if (error) {
106 | reject(error.message)
107 | } else {
108 | resolve(rows.recordset)
109 | }
110 | })
111 | })
112 | }
113 |
114 | function getConsignorByVendor(vendor) {
115 | return new Promise((resolve, reject) => {
116 | var request = new db.Request()
117 | request.input("vendor", db.VarChar, vendor)
118 | let query =
119 | "SELECT id, qbCompany, defaultPercentage, qbStAddress1, qbStAddress2, (qbCity + ', ' + qbState + ' ' + qbZip) as bottom_line FROM consignors WHERE qbCompany=@vendor"
120 |
121 | request.query(query, (error, rows) => {
122 | if (error) {
123 | reject(error.message)
124 | } else {
125 | resolve(rows.recordset)
126 | }
127 | })
128 | })
129 | }
130 |
131 | module.exports = consignorModel
132 |
--------------------------------------------------------------------------------
/models/order-model.js:
--------------------------------------------------------------------------------
1 | const db = require("../database/db")
2 |
3 | const orderModel = {
4 | createOrders: createOrders,
5 | createOrderItem: createOrderItem,
6 | }
7 |
8 | function createOrders(req) {
9 | return new Promise((resolve, reject) => {
10 | var request = new db.Request()
11 |
12 | const spfy_order_id = req.body.name
13 | const spfy_email = req.body.contact_email
14 | const spfy_financial_status = req.body.financial_status
15 | const spfy_paid_at = req.body.processed_at
16 | const spfy_fulfillment_status = req.body.fulfillment_status
17 | const spfy_fulfilled_at = req.body.updated_at
18 | const spfy_accepts_marketing = req.body.buyer_accepts_marketing
19 | const spfy_currency = req.body.currency
20 | const spfy_subtotal = req.body.subtotal_price
21 | const spfy_shipping = req.body.requires_shipping
22 | const spfy_taxes = req.body.total_tax
23 | const spfy_total = req.body.total_price
24 | const spfy_discount_amount = req.body.total_discounts
25 | const spfy_created_at = req.body.created_at
26 |
27 | var spfy_billing_name = ""
28 | var spfy_billing_street = ""
29 | var spfy_billing_address_1 = ""
30 | var spfy_billing_address_2 = ""
31 | var spfy_billing_company = ""
32 | var spfy_billing_city = ""
33 | var spfy_billing_zip = ""
34 | var spfy_billing_state = ""
35 | var spfy_billing_province = ""
36 | var spfy_billing_country = ""
37 | var spfy_billing_phone = ""
38 | var spfy_billing_province_name = ""
39 |
40 | if (req.body.billing_address) {
41 | spfy_billing_name = req.body.billing_address.name
42 | spfy_billing_street = req.body.billing_address.address1
43 | spfy_billing_address_1 = req.body.billing_address.address1
44 | spfy_billing_address_2 = req.body.billing_address.address2
45 | spfy_billing_company = req.body.billing_address.company
46 | spfy_billing_city = req.body.billing_address.city
47 | spfy_billing_zip = req.body.billing_address.zip
48 | spfy_billing_state = req.body.billing_address.province
49 | spfy_billing_province = req.body.billing_address.province
50 | spfy_billing_country = req.body.billing_address.country
51 | spfy_billing_phone = req.body.billing_address.phone
52 | spfy_billing_province_name = req.body.billing_address.province
53 | }
54 |
55 | var spfy_shipping_name = ""
56 | var spfy_shipping_street = ""
57 | var spfy_shipping_address_1 = ""
58 | var spfy_shipping_address_2 = ""
59 | var spfy_shipping_company = ""
60 | var spfy_shipping_city = ""
61 | var spfy_shipping_zip = ""
62 | var spfy_shipping_state = ""
63 | var spfy_shipping_province = ""
64 | var spfy_shipping_country = ""
65 | var spfy_shipping_phone = ""
66 | var spfy_shipping_province_name = ""
67 |
68 | if (req.body.shipping_address) {
69 | spfy_shipping_name = req.body.shipping_address.name
70 | spfy_shipping_street = req.body.shipping_address.adress1
71 | spfy_shipping_address_1 = req.body.shipping_address.adress1
72 | spfy_shipping_address_2 = req.body.shipping_address.adress2
73 | spfy_shipping_company = req.body.shipping_address.company
74 | spfy_shipping_city = req.body.shipping_address.city
75 | spfy_shipping_zip = req.body.shipping_address.zip
76 | spfy_shipping_state = req.body.shipping_address.province
77 | spfy_shipping_province = req.body.shipping_address.province
78 | spfy_shipping_province_name = req.body.shipping_address.province
79 | spfy_shipping_country = req.body.shipping_address.country
80 | spfy_shipping_phone = req.body.shipping_address.phone
81 | }
82 |
83 | const spfy_notes = req.body.note
84 | const spfy_note_attributes = req.body.note_attributes
85 | const spfy_cancelled_at = req.body.cancelled_at
86 | const spfy_payment_method = req.body.processing_method
87 | const spfy_payment_reference_id = req.body.reference
88 | const spfy_refunded_amount = req.body.refunds.price
89 | const spfy_outstanding_balance = req.body.total_outstanding
90 | const spfy_employee = req.body.name
91 | const spfy_location = req.body.location_id
92 | const spfy_device_id = req.body.device_id
93 | const spfy_id = req.body.id
94 | const spfy_risk_level = ""
95 | const spfy_source = req.body.source_url
96 | var spfy_tax_1_name = ""
97 | var spfy_tax_1_amount = 0
98 | var spfy_tax_2_name = ""
99 | var spfy_tax_2_amount = 0
100 | var spfy_tax_3_name = ""
101 | var spfy_tax_3_amount = 0
102 | var spfy_tax_4_name = ""
103 | var spfy_tax_4_amount = 0
104 | var spfy_tax_5_name = ""
105 | var spfy_tax_5_amount = 0
106 |
107 | for (let i = 0; i < req.body.tax_lines.length; i++) {
108 | if (i == 0) {
109 | spfy_tax_1_name = req.body.tax_lines[0].title
110 | spfy_tax_1_amount = req.body.tax_lines[0].price
111 | } else if (i == 1) {
112 | spfy_tax_2_name = req.body.tax_lines[1].title
113 | spfy_tax_2_amount = req.body.tax_lines[1].price
114 | } else if (i == 2) {
115 | spfy_tax_3_name = req.body.tax_lines[2].title
116 | spfy_tax_3_amount = req.body.tax_lines[2].price
117 | } else if (i == 3) {
118 | spfy_tax_4_name = req.body.tax_lines[3].title
119 | spfy_tax_4_amount = req.body.tax_lines[3].price
120 | } else if (i == 4) {
121 | spfy_tax_5_name = req.body.tax_lines[4].title
122 | spfy_tax_5_amount = req.body.tax_lines[4].price
123 | }
124 | }
125 |
126 | const spfy_phone = req.body.phone
127 | const spfy_receipt_number = req.body.number
128 | const spfy_duties = req.body.current_total_duties_set
129 |
130 | const spfy_payment_terms_name = req.body.payment_gateway_names[0]
131 | const spfy_next_payment_due_at = ""
132 | const last_updated = req.body.updated_at
133 | const spfy_json_response = req.body
134 |
135 | request.input("spfy_order_id", db.VarChar, spfy_order_id)
136 | request.input("spfy_email", db.VarChar, spfy_email)
137 | request.input("spfy_financial_status", db.VarChar, spfy_financial_status)
138 | request.input("spfy_paid_at", db.DateTime, spfy_paid_at)
139 | request.input(
140 | "spfy_fulfillment_status",
141 | db.VarChar,
142 | spfy_fulfillment_status
143 | )
144 | request.input("spfy_fulfilled_at", db.DateTime, spfy_fulfilled_at)
145 | request.input("spfy_accepts_marketing", db.VarChar, spfy_accepts_marketing)
146 | request.input("spfy_currency", db.VarChar, spfy_currency)
147 | request.input("spfy_subtotal", db.Numeric, spfy_subtotal)
148 | request.input("spfy_shipping", db.Numeric, spfy_shipping)
149 | request.input("spfy_taxes", db.Numeric, spfy_taxes)
150 | request.input("spfy_total", db.Numeric, spfy_total)
151 | request.input("spfy_discount_amount", db.Numeric, spfy_discount_amount)
152 | request.input("spfy_created_at", db.DateTime, spfy_created_at)
153 | request.input("spfy_billing_name", db.VarChar, spfy_billing_name)
154 | request.input("spfy_billing_street", db.VarChar, spfy_billing_street)
155 | request.input("spfy_billing_address_1", db.VarChar, spfy_billing_address_1)
156 | request.input("spfy_billing_address_2", db.VarChar, spfy_billing_address_2)
157 | request.input("spfy_billing_company", db.VarChar, spfy_billing_company)
158 | request.input("spfy_billing_city", db.VarChar, spfy_billing_city)
159 | request.input("spfy_billing_zip", db.VarChar, spfy_billing_zip)
160 | request.input("spfy_billing_state", db.VarChar, spfy_billing_state)
161 | request.input("spfy_billing_province", db.VarChar, spfy_billing_province)
162 | request.input("spfy_billing_country", db.VarChar, spfy_billing_country)
163 | request.input("spfy_billing_phone", db.Int, spfy_billing_phone)
164 | request.input(
165 | "spfy_billing_province_name",
166 | db.VarChar,
167 | spfy_billing_province_name
168 | )
169 | request.input("spfy_shipping_name", db.VarChar, spfy_shipping_name)
170 | request.input("spfy_shipping_street", db.VarChar, spfy_shipping_street)
171 | request.input(
172 | "spfy_shipping_address_1",
173 | db.VarChar,
174 | spfy_shipping_address_1
175 | )
176 | request.input(
177 | "spfy_shipping_address_2",
178 | db.VarChar,
179 | spfy_shipping_address_2
180 | )
181 | request.input("spfy_shipping_company", db.VarChar, spfy_shipping_company)
182 | request.input("spfy_shipping_city", db.VarChar, spfy_shipping_city)
183 | request.input("spfy_shipping_zip", db.VarChar, spfy_shipping_zip)
184 | request.input("spfy_shipping_state", db.VarChar, spfy_shipping_state)
185 | request.input("spfy_shipping_province", db.VarChar, spfy_shipping_province)
186 | request.input(
187 | "spfy_shipping_province_name",
188 | db.VarChar,
189 | spfy_shipping_province_name
190 | )
191 | request.input("spfy_shipping_country", db.VarChar, spfy_shipping_country)
192 | request.input("spfy_shipping_phone", db.VarChar, spfy_shipping_phone)
193 | request.input("spfy_notes", db.VarChar, spfy_notes)
194 | request.input("spfy_note_attributes", db.VarChar, spfy_note_attributes)
195 | request.input("spfy_cancelled_at", db.DateTime, spfy_cancelled_at)
196 | request.input("spfy_payment_method", db.VarChar, spfy_payment_method)
197 | request.input(
198 | "spfy_payment_reference_id",
199 | db.VarChar,
200 | spfy_payment_reference_id
201 | )
202 | request.input("spfy_refunded_amount", db.Numeric, spfy_refunded_amount)
203 | request.input(
204 | "spfy_outstanding_balance",
205 | db.Numeric,
206 | spfy_outstanding_balance
207 | )
208 | request.input("spfy_employee", db.VarChar, spfy_employee)
209 | request.input("spfy_location", db.VarChar, spfy_location)
210 | request.input("spfy_device_id", db.Int, spfy_device_id)
211 | request.input("spfy_id", db.VarChar, spfy_id)
212 | request.input("spfy_risk_level", db.VarChar, spfy_risk_level)
213 | request.input("spfy_source", db.VarChar, spfy_source)
214 | request.input("spfy_tax_1_name", db.VarChar, spfy_tax_1_name)
215 | request.input("spfy_tax_1_amount", db.Numeric, spfy_tax_1_amount)
216 | request.input("spfy_tax_2_name", db.VarChar, spfy_tax_2_name)
217 | request.input("spfy_tax_2_amount", db.Numeric, spfy_tax_2_amount)
218 | request.input("spfy_tax_3_name", db.VarChar, spfy_tax_3_name)
219 | request.input("spfy_tax_3_amount", db.Numeric, spfy_tax_3_amount)
220 | request.input("spfy_tax_4_name", db.VarChar, spfy_tax_4_name)
221 | request.input("spfy_tax_4_amount", db.Numeric, spfy_tax_4_amount)
222 | request.input("spfy_tax_5_name", db.VarChar, spfy_tax_5_name)
223 | request.input("spfy_tax_5_amount", db.Numeric, spfy_tax_5_amount)
224 | request.input("spfy_phone", db.VarChar, spfy_phone)
225 | request.input("spfy_receipt_number", db.VarChar, spfy_receipt_number)
226 | request.input("spfy_duties", db.Numeric, spfy_duties)
227 | request.input(
228 | "spfy_payment_terms_name",
229 | db.VarChar,
230 | spfy_payment_terms_name
231 | )
232 | request.input(
233 | "spfy_next_payment_due_at",
234 | db.VarChar,
235 | spfy_next_payment_due_at
236 | )
237 | request.input("last_updated", db.DateTime, last_updated)
238 | request.input("spfy_json_response", db.VarChar, spfy_json_response)
239 |
240 | let query =
241 | "INSERT INTO spfyOrders(spfy_order_id, spfy_email, spfy_financial_status, spfy_paid_at, \
242 | spfy_fulfillment_status, spfy_fulfilled_at, spfy_accepts_marketing, spfy_currency, \
243 | spfy_subtotal, spfy_shipping, spfy_taxes, spfy_total, spfy_discount_amount, spfy_created_at, \
244 | spfy_billing_name, spfy_billing_street, spfy_billing_address_1, spfy_billing_address_2, \
245 | spfy_billing_company, spfy_billing_city, spfy_billing_zip, spfy_billing_state, spfy_billing_province, \
246 | spfy_shipping_name, spfy_shipping_street, spfy_shipping_address_1, spfy_shipping_address_2, spfy_shipping_company, \
247 | spfy_shipping_city, spfy_shipping_zip, spfy_shipping_state, spfy_shipping_province, spfy_shipping_province_name, \
248 | spfy_shipping_country, spfy_shipping_phone, spfy_notes, spfy_note_attributes, spfy_cancelled_at, \
249 | spfy_payment_method, spfy_payment_reference_id, spfy_refunded_amount, spfy_outstanding_balance, spfy_employee, \
250 | spfy_location, spfy_device_id, spfy_id, spfy_risk_level, spfy_source, spfy_tax_1_name,spfy_tax_1_amount, \
251 | spfy_tax_2_name, spfy_tax_2_amount, spfy_tax_3_name, spfy_tax_3_amount, spfy_tax_4_name, spfy_tax_4_amount, \
252 | spfy_tax_5_name, spfy_tax_5_amount, spfy_phone, spfy_receipt_number, spfy_duties, spfy_payment_terms_name, \
253 | spfy_next_payment_due_at, last_updated, spfy_json_response) VALUES (@spfy_order_id, @spfy_email, @spfy_financial_status, @spfy_paid_at, \
254 | @spfy_fulfillment_status, @spfy_fulfilled_at, @spfy_accepts_marketing, @spfy_currency, \
255 | @spfy_subtotal, @spfy_shipping, @spfy_taxes, @spfy_total, @spfy_discount_amount, @spfy_created_at, \
256 | @spfy_billing_name, @spfy_billing_street, @spfy_billing_address_1, @spfy_billing_address_2, \
257 | @spfy_billing_company, @spfy_billing_city, @spfy_billing_zip, @spfy_billing_state, @spfy_billing_province, \
258 | @spfy_shipping_name, @spfy_shipping_street, @spfy_shipping_address_1, @spfy_shipping_address_2, @spfy_shipping_company, \
259 | @spfy_shipping_city, @spfy_shipping_zip, @spfy_shipping_state, @spfy_shipping_province, @spfy_shipping_province_name, \
260 | @spfy_shipping_country, @spfy_shipping_phone, @spfy_notes, @spfy_note_attributes, @spfy_cancelled_at, \
261 | @spfy_payment_method, @spfy_payment_reference_id, @spfy_refunded_amount, @spfy_outstanding_balance, @spfy_employee, \
262 | @spfy_location, @spfy_device_id, @spfy_id, @spfy_risk_level, @spfy_source, @spfy_tax_1_name, @spfy_tax_1_amount, \
263 | @spfy_tax_2_name, @spfy_tax_2_amount, @spfy_tax_3_name, @spfy_tax_3_amount, @spfy_tax_4_name, @spfy_tax_4_amount, \
264 | @spfy_tax_5_name, @spfy_tax_5_amount, @spfy_phone, @spfy_receipt_number, @spfy_duties, @spfy_payment_terms_name, \
265 | @spfy_next_payment_due_at, @last_updated, @spfy_json_response)"
266 |
267 | request.query(query, (error, rows) => {
268 | if (error) {
269 | reject(error.message)
270 | } else {
271 | resolve(rows.recordset)
272 | }
273 | })
274 | })
275 | }
276 |
277 | function createOrderItem(
278 | order_id,
279 | created_at,
280 | qty,
281 | name,
282 | price,
283 | compare_at_price,
284 | sku,
285 | shipping,
286 | taxable,
287 | fulfillment_status,
288 | vendor,
289 | discount_amount,
290 | last_updated
291 | ) {
292 | var request = new db.Request()
293 | request.input("spfy_order_id", db.VarChar, order_id)
294 | request.input("spfy_created_at", db.DateTime, created_at)
295 | request.input("spfy_line_item_qty", db.Numeric, qty)
296 | request.input("spfy_line_item_name", db.VarChar, name)
297 | request.input("spfy_line_item_price", db.Numeric, price)
298 | request.input("spfy_line_item_compare_at_price", db.Numeric, compare_at_price)
299 | request.input("spfy_line_item_sku", db.VarChar, sku)
300 | request.input("spfy_line_item_taxable", db.VarChar, taxable)
301 | request.input("spfy_line_item_req_shipping", db.VarChar, shipping)
302 | request.input(
303 | "spfy_line_item_fulfillment_status",
304 | db.VarChar,
305 | fulfillment_status
306 | )
307 | request.input("spfy_line_item_discount_amount", db.Numeric, discount_amount)
308 | request.input("spfy_vendor", db.VarChar, vendor)
309 | request.input("last_updated", db.DateTime, last_updated)
310 |
311 | let subQuery =
312 | "INSERT INTO spfyOrderItems(spfy_order_id, spfy_created_at, spfy_line_item_qty, spfy_line_item_name, \
313 | spfy_line_item_price, spfy_line_item_compare_at_price, spfy_line_item_sku, spfy_line_item_taxable, \
314 | spfy_line_item_req_shipping, spfy_line_item_fulfillment_status, spfy_line_item_discount_amount, spfy_vendor, \
315 | last_updated) VALUES (@spfy_order_id, @spfy_created_at, @spfy_line_item_qty, @spfy_line_item_name, \
316 | @spfy_line_item_price, @spfy_line_item_compare_at_price, @spfy_line_item_sku, @spfy_line_item_taxable, \
317 | @spfy_line_item_req_shipping, @spfy_line_item_fulfillment_status, @spfy_line_item_discount_amount, @spfy_vendor, @last_updated)"
318 |
319 | return new Promise((resolve, reject) => {
320 | request.query(subQuery, (err, data) => {
321 | if (err) {
322 | reject(err.message)
323 | } else {
324 | resolve({ code: 200 })
325 | }
326 | })
327 | })
328 | }
329 |
330 | module.exports = orderModel
331 |
--------------------------------------------------------------------------------
/models/payout-model.js:
--------------------------------------------------------------------------------
1 | const db = require("../database/db")
2 |
3 | const payoutModel = {
4 | getPayouts: getPayouts,
5 | getPayoutDetailsByVendor: getPayoutDetailsByVendor,
6 | getPayoutByVendor: getPayoutByVendor,
7 | }
8 |
9 | function getPayouts(flag) {
10 | return new Promise((resolve, reject) => {
11 | var request = new db.Request()
12 |
13 | var date = new Date()
14 | var year = date.getFullYear()
15 | var month = ""
16 |
17 | //get first and last date
18 | if (flag == "BeforePayouts") {
19 | month = date.getMonth()
20 | } else {
21 | month = date.getMonth() + 1
22 | }
23 |
24 | const firstDate = new Date(year, month - 2, 0)
25 | const lastDate = new Date(year, month - 1, 1)
26 |
27 | request.input("firstDate", db.DateTime, firstDate)
28 | request.input("lastDate", db.DateTime, lastDate)
29 |
30 | let query =
31 | "SELECT distinct(spfy_vendor), sum(spfy_line_item_qty) as items_sold, \
32 | format((sum(spfy_line_item_qty * spfy_line_item_price)), 'C') as total_sales, defaultPercentage, \
33 | format(sum(spfy_line_item_qty * spfy_line_item_price * defaultPercentage/100), 'C') as net_sales from tstSpfyOrderItems items \
34 | inner join consignors csn on csn.qbCompany = items.spfy_vendor \
35 | where spfy_created_at > @firstDate and spfy_created_at < @lastDate \
36 | group by spfy_vendor, defaultPercentage \
37 | order by total_sales desc"
38 |
39 | request.query(query, (error, rows) => {
40 | if (error) {
41 | reject(error.message)
42 | } else {
43 | resolve(rows.recordset)
44 | }
45 | })
46 | })
47 | }
48 |
49 | function getPayoutDetailsByVendor(vendor) {
50 | return new Promise((resolve, reject) => {
51 | var request = new db.Request()
52 |
53 | //get first and last date
54 | var date = new Date()
55 | var month = date.getMonth() + 1
56 | var year = date.getFullYear()
57 | const firstDate = new Date(year, month - 2, 0)
58 | const lastDate = new Date(year, month - 1, 1)
59 |
60 | request.input("firstDate", db.DateTime, firstDate)
61 | request.input("lastDate", db.DateTime, lastDate)
62 | request.input("vendor", db.VarChar, vendor)
63 |
64 | let query =
65 | "SELECT spfy_order_id, spfy_line_item_name, spfy_line_item_qty, spfy_line_item_price, spfy_line_item_qty * spfy_line_item_price as total_amount, defaultPercentage, \
66 | format((defaultPercentage / 100 * spfy_line_item_qty * spfy_line_item_price), 'C') as net_amount from tstSpfyOrderItems items \
67 | inner join consignors csn on csn.qbCompany = items.spfy_vendor where spfy_vendor=@vendor and spfy_created_at > @firstDate and spfy_created_at < @lastDate \
68 | group by spfy_order_id, spfy_vendor, spfy_line_item_name, defaultPercentage, spfy_line_item_price, spfy_line_item_qty \
69 | order by total_amount desc"
70 |
71 | request.query(query, (error, rows) => {
72 | if (error) {
73 | reject(error.message)
74 | } else {
75 | resolve(rows.recordset)
76 | }
77 | })
78 | })
79 | }
80 |
81 | function getPayoutByVendor(vendor) {
82 | return new Promise((resolve, reject) => {
83 | var request = new db.Request()
84 |
85 | //get first and last date
86 | var date = new Date()
87 | var month = date.getMonth() + 1
88 | var year = date.getFullYear()
89 | const firstDate = new Date(year, month - 2, 0)
90 | const lastDate = new Date(year, month - 1, 1)
91 |
92 | request.input("firstDate", db.DateTime, firstDate)
93 | request.input("lastDate", db.DateTime, lastDate)
94 | request.input("vendor", db.VarChar, vendor)
95 |
96 | let query =
97 | "SELECT distinct(spfy_vendor), sum(spfy_line_item_qty) as items_sold, \
98 | format(sum(spfy_line_item_qty * spfy_line_item_price), 'C') as total_sales, \
99 | defaultPercentage, sum(spfy_line_item_qty * spfy_line_item_price * defaultPercentage/100) as net_sales from tstSpfyOrderItems items \
100 | inner join consignors csn on csn.qbCompany = items.spfy_vendor where spfy_created_at > @firstDate and spfy_created_at < @lastDate and spfy_vendor=@vendor \
101 | group by spfy_vendor, defaultPercentage \
102 | order by total_sales desc"
103 |
104 | request.query(query, (error, rows) => {
105 | if (error) {
106 | reject(error.message)
107 | } else {
108 | resolve(rows.recordset)
109 | }
110 | })
111 | })
112 | }
113 |
114 | module.exports = payoutModel
115 |
--------------------------------------------------------------------------------
/models/product-model.js:
--------------------------------------------------------------------------------
1 | const db = require("../database/db")
2 | const shopify = require("../services/shopify")
3 | const azureStorage = require("azure-storage")
4 | const getStream = require("into-stream")
5 |
6 | const blobService = azureStorage.createBlobService(
7 | process.env.AZURE_ACCOUNT_NAME,
8 | process.env.AZURE_ACCOUNT_KEY
9 | )
10 |
11 | uploadFileToBlob = async (directoryPath, title, file) => {
12 | return new Promise((resolve, reject) => {
13 | const blobName = file.originalname
14 | const stream = getStream(file.buffer)
15 | const streamLength = file.buffer.length
16 |
17 | blobService.createBlockBlobFromStream(
18 | process.env.AZURE_CONTAINER_NAME,
19 | `${directoryPath}/${title}/${blobName}`,
20 | stream,
21 | streamLength,
22 | err => {
23 | if (err) {
24 | reject(err)
25 | } else {
26 | resolve({
27 | filename: blobName,
28 | originalname: file.originalname,
29 | size: streamLength,
30 | path: `${process.env.AZURE_CONTAINER_NAME}/${directoryPath}/${title}/${blobName}`,
31 | url: `${process.env.AZURE_BLOB_URL}${process.env.AZURE_CONTAINER_NAME}/${directoryPath}/${title}/${blobName}`,
32 | })
33 | }
34 | }
35 | )
36 | })
37 | }
38 |
39 | const productModel = {
40 | getAllProducts: getAllProducts,
41 | getProductById: getProductById,
42 | getProductsByVendor: getProductsByVendor,
43 | setProducts: setProducts,
44 | updateProducts: updateProducts,
45 | deleteProduct: deleteProduct,
46 | }
47 |
48 | function getAllProducts() {
49 | return new Promise((resolve, reject) => {
50 | var request = new db.Request()
51 | let query = "SELECT * FROM products"
52 |
53 | request.query(query, (error, rows) => {
54 | if (error) {
55 | reject(error.message)
56 | } else {
57 | resolve(rows.recordset)
58 | }
59 | })
60 | })
61 | }
62 |
63 | function getProductById(id) {
64 | const product_id = id
65 | return new Promise((resolve, reject) => {
66 | var request = new db.Request()
67 | request.input("product_id", db.Int, product_id)
68 | let query = "SELECT * FROM products WHERE product_id=@product_id"
69 |
70 | request.query(query, (error, rows) => {
71 | var shopify_id = ""
72 | if (error) {
73 | reject(error.message)
74 | } else {
75 | shopify_id = rows.recordset[0].shopify_id
76 | shopify.get(
77 | "/admin/products/" + shopify_id + ".json",
78 | function (err, product_data, headers) {
79 | var product = product_data.product
80 | // send records as a response
81 | resolve({ data: rows.recordset[0], shopifyData: product })
82 | }
83 | )
84 | }
85 | })
86 | })
87 | }
88 |
89 | function getProductsByVendor(vendor) {
90 | return new Promise((resolve, reject) => {
91 | var request = new db.Request()
92 | request.input("vendor", db.VarChar, vendor)
93 | let query = "SELECT * FROM products WHERE vendor=@vendor"
94 |
95 | request.query(query, (error, rows) => {
96 | if (error) {
97 | reject(error.message)
98 | } else {
99 | resolve({ data: rows.recordset })
100 | }
101 | })
102 | })
103 | }
104 |
105 | function setProducts(req, shopify_id) {
106 | //Assign value to variable of product from request
107 | const title = req.body.title
108 | const consignor_id = req.body.consignor_id
109 | const description = req.body.description
110 | const product_type = req.body.product_type
111 | const size = req.body.size
112 | const color = req.body.color
113 | const material = req.body.material
114 | const price = req.body.price
115 | const base_price = req.body.base_price
116 | const notes = req.body.notes
117 | const published_at = req.body.published_at
118 | const discountSchedule = req.body.discountSchedule
119 |
120 | var request = new db.Request()
121 | var datetime = new Date()
122 | var images = ""
123 |
124 | //setting variables for mssql
125 | request.input("consignor_id", db.Int, consignor_id)
126 | request.input("title", db.VarChar, title)
127 | request.input("description", db.VarChar, description)
128 | request.input("product_type", db.VarChar, product_type)
129 | request.input("base_price", db.Numeric, base_price)
130 | request.input("size", db.Int, size)
131 | request.input("color", db.VarChar, color)
132 | request.input("material", db.VarChar, material)
133 | request.input("price", db.Numeric, price)
134 | request.input("notes", db.VarChar, notes)
135 | request.input("published_at", db.VarChar, published_at)
136 | request.input("discountSchedule", db.VarChar, discountSchedule)
137 | request.input("datetime", db.DateTime, datetime)
138 | request.input("shopify_id", db.VarChar, shopify_id)
139 |
140 | for (var i = 0; i < req.files.length; i++) {
141 | images += req.files[i].originalname + ","
142 | uploadFileToBlob("products", title, req.files[i])
143 | }
144 |
145 | let query =
146 | "INSERT INTO products(consignorID, shopify_id, vendor, title, description, product_type, size, color, material, price, base_price, notes, published_at, discountSchedule, created_at, updated_at, main_img_src) VALUES (@consignor_id, @shopify_id, 'Tacoma Consignment', @title, @description, @product_type, @size, @color, @material, @price, @base_price, @notes, @published_at, @discountSchedule, @datetime, @datetime, @main_img_src)"
147 |
148 | request.input("main_img_src", db.VarChar, images)
149 | return new Promise((resolve, reject) => {
150 | request.query(query, function (err, rows) {
151 | if (err) {
152 | reject(error.message)
153 | } else {
154 | resolve({ code: 200 })
155 | }
156 | })
157 | })
158 | }
159 |
160 | function updateProducts(req) {
161 | var request = new db.Request()
162 | const title = req.body.title
163 | const product_id = req.body.product_id
164 | var images = ""
165 |
166 | var datetime = new Date()
167 |
168 | const consignor_id = req.body.consignor_id
169 | const description = req.body.description
170 | const product_type = req.body.product_type
171 | const size = req.body.size
172 | const color = req.body.color
173 | const material = req.body.material
174 | const price = req.body.price
175 | const base_price = req.body.base_price
176 | const notes = req.body.notes
177 | const published_at = req.body.published_at
178 | const discountSchedule = req.body.discountSchedule
179 | const status = req.body.status
180 |
181 | const shopify_published_at = new Date(published_at)
182 |
183 | request.input("consignor_id", db.Int, consignor_id)
184 | request.input("title", db.VarChar, title)
185 | request.input("description", db.VarChar, description)
186 | request.input("product_type", db.VarChar, product_type)
187 | request.input("base_price", db.Numeric, base_price)
188 | request.input("size", db.Int, size)
189 | request.input("color", db.VarChar, color)
190 | request.input("material", db.VarChar, material)
191 | request.input("price", db.Numeric, price)
192 | request.input("notes", db.VarChar, notes)
193 | request.input("published_at", db.VarChar, published_at)
194 | request.input("discountSchedule", db.VarChar, discountSchedule)
195 | request.input("datetime", db.DateTime, datetime)
196 | request.input("status", db.VarChar, status)
197 |
198 | request.input("product_id", db.Int, product_id)
199 | return new Promise((resolve, reject) => {
200 | request.query(
201 | "SELECT main_img_src, title, shopify_id FROM products WHERE product_id=@product_id",
202 | function (err, data) {
203 | if (err) console.log(err)
204 | var old_images = data.recordset[0].main_img_src
205 | var old_title = data.recordset[0].title
206 | var shopify_id = data.recordset[0].shopify_id
207 |
208 | var updated_data = {
209 | product: {
210 | id: shopify_id,
211 | title: title,
212 | body_html: description,
213 | vendor: "Tacoma Consignment",
214 | product_type: product_type,
215 | published_at: shopify_published_at,
216 | },
217 | }
218 |
219 | var image_array = old_images.split(",")
220 | const blobPath = "products/" + old_title + "/"
221 | for (let i = 0; i < image_array.length - 1; i++) {
222 | var imageBlob = blobPath + image_array[i]
223 | blobService.deleteBlob(
224 | process.env.AZURE_CONTAINER_NAME,
225 | imageBlob,
226 | function (error, response) {
227 | if (!error) {
228 | console.log("deleted!")
229 | }
230 | }
231 | )
232 | }
233 |
234 | shopify.get(
235 | "/admin/products/" + shopify_id + ".json",
236 | function (error, shopify_data) {
237 | var temp_images = shopify_data.product.images
238 | var temp_variants = shopify_data.product.variants
239 | for (let i = 0; i < temp_images.length; i++) {
240 | shopify.delete(
241 | "/admin/products/" +
242 | shopify_id +
243 | "/images/" +
244 | temp_images[i].id +
245 | ".json",
246 | function (error, shopify_data) {
247 | console.log("deleted!")
248 | }
249 | )
250 | }
251 | for (let i = 0; i < temp_variants.length; i++) {
252 | shopify.delete(
253 | "/admin/products/" +
254 | shopify_id +
255 | "/variants/" +
256 | temp_variants[i].id +
257 | ".json",
258 | function (error, shopify_data) {
259 | console.log("deleted!")
260 | }
261 | )
262 | }
263 |
264 | for (var i = 0; i < req.files.length; i++) {
265 | images += req.files[i].originalname + ","
266 | var tempImage = {
267 | image: {
268 | position: i + 1,
269 | attachment: req.files[i].buffer.toString("base64"),
270 | width: 640,
271 | height: 480,
272 | filename: req.files[i].originalname,
273 | },
274 | }
275 | shopify.post(
276 | "/admin/products/" + shopify_id + "/images.json",
277 | tempImage,
278 | function (error, shopify_data) {
279 | console.log(shopify_data)
280 | }
281 | )
282 | uploadFileToBlob("products", title, req.files[i])
283 | }
284 |
285 | var tempVariant = {
286 | variant: {
287 | Color: color,
288 | Size: size,
289 | },
290 | }
291 |
292 | shopify.post(
293 | "admin/products/" + shopify_id + "/variants.json",
294 | tempVariant,
295 | function (error, shopify_data) {
296 | console.log(shopify_data)
297 | }
298 | )
299 |
300 | request.input("main_img_src", db.VarChar, images)
301 |
302 | shopify.put(
303 | "/admin/products/" + shopify_id + ".json",
304 | updated_data,
305 | function (error, shopify_data) {
306 | request.query(
307 | "UPDATE products SET consignorID=@consignor_id, title=@title, description=@description, product_type=@product_type, \
308 | size=@size, color=@color, material=@material, price=@price, notes=@notes, published_at=@published_at, discountSchedule=@discountSchedule, status=@status,\
309 | updated_at=@datetime, main_img_src=@main_img_src, base_price=@base_price WHERE product_id=@product_id",
310 | function (err, rows) {
311 | if (err) console.log(err.message)
312 | // send records as a response
313 | resolve({ code: 200 })
314 | }
315 | )
316 | }
317 | )
318 | }
319 | )
320 | }
321 | )
322 | })
323 | }
324 |
325 | function deleteProduct(req) {
326 | var request = new db.Request()
327 | const product_id = req.query.product_id
328 | const title = req.query.title
329 | const blobPath = "products/" + title + "/"
330 | request.input("product_id", db.Int, product_id)
331 | return new Promise((resolve, reject) => {
332 | request.query(
333 | "SELECT main_img_src, shopify_id FROM products WHERE product_id=@product_id",
334 | function (err, data) {
335 | if (err) console.log(err)
336 | var images = data.recordset[0].main_img_src
337 | var shopify_id = data.recordset[0].shopify_id
338 | var image_array = images.split(",")
339 | for (let i = 0; i < image_array.length - 1; i++) {
340 | var imageBlob = blobPath + image_array[i]
341 | blobService.deleteBlob(
342 | process.env.AZURE_CONTAINER_NAME,
343 | imageBlob,
344 | function (error, response) {
345 | if (!error) {
346 | console.log("deleted!")
347 | }
348 | }
349 | )
350 | }
351 | shopify.delete(
352 | "/admin/products/" + shopify_id + ".json",
353 | function (error, shopify_data, headers) {
354 | request.query(
355 | "DELETE FROM products WHERE product_id=@product_id",
356 | function (err, data) {
357 | if (err) reject(error.message)
358 | // send records as a response
359 | resolve({ code: 200 })
360 | }
361 | )
362 | }
363 | )
364 | }
365 | )
366 | })
367 | }
368 |
369 | module.exports = productModel
370 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tconsignment-system-api",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "server.js",
6 | "scripts": {
7 | "start": "nodemon server.js",
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "azure-storage": "^2.10.4",
14 | "body-parser": "^1.19.0",
15 | "cors": "^2.8.5",
16 | "dotenv": "^10.0.0",
17 | "express": "^4.17.1",
18 | "express-jwt": "^6.0.0",
19 | "express-jwt-authz": "^2.4.1",
20 | "into-stream": "^3.1.0",
21 | "jwks-rsa": "^1.6.0",
22 | "mssql": "^7.2.1",
23 | "multer": "^1.4.3",
24 | "nodemon": "^2.0.12",
25 | "shopify-node-api": "^1.5.2"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/public/products/photo_2021-08-19_18-51-02.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elitedev201/Vue-shopify-api-integration/18111e9aa61c28c0034c4cae1f190d6972d3af84/public/products/photo_2021-08-19_18-51-02.jpg
--------------------------------------------------------------------------------
/public/products/photo_2021-08-19_18-51-12.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elitedev201/Vue-shopify-api-integration/18111e9aa61c28c0034c4cae1f190d6972d3af84/public/products/photo_2021-08-19_18-51-12.jpg
--------------------------------------------------------------------------------
/routes/consignors.js:
--------------------------------------------------------------------------------
1 | var router = require("express").Router()
2 | const checkAuth = require("../middleware/auth")
3 | const consignorService = require("../services/consignorService")
4 |
5 | router.get("/consignors", getAllConsignors)
6 | router.post("/consignor", addConsignor)
7 | router.put("/consignor", updateConsignor)
8 | router.get("/consignorbyid", getConsignorById)
9 | router.get("/consignor", getConsignorByVendor)
10 | router.delete("/consignor", deleteConsignor)
11 |
12 | function getAllConsignors(req, res) {
13 | consignorService
14 | .getAllConsignors()
15 | .then(result => {
16 | res.json(result)
17 | })
18 | .catch(err => {
19 | res.json(err)
20 | })
21 | }
22 |
23 | function addConsignor(req, res) {
24 | var data = req.body
25 | consignorService
26 | .addConsignor(data)
27 | .then(result => {
28 | res.json(result)
29 | })
30 | .catch(err => {
31 | res.json(err)
32 | })
33 | }
34 |
35 | function updateConsignor(req, res) {
36 | var data = req.body
37 | consignorService
38 | .updateConsignor(data)
39 | .then(result => {
40 | res.json(result)
41 | })
42 | .catch(err => {
43 | res.json(err)
44 | })
45 | }
46 |
47 | function getConsignorById(req, res) {
48 | const id = req.query.id
49 | consignorService
50 | .getConsignorById(id)
51 | .then(result => {
52 | res.json(result)
53 | })
54 | .catch(err => {
55 | res.json(err)
56 | })
57 | }
58 |
59 | function getConsignorByVendor(req, res) {
60 | const vendor = req.query.vendor
61 | consignorService
62 | .getConsignorByVendor(vendor)
63 | .then(result => {
64 | res.json(result)
65 | })
66 | .catch(err => {
67 | res.json(err)
68 | })
69 | }
70 |
71 | function deleteConsignor(req, res) {
72 | const id = req.query.id
73 | consignorService
74 | .delConsignor(id)
75 | .then(result => {
76 | res.json(result)
77 | })
78 | .catch(err => {
79 | res.json(err)
80 | })
81 | }
82 |
83 | module.exports = router
84 |
--------------------------------------------------------------------------------
/routes/index.js:
--------------------------------------------------------------------------------
1 | var router = require("express").Router()
2 |
3 | const products = require('./products')
4 | const consignors = require('./consignors')
5 | const orders = require('./orders')
6 | const payouts = require('./payouts')
7 |
8 | router.use(products)
9 | router.use(consignors)
10 | router.use(orders)
11 | router.use(payouts)
12 |
13 | router.get("/", (req, res) => {
14 | res.send(`Hi! Server is listening on port ${process.env.PORT}`)
15 | })
16 |
17 | router.use(function (err, req, res, next) {
18 | if (err.name === "ValidationError") {
19 | return res.status(422).json({
20 | errors: Object.keys(err.errors).reduce(function (errors, key) {
21 | errors[key] = err.errors[key].message
22 |
23 | return errors
24 | }, {}),
25 | })
26 | }
27 |
28 | return next(err)
29 | })
30 |
31 | module.exports = router
--------------------------------------------------------------------------------
/routes/orders.js:
--------------------------------------------------------------------------------
1 | var router = require("express").Router()
2 | const checkAuth = require("../middleware/auth")
3 | const orderService = require("../services/orderService")
4 |
5 | //webhook routes
6 | router.post("/order/create", createOrders)
7 |
8 | // router.post("/order/update", (req, res) => {
9 | // console.log(req.body)
10 | // })
11 |
12 | // router.post("/order/delete", (req, res) => {
13 | // console.log(req.body)
14 | // })
15 |
16 | // router.post("/order/cancel", (req, res) => {
17 | // console.log(req.body)
18 | // })
19 |
20 | // router.post("/order/fulfillment", (req, res) => {
21 | // console.log(req.body)
22 | // })
23 |
24 | // router.post("/order/payment", (req, res) => {
25 | // console.log(req.body)
26 | // })
27 |
28 | // router.post("/order/create", createOrders)
29 |
30 | function createOrders(req, res) {
31 | orderService
32 | .createOrders(req)
33 | .then(result => {
34 | res.json(result)
35 | })
36 | .catch(err => {
37 | res.json(err)
38 | })
39 | }
40 |
41 | module.exports = router
42 |
--------------------------------------------------------------------------------
/routes/payouts.js:
--------------------------------------------------------------------------------
1 | var router = require("express").Router()
2 | const checkAuth = require("../middleware/auth")
3 | const checkPermissions = require("../middleware/permission")
4 | const payoutService = require("../services/payoutService")
5 |
6 | router.get("/payouts", checkAuth, checkPermissions, getPayouts)
7 | router.get("/payout_details", getPayoutDetailsByVendor)
8 | router.get("/payout", getPayoutByVendor)
9 |
10 | function getPayouts(req, res) {
11 | payoutService
12 | .getPayouts(req.query.flag)
13 | .then(result => {
14 | res.json(result)
15 | })
16 | .catch(err => {
17 | res.json(err)
18 | })
19 | }
20 |
21 | function getPayoutDetailsByVendor(req, res) {
22 | const vendor = req.query.vendor
23 | payoutService
24 | .getPayoutDetailsByVendor(vendor)
25 | .then(result => {
26 | res.json(result)
27 | })
28 | .catch(err => {
29 | res.json(err)
30 | })
31 | }
32 |
33 | function getPayoutByVendor(req, res) {
34 | const vendor = req.query.vendor
35 | payoutService
36 | .getPayoutByVendor(vendor)
37 | .then(result => {
38 | res.json(result)
39 | })
40 | .catch(err => {
41 | res.json(err)
42 | })
43 | }
44 |
45 | module.exports = router
46 |
--------------------------------------------------------------------------------
/routes/products.js:
--------------------------------------------------------------------------------
1 | var router = require("express").Router()
2 | const multer = require("multer")
3 | const checkAuth = require("../middleware/auth")
4 |
5 | const productService = require("../services/productService")
6 |
7 | const inMemoryStorage = multer.memoryStorage()
8 | const uploadStrategy = multer({ storage: inMemoryStorage }).array("files", 10)
9 |
10 | // router.get("/products", checkJwt, (req, res) => {
11 | // res.send(data)
12 | // })
13 |
14 | router.get("/products", checkAuth, getAllProducts)
15 | router.get("/product", getProductById)
16 | router.get("/productsbyvendor", getProductsByVendor)
17 | router.post("/products", uploadStrategy, setProducts)
18 | router.put("/products", uploadStrategy, updateProducts)
19 | router.delete("/products", deleteProduct)
20 |
21 | //get all product info from mssql
22 | function getAllProducts(req, res) {
23 | productService
24 | .getAllProducts()
25 | .then(result => {
26 | res.json(result)
27 | })
28 | .catch(err => {
29 | res.json(err)
30 | })
31 | }
32 |
33 | //get product info by product_id from shopify and mssql
34 | function getProductById(req, res) {
35 | const product_id = req.query.product_id
36 | productService
37 | .getProductById(product_id)
38 | .then(result => {
39 | res.json(result)
40 | })
41 | .catch(err => {
42 | res.json(err)
43 | })
44 | }
45 |
46 | //get products info by vendor from shopify and mssql
47 | function getProductsByVendor(req, res) {
48 | const vendor = req.query.vendor
49 | productService
50 | .getProductsByVendor(vendor)
51 | .then(result => {
52 | res.json(result)
53 | })
54 | .catch(err => {
55 | res.json(err)
56 | })
57 | }
58 |
59 | //Adding product info to shopify and mssql
60 | function setProducts(req, res) {
61 | productService
62 | .setProducts(req)
63 | .then(result => {
64 | res.json(result)
65 | })
66 | .catch(err => {
67 | res.json(err)
68 | })
69 | }
70 |
71 | //updating product on shopify and mssql
72 | function updateProducts(req, res) {
73 | productService
74 | .updateProducts(req)
75 | .then(result => {
76 | res.json(result)
77 | })
78 | .catch(err => {
79 | res.json(err)
80 | })
81 | }
82 |
83 | //delete product from shopify and mssql
84 | function deleteProduct(req, res) {
85 | productService
86 | .deleteProduct(req)
87 | .then(result => {
88 | res.json(result)
89 | })
90 | .catch(err => {
91 | res.json(err)
92 | })
93 | }
94 |
95 | module.exports = router
96 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | // server/server/js
2 | const express = require("express")
3 | const bodyParser = require("body-parser")
4 | const cors = require("cors")
5 | const app = express()
6 | const sql = require("mssql")
7 | const dotenvConf = require("dotenv").config()
8 |
9 | app.use(bodyParser.json())
10 | app.use(cors())
11 | app.use(express.urlencoded({ extended: true }))
12 |
13 | app.use(require("./routes"))
14 |
15 | // config for your database
16 | const config = {
17 | user: process.env.DB_USER,
18 | password: process.env.DB_PASS,
19 | server: process.env.DB_HOST,
20 | database: process.env.DB_NAME,
21 | options: {
22 | trustedConnection: true,
23 | encrypt: true,
24 | enableArithAbort: true,
25 | trustServerCertificate: true,
26 | },
27 | }
28 |
29 |
30 | //connect to mssql
31 | sql.connect(config)
32 |
33 | // listen on the port
34 | app.listen(process.env.PORT || 8000)
35 |
--------------------------------------------------------------------------------
/server/.env:
--------------------------------------------------------------------------------
1 | # MSSQL config
2 | DB_HOST=tconsign21.database.windows.net
3 | DB_USER=tcadmin
4 | DB_PASS=Over 12,000 sq. ft. of finds!
5 | DB_NAME=tconsign
6 | PORT=8000
7 |
8 | # Auth0 config
9 | AUTH0_DOMAIN=eclectico.us.auth0.com
10 | AUTH0_AUDIENCE=https://tacomaconsignment.com
11 |
12 | # Azure blob config
13 | AZURE_ACCOUNT_NAME=cs410032000dc000ac4
14 | AZURE_ACCOUNT_KEY=Rk5OZVd7RIUSZjHt1yg/YGRVgnf+NzM33hyNWvC3SOJQgiPBktph+G9DBTN+jPQzP+3cCCdutyYg1cbKGoIUrw==
15 | AZURE_BLOB_URL=https://cs410032000dc000ac4.blob.core.windows.net
16 | AZURE_CONTAINER_NAME=testcontainer
17 |
18 | # Shopify config
19 | SHOPIFY_API_KEY=fa4f8443ab7b37f4803230a8aebbb7b2
20 | SHOPIFY_PASSWORD=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
21 | SHOPIFY_SHOP_NAME=spfy-connection-app-store.myshopify.com
22 | SHOPIFY_ACCESS_TOKEN=prtapi_66df9304cda675601c68025aeac9a208
--------------------------------------------------------------------------------
/server/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 | auth_config.json
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 |
15 | # Editor directories and files
16 | .idea
17 | .vscode
18 | *.suo
19 | *.ntvs*
20 | *.njsproj
21 | *.sln
22 | *.sw?
23 |
--------------------------------------------------------------------------------
/server/database/config.js:
--------------------------------------------------------------------------------
1 |
2 | // config for your mssql
3 | const config = {
4 | user: process.env.DB_USER,
5 | password: process.env.DB_PASS,
6 | server: process.env.DB_HOST,
7 | database: process.env.DB_NAME,
8 | options: {
9 | trustedConnection: true,
10 | encrypt: true,
11 | enableArithAbort: true,
12 | trustServerCertificate: true,
13 | },
14 | }
15 |
16 | module.exports = config
--------------------------------------------------------------------------------
/server/database/db.js:
--------------------------------------------------------------------------------
1 | const sql = require("mssql")
2 | const databaseConfig = require('./config')
3 |
4 | sql.connect(databaseConfig)
5 |
6 | module.exports = sql
7 |
--------------------------------------------------------------------------------
/server/middleware/auth.js:
--------------------------------------------------------------------------------
1 | const jwt = require("express-jwt")
2 | const jwksRsa = require("jwks-rsa")
3 |
4 | // Create middleware to validate the JWT using express-jwt
5 | const checkJwt = jwt({
6 | // Provide a signing key based on the key identifier in the header and the signing keys provided by your Auth0 JWKS endpoint.
7 | secret: jwksRsa.expressJwtSecret({
8 | cache: true,
9 | rateLimit: true,
10 | jwksRequestsPerMinute: 5,
11 | jwksUri: `https://${process.env.AUTH0_DOMAIN}/.well-known/jwks.json`,
12 | }),
13 |
14 | // Validate the audience (Identifier) and the issuer (Domain).
15 | audience: process.env.AUTH0_AUDIENCE,
16 | issuer: `https://${process.env.AUTH0_DOMAIN}/`,
17 | algorithms: ["RS256"],
18 | })
19 |
20 | module.exports = checkJwt
--------------------------------------------------------------------------------
/server/middleware/permission.js:
--------------------------------------------------------------------------------
1 | const jwtAuthz = require("express-jwt-authz")
2 |
3 | const checkPermissions = jwtAuthz(["manage:users"], {
4 | customScopeKey: "permissions",
5 | })
6 |
7 | module.exports = checkPermissions
--------------------------------------------------------------------------------
/server/models/consignor-model.js:
--------------------------------------------------------------------------------
1 | const db = require("../database/db")
2 |
3 | const consignorModel = {
4 | getAllConsignors: getAllConsignors,
5 | addConsignor: addConsignor,
6 | updateConsignor: updateConsignor,
7 | getConsignorById: getConsignorById,
8 | getConsignorByVendor: getConsignorByVendor,
9 | delConsignor: delConsignor,
10 | }
11 |
12 | function getAllConsignors() {
13 | return new Promise((resolve, reject) => {
14 | var request = new db.Request()
15 | let query = "SELECT * FROM consignors"
16 |
17 | request.query(query, (error, rows) => {
18 | if (error) {
19 | reject(error.message)
20 | } else {
21 | resolve(rows.recordset)
22 | }
23 | })
24 | })
25 | }
26 |
27 | function addConsignor(data) {
28 | var request = new db.Request()
29 | request.input("qbCompany", db.VarChar, data.company)
30 | request.input("defaultPercentage", db.Numeric, 50)
31 | request.input("qbFirst", db.VarChar, data.first)
32 | request.input("qbLast", db.VarChar, data.last)
33 | request.input("qbStAddress1", db.VarChar, data.stAddress1)
34 | request.input("qbStAddress2", db.VarChar, data.stAddress2)
35 | request.input("qbCity", db.VarChar, data.city)
36 | request.input("qbState", db.VarChar, data.state)
37 | request.input("qbZip", db.VarChar, data.zip)
38 | request.input("qbEmail", db.VarChar, data.email)
39 | request.input("qbPhone", db.VarChar, data.phone)
40 | let query =
41 | "INSERT INTO consignors(qbCompany, defaultPercentage, qbFirst, qbLast, qbStAddress1, qbStAddress2, qbCity, qbState, qbZip, qbEmail, qbPhone ) VALUES (@qbCompany, @defaultPercentage, @qbFirst, @qbLast, @qbStAddress1, @qbStAddress2, @qbCity, @qbState, @qbZip, @qbEmail, @qbPhone)"
42 |
43 | return new Promise((resolve, reject) => {
44 | request.query(query, (error, rows) => {
45 | if (error) {
46 | reject(error.message)
47 | } else {
48 | resolve({ code: 200 })
49 | }
50 | })
51 | })
52 | }
53 |
54 | function updateConsignor(data) {
55 | var request = new db.Request()
56 | request.input("id", db.VarChar, data.id)
57 | request.input("qbCompany", db.VarChar, data.company)
58 | request.input("qbFirst", db.VarChar, data.first)
59 | request.input("qbLast", db.VarChar, data.last)
60 | request.input("qbStAddress1", db.VarChar, data.stAddress1)
61 | request.input("qbStAddress2", db.VarChar, data.stAddress2)
62 | request.input("qbCity", db.VarChar, data.city)
63 | request.input("qbState", db.VarChar, data.state)
64 | request.input("qbZip", db.VarChar, data.zip)
65 | request.input("qbEmail", db.VarChar, data.email)
66 | request.input("qbPhone", db.VarChar, data.phone)
67 | let query =
68 | "UPDATE consignors SET qbCompany=@qbCompany, qbFirst=@qbFirst, qbLast=@qbLast, qbStAddress1=@qbStAddress1, qbStAddress2=@qbStAddress2, qbCity=@qbCity, qbState=@qbState, qbZip=@qbZip, qbEmail=@qbEmail, qbPhone=@qbPhone WHERE id=@id"
69 |
70 | return new Promise((resolve, reject) => {
71 | request.query(query, (error, rows) => {
72 | if (error) {
73 | reject(error.message)
74 | } else {
75 | resolve({ code: 200 })
76 | }
77 | })
78 | })
79 | }
80 |
81 | function delConsignor(id) {
82 | return new Promise((resolve, reject) => {
83 | var request = new db.Request()
84 | request.input("id", db.Int, id)
85 | let query = "DELETE FROM consignors WHERE id=@id"
86 |
87 | request.query(query, (error, rows) => {
88 | if (error) {
89 | reject(error.message)
90 | } else {
91 | resolve(rows.recordset)
92 | }
93 | })
94 | })
95 | }
96 |
97 | function getConsignorById(id) {
98 | return new Promise((resolve, reject) => {
99 | var request = new db.Request()
100 | request.input("id", db.Int, id)
101 | let query =
102 | "SELECT * FROM consignors WHERE id=@id"
103 |
104 | request.query(query, (error, rows) => {
105 | if (error) {
106 | reject(error.message)
107 | } else {
108 | resolve(rows.recordset)
109 | }
110 | })
111 | })
112 | }
113 |
114 | function getConsignorByVendor(vendor) {
115 | return new Promise((resolve, reject) => {
116 | var request = new db.Request()
117 | request.input("vendor", db.VarChar, vendor)
118 | let query =
119 | "SELECT id, qbCompany, defaultPercentage, qbStAddress1, qbStAddress2, (qbCity + ', ' + qbState + ' ' + qbZip) as bottom_line FROM consignors WHERE qbCompany=@vendor"
120 |
121 | request.query(query, (error, rows) => {
122 | if (error) {
123 | reject(error.message)
124 | } else {
125 | resolve(rows.recordset)
126 | }
127 | })
128 | })
129 | }
130 |
131 | module.exports = consignorModel
132 |
--------------------------------------------------------------------------------
/server/models/payout-model.js:
--------------------------------------------------------------------------------
1 | const db = require("../database/db")
2 |
3 | const payoutModel = {
4 | getPayouts: getPayouts,
5 | getPayoutDetailsByVendor: getPayoutDetailsByVendor,
6 | getPayoutByVendor: getPayoutByVendor,
7 | }
8 |
9 | function getPayouts(flag) {
10 | return new Promise((resolve, reject) => {
11 | var request = new db.Request()
12 |
13 | var date = new Date()
14 | var year = date.getFullYear()
15 | var month = ""
16 |
17 | //get first and last date
18 | if (flag == "BeforePayouts") {
19 | month = date.getMonth()
20 | } else {
21 | month = date.getMonth() + 1
22 | }
23 |
24 | const firstDate = new Date(year, month - 2, 0)
25 | const lastDate = new Date(year, month - 1, 1)
26 |
27 | request.input("firstDate", db.DateTime, firstDate)
28 | request.input("lastDate", db.DateTime, lastDate)
29 |
30 | let query =
31 | "SELECT distinct(spfy_vendor), sum(spfy_line_item_qty) as items_sold, \
32 | format((sum(spfy_line_item_qty * spfy_line_item_price)), 'C') as total_sales, defaultPercentage, \
33 | format(sum(spfy_line_item_qty * spfy_line_item_price * defaultPercentage/100), 'C') as net_sales from tstSpfyOrderItems items \
34 | inner join consignors csn on csn.qbCompany = items.spfy_vendor \
35 | where spfy_created_at > @firstDate and spfy_created_at < @lastDate \
36 | group by spfy_vendor, defaultPercentage \
37 | order by total_sales desc"
38 |
39 | request.query(query, (error, rows) => {
40 | if (error) {
41 | reject(error.message)
42 | } else {
43 | resolve(rows.recordset)
44 | }
45 | })
46 | })
47 | }
48 |
49 | function getPayoutDetailsByVendor(vendor) {
50 | return new Promise((resolve, reject) => {
51 | var request = new db.Request()
52 |
53 | //get first and last date
54 | var date = new Date()
55 | var month = date.getMonth() + 1
56 | var year = date.getFullYear()
57 | const firstDate = new Date(year, month - 2, 0)
58 | const lastDate = new Date(year, month - 1, 1)
59 |
60 | request.input("firstDate", db.DateTime, firstDate)
61 | request.input("lastDate", db.DateTime, lastDate)
62 | request.input("vendor", db.VarChar, vendor)
63 |
64 | let query =
65 | "SELECT spfy_order_id, spfy_line_item_name, spfy_line_item_qty, spfy_line_item_price, spfy_line_item_qty * spfy_line_item_price as total_amount, defaultPercentage, \
66 | format((defaultPercentage / 100 * spfy_line_item_qty * spfy_line_item_price), 'C') as net_amount from tstSpfyOrderItems items \
67 | inner join consignors csn on csn.qbCompany = items.spfy_vendor where spfy_vendor=@vendor and spfy_created_at > @firstDate and spfy_created_at < @lastDate \
68 | group by spfy_order_id, spfy_vendor, spfy_line_item_name, defaultPercentage, spfy_line_item_price, spfy_line_item_qty \
69 | order by total_amount desc"
70 |
71 | request.query(query, (error, rows) => {
72 | if (error) {
73 | reject(error.message)
74 | } else {
75 | resolve(rows.recordset)
76 | }
77 | })
78 | })
79 | }
80 |
81 | function getPayoutByVendor(vendor) {
82 | return new Promise((resolve, reject) => {
83 | var request = new db.Request()
84 |
85 | //get first and last date
86 | var date = new Date()
87 | var month = date.getMonth() + 1
88 | var year = date.getFullYear()
89 | const firstDate = new Date(year, month - 2, 0)
90 | const lastDate = new Date(year, month - 1, 1)
91 |
92 | request.input("firstDate", db.DateTime, firstDate)
93 | request.input("lastDate", db.DateTime, lastDate)
94 | request.input("vendor", db.VarChar, vendor)
95 |
96 | let query =
97 | "SELECT distinct(spfy_vendor), sum(spfy_line_item_qty) as items_sold, \
98 | format(sum(spfy_line_item_qty * spfy_line_item_price), 'C') as total_sales, \
99 | defaultPercentage, sum(spfy_line_item_qty * spfy_line_item_price * defaultPercentage/100) as net_sales from tstSpfyOrderItems items \
100 | inner join consignors csn on csn.qbCompany = items.spfy_vendor where spfy_created_at > @firstDate and spfy_created_at < @lastDate and spfy_vendor=@vendor \
101 | group by spfy_vendor, defaultPercentage \
102 | order by total_sales desc"
103 |
104 | request.query(query, (error, rows) => {
105 | if (error) {
106 | reject(error.message)
107 | } else {
108 | resolve(rows.recordset)
109 | }
110 | })
111 | })
112 | }
113 |
114 | module.exports = payoutModel
115 |
--------------------------------------------------------------------------------
/server/models/product-model.js:
--------------------------------------------------------------------------------
1 | const db = require("../database/db")
2 | const shopify = require("../services/shopify")
3 | const azureStorage = require("azure-storage")
4 | const getStream = require("into-stream")
5 |
6 | const blobService = azureStorage.createBlobService(
7 | process.env.AZURE_ACCOUNT_NAME,
8 | process.env.AZURE_ACCOUNT_KEY
9 | )
10 |
11 | uploadFileToBlob = async (directoryPath, title, file) => {
12 | return new Promise((resolve, reject) => {
13 | const blobName = file.originalname
14 | const stream = getStream(file.buffer)
15 | const streamLength = file.buffer.length
16 |
17 | blobService.createBlockBlobFromStream(
18 | process.env.AZURE_CONTAINER_NAME,
19 | `${directoryPath}/${title}/${blobName}`,
20 | stream,
21 | streamLength,
22 | err => {
23 | if (err) {
24 | reject(err)
25 | } else {
26 | resolve({
27 | filename: blobName,
28 | originalname: file.originalname,
29 | size: streamLength,
30 | path: `${process.env.AZURE_CONTAINER_NAME}/${directoryPath}/${title}/${blobName}`,
31 | url: `${process.env.AZURE_BLOB_URL}${process.env.AZURE_CONTAINER_NAME}/${directoryPath}/${title}/${blobName}`,
32 | })
33 | }
34 | }
35 | )
36 | })
37 | }
38 |
39 | const productModel = {
40 | getAllProducts: getAllProducts,
41 | getProductById: getProductById,
42 | getProductsByVendor: getProductsByVendor,
43 | setProducts: setProducts,
44 | updateProducts: updateProducts,
45 | deleteProduct: deleteProduct,
46 | }
47 |
48 | function getAllProducts() {
49 | return new Promise((resolve, reject) => {
50 | var request = new db.Request()
51 | let query = "SELECT * FROM products"
52 |
53 | request.query(query, (error, rows) => {
54 | if (error) {
55 | reject(error.message)
56 | } else {
57 | resolve(rows.recordset)
58 | }
59 | })
60 | })
61 | }
62 |
63 | function getProductById(id) {
64 | const product_id = id
65 | return new Promise((resolve, reject) => {
66 | var request = new db.Request()
67 | request.input("product_id", db.Int, product_id)
68 | let query = "SELECT * FROM products WHERE product_id=@product_id"
69 |
70 | request.query(query, (error, rows) => {
71 | var shopify_id = ""
72 | if (error) {
73 | reject(error.message)
74 | } else {
75 | shopify_id = rows.recordset[0].shopify_id
76 | shopify.get(
77 | "/admin/products/" + shopify_id + ".json",
78 | function (err, product_data, headers) {
79 | var product = product_data.product
80 | // send records as a response
81 | resolve({ data: rows.recordset[0], shopifyData: product })
82 | }
83 | )
84 | }
85 | })
86 | })
87 | }
88 |
89 | function getProductsByVendor(vendor) {
90 | return new Promise((resolve, reject) => {
91 | var request = new db.Request()
92 | request.input("vendor", db.VarChar, vendor)
93 | let query = "SELECT * FROM products WHERE vendor=@vendor"
94 |
95 | request.query(query, (error, rows) => {
96 | if (error) {
97 | reject(error.message)
98 | } else {
99 | resolve({ data: rows.recordset })
100 | }
101 | })
102 | })
103 | }
104 |
105 | function setProducts(req, shopify_id) {
106 | //Assign value to variable of product from request
107 | const title = req.body.title
108 | const consignor_id = req.body.consignor_id
109 | const description = req.body.description
110 | const product_type = req.body.product_type
111 | const size = req.body.size
112 | const color = req.body.color
113 | const material = req.body.material
114 | const price = req.body.price
115 | const base_price = req.body.base_price
116 | const notes = req.body.notes
117 | const published_at = req.body.published_at
118 | const discountSchedule = req.body.discountSchedule
119 |
120 | var request = new db.Request()
121 | var datetime = new Date()
122 | var images = ""
123 |
124 | //setting variables for mssql
125 | request.input("consignor_id", db.Int, consignor_id)
126 | request.input("title", db.VarChar, title)
127 | request.input("description", db.VarChar, description)
128 | request.input("product_type", db.VarChar, product_type)
129 | request.input("base_price", db.Numeric, base_price)
130 | request.input("size", db.Int, size)
131 | request.input("color", db.VarChar, color)
132 | request.input("material", db.VarChar, material)
133 | request.input("price", db.Numeric, price)
134 | request.input("notes", db.VarChar, notes)
135 | request.input("published_at", db.VarChar, published_at)
136 | request.input("discountSchedule", db.VarChar, discountSchedule)
137 | request.input("datetime", db.DateTime, datetime)
138 | request.input("shopify_id", db.VarChar, shopify_id)
139 |
140 | for (var i = 0; i < req.files.length; i++) {
141 | images += req.files[i].originalname + ","
142 | uploadFileToBlob("products", title, req.files[i])
143 | }
144 |
145 | let query =
146 | "INSERT INTO products(consignorID, shopify_id, vendor, title, description, product_type, size, color, material, price, base_price, notes, published_at, discountSchedule, created_at, updated_at, main_img_src) VALUES (@consignor_id, @shopify_id, 'Tacoma Consignment', @title, @description, @product_type, @size, @color, @material, @price, @base_price, @notes, @published_at, @discountSchedule, @datetime, @datetime, @main_img_src)"
147 |
148 | request.input("main_img_src", db.VarChar, images)
149 | return new Promise((resolve, reject) => {
150 | request.query(query, function (err, rows) {
151 | if (err) {
152 | reject(error.message)
153 | } else {
154 | resolve({ code: 200 })
155 | }
156 | })
157 | })
158 | }
159 |
160 | function updateProducts(req) {
161 | var request = new db.Request()
162 | const title = req.body.title
163 | const product_id = req.body.product_id
164 | var images = ""
165 |
166 | var datetime = new Date()
167 |
168 | const consignor_id = req.body.consignor_id
169 | const description = req.body.description
170 | const product_type = req.body.product_type
171 | const size = req.body.size
172 | const color = req.body.color
173 | const material = req.body.material
174 | const price = req.body.price
175 | const base_price = req.body.base_price
176 | const notes = req.body.notes
177 | const published_at = req.body.published_at
178 | const discountSchedule = req.body.discountSchedule
179 | const status = req.body.status
180 |
181 | const shopify_published_at = new Date(published_at)
182 |
183 | request.input("consignor_id", db.Int, consignor_id)
184 | request.input("title", db.VarChar, title)
185 | request.input("description", db.VarChar, description)
186 | request.input("product_type", db.VarChar, product_type)
187 | request.input("base_price", db.Numeric, base_price)
188 | request.input("size", db.Int, size)
189 | request.input("color", db.VarChar, color)
190 | request.input("material", db.VarChar, material)
191 | request.input("price", db.Numeric, price)
192 | request.input("notes", db.VarChar, notes)
193 | request.input("published_at", db.VarChar, published_at)
194 | request.input("discountSchedule", db.VarChar, discountSchedule)
195 | request.input("datetime", db.DateTime, datetime)
196 | request.input("status", db.VarChar, status)
197 |
198 | request.input("product_id", db.Int, product_id)
199 | return new Promise((resolve, reject) => {
200 | request.query(
201 | "SELECT main_img_src, title, shopify_id FROM products WHERE product_id=@product_id",
202 | function (err, data) {
203 | if (err) console.log(err)
204 | var old_images = data.recordset[0].main_img_src
205 | var old_title = data.recordset[0].title
206 | var shopify_id = data.recordset[0].shopify_id
207 |
208 | var updated_data = {
209 | product: {
210 | id: shopify_id,
211 | title: title,
212 | body_html: description,
213 | vendor: "Tacoma Consignment",
214 | product_type: product_type,
215 | published_at: shopify_published_at,
216 | },
217 | }
218 |
219 | var image_array = old_images.split(",")
220 | const blobPath = "products/" + old_title + "/"
221 | for (let i = 0; i < image_array.length - 1; i++) {
222 | var imageBlob = blobPath + image_array[i]
223 | blobService.deleteBlob(
224 | process.env.AZURE_CONTAINER_NAME,
225 | imageBlob,
226 | function (error, response) {
227 | if (!error) {
228 | console.log("deleted!")
229 | }
230 | }
231 | )
232 | }
233 |
234 | shopify.get(
235 | "/admin/products/" + shopify_id + ".json",
236 | function (error, shopify_data) {
237 | var temp_images = shopify_data.product.images
238 | var temp_variants = shopify_data.product.variants
239 | for (let i = 0; i < temp_images.length; i++) {
240 | shopify.delete(
241 | "/admin/products/" +
242 | shopify_id +
243 | "/images/" +
244 | temp_images[i].id +
245 | ".json",
246 | function (error, shopify_data) {
247 | console.log("deleted!")
248 | }
249 | )
250 | }
251 | for (let i = 0; i < temp_variants.length; i++) {
252 | shopify.delete(
253 | "/admin/products/" +
254 | shopify_id +
255 | "/variants/" +
256 | temp_variants[i].id +
257 | ".json",
258 | function (error, shopify_data) {
259 | console.log("deleted!")
260 | }
261 | )
262 | }
263 |
264 | for (var i = 0; i < req.files.length; i++) {
265 | images += req.files[i].originalname + ","
266 | var tempImage = {
267 | image: {
268 | position: i + 1,
269 | attachment: req.files[i].buffer.toString("base64"),
270 | width: 640,
271 | height: 480,
272 | filename: req.files[i].originalname,
273 | },
274 | }
275 | shopify.post(
276 | "/admin/products/" + shopify_id + "/images.json",
277 | tempImage,
278 | function (error, shopify_data) {
279 | console.log(shopify_data)
280 | }
281 | )
282 | uploadFileToBlob("products", title, req.files[i])
283 | }
284 |
285 | var tempVariant = {
286 | variant: {
287 | Color: color,
288 | Size: size,
289 | },
290 | }
291 |
292 | shopify.post(
293 | "admin/products/" + shopify_id + "/variants.json",
294 | tempVariant,
295 | function (error, shopify_data) {
296 | console.log(shopify_data)
297 | }
298 | )
299 |
300 | request.input("main_img_src", db.VarChar, images)
301 |
302 | shopify.put(
303 | "/admin/products/" + shopify_id + ".json",
304 | updated_data,
305 | function (error, shopify_data) {
306 | request.query(
307 | "UPDATE products SET consignorID=@consignor_id, title=@title, description=@description, product_type=@product_type, \
308 | size=@size, color=@color, material=@material, price=@price, notes=@notes, published_at=@published_at, discountSchedule=@discountSchedule, status=@status,\
309 | updated_at=@datetime, main_img_src=@main_img_src, base_price=@base_price WHERE product_id=@product_id",
310 | function (err, rows) {
311 | if (err) console.log(err.message)
312 | // send records as a response
313 | resolve({ code: 200 })
314 | }
315 | )
316 | }
317 | )
318 | }
319 | )
320 | }
321 | )
322 | })
323 | }
324 |
325 | function deleteProduct(req) {
326 | var request = new db.Request()
327 | const product_id = req.query.product_id
328 | const title = req.query.title
329 | const blobPath = "products/" + title + "/"
330 | request.input("product_id", db.Int, product_id)
331 | return new Promise((resolve, reject) => {
332 | request.query(
333 | "SELECT main_img_src, shopify_id FROM products WHERE product_id=@product_id",
334 | function (err, data) {
335 | if (err) console.log(err)
336 | var images = data.recordset[0].main_img_src
337 | var shopify_id = data.recordset[0].shopify_id
338 | var image_array = images.split(",")
339 | for (let i = 0; i < image_array.length - 1; i++) {
340 | var imageBlob = blobPath + image_array[i]
341 | blobService.deleteBlob(
342 | process.env.AZURE_CONTAINER_NAME,
343 | imageBlob,
344 | function (error, response) {
345 | if (!error) {
346 | console.log("deleted!")
347 | }
348 | }
349 | )
350 | }
351 | shopify.delete(
352 | "/admin/products/" + shopify_id + ".json",
353 | function (error, shopify_data, headers) {
354 | request.query(
355 | "DELETE FROM products WHERE product_id=@product_id",
356 | function (err, data) {
357 | if (err) reject(error.message)
358 | // send records as a response
359 | resolve({ code: 200 })
360 | }
361 | )
362 | }
363 | )
364 | }
365 | )
366 | })
367 | }
368 |
369 | module.exports = productModel
370 |
--------------------------------------------------------------------------------
/server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tconsignment-system-api",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "server.js",
6 | "scripts": {
7 | "start": "nodemon server.js",
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "azure-storage": "^2.10.4",
14 | "body-parser": "^1.19.0",
15 | "cors": "^2.8.5",
16 | "dotenv": "^10.0.0",
17 | "express": "^4.17.1",
18 | "express-jwt": "^6.0.0",
19 | "express-jwt-authz": "^2.4.1",
20 | "into-stream": "^3.1.0",
21 | "jwks-rsa": "^1.6.0",
22 | "mssql": "^7.2.1",
23 | "multer": "^1.4.3",
24 | "nodemon": "^2.0.12",
25 | "shopify-node-api": "^1.5.2"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/server/public/products/photo_2021-08-19_18-51-02.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elitedev201/Vue-shopify-api-integration/18111e9aa61c28c0034c4cae1f190d6972d3af84/server/public/products/photo_2021-08-19_18-51-02.jpg
--------------------------------------------------------------------------------
/server/public/products/photo_2021-08-19_18-51-12.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elitedev201/Vue-shopify-api-integration/18111e9aa61c28c0034c4cae1f190d6972d3af84/server/public/products/photo_2021-08-19_18-51-12.jpg
--------------------------------------------------------------------------------
/server/routes/consignors.js:
--------------------------------------------------------------------------------
1 | var router = require("express").Router()
2 | const checkAuth = require("../middleware/auth")
3 | const consignorService = require("../services/consignorService")
4 |
5 | router.get("/consignors", getAllConsignors)
6 | router.post("/consignor", addConsignor)
7 | router.put("/consignor", updateConsignor)
8 | router.get("/consignorbyid", getConsignorById)
9 | router.get("/consignor", getConsignorByVendor)
10 | router.delete("/consignor", deleteConsignor)
11 |
12 | function getAllConsignors(req, res) {
13 | consignorService
14 | .getAllConsignors()
15 | .then(result => {
16 | res.json(result)
17 | })
18 | .catch(err => {
19 | res.json(err)
20 | })
21 | }
22 |
23 | function addConsignor(req, res) {
24 | var data = req.body
25 | consignorService
26 | .addConsignor(data)
27 | .then(result => {
28 | res.json(result)
29 | })
30 | .catch(err => {
31 | res.json(err)
32 | })
33 | }
34 |
35 | function updateConsignor(req, res) {
36 | var data = req.body
37 | consignorService
38 | .updateConsignor(data)
39 | .then(result => {
40 | res.json(result)
41 | })
42 | .catch(err => {
43 | res.json(err)
44 | })
45 | }
46 |
47 | function getConsignorById(req, res) {
48 | const id = req.query.id
49 | consignorService
50 | .getConsignorById(id)
51 | .then(result => {
52 | res.json(result)
53 | })
54 | .catch(err => {
55 | res.json(err)
56 | })
57 | }
58 |
59 | function getConsignorByVendor(req, res) {
60 | const vendor = req.query.vendor
61 | consignorService
62 | .getConsignorByVendor(vendor)
63 | .then(result => {
64 | res.json(result)
65 | })
66 | .catch(err => {
67 | res.json(err)
68 | })
69 | }
70 |
71 | function deleteConsignor(req, res) {
72 | const id = req.query.id
73 | consignorService
74 | .delConsignor(id)
75 | .then(result => {
76 | res.json(result)
77 | })
78 | .catch(err => {
79 | res.json(err)
80 | })
81 | }
82 |
83 | module.exports = router
84 |
--------------------------------------------------------------------------------
/server/routes/index.js:
--------------------------------------------------------------------------------
1 | var router = require("express").Router()
2 |
3 | const products = require('./products')
4 | const consignors = require('./consignors')
5 | const orders = require('./orders')
6 | const payouts = require('./payouts')
7 |
8 | router.use(products)
9 | router.use(consignors)
10 | router.use(orders)
11 | router.use(payouts)
12 |
13 | router.get("/", (req, res) => {
14 | res.send(`Hi! Server is listening on port ${process.env.PORT}`)
15 | })
16 |
17 | router.use(function (err, req, res, next) {
18 | if (err.name === "ValidationError") {
19 | return res.status(422).json({
20 | errors: Object.keys(err.errors).reduce(function (errors, key) {
21 | errors[key] = err.errors[key].message
22 |
23 | return errors
24 | }, {}),
25 | })
26 | }
27 |
28 | return next(err)
29 | })
30 |
31 | module.exports = router
--------------------------------------------------------------------------------
/server/routes/orders.js:
--------------------------------------------------------------------------------
1 | var router = require("express").Router()
2 | const checkAuth = require("../middleware/auth")
3 | const orderService = require("../services/orderService")
4 |
5 | //webhook routes
6 | router.post("/order/create", createOrders)
7 |
8 | // router.post("/order/update", (req, res) => {
9 | // console.log(req.body)
10 | // })
11 |
12 | // router.post("/order/delete", (req, res) => {
13 | // console.log(req.body)
14 | // })
15 |
16 | // router.post("/order/cancel", (req, res) => {
17 | // console.log(req.body)
18 | // })
19 |
20 | // router.post("/order/fulfillment", (req, res) => {
21 | // console.log(req.body)
22 | // })
23 |
24 | // router.post("/order/payment", (req, res) => {
25 | // console.log(req.body)
26 | // })
27 |
28 | // router.post("/order/create", createOrders)
29 |
30 | function createOrders(req, res) {
31 | orderService
32 | .createOrders(req)
33 | .then(result => {
34 | res.json(result)
35 | })
36 | .catch(err => {
37 | res.json(err)
38 | })
39 | }
40 |
41 | module.exports = router
42 |
--------------------------------------------------------------------------------
/server/routes/payouts.js:
--------------------------------------------------------------------------------
1 | var router = require("express").Router()
2 | const checkAuth = require("../middleware/auth")
3 | const checkPermissions = require("../middleware/permission")
4 | const payoutService = require("../services/payoutService")
5 |
6 | router.get("/payouts", checkAuth, checkPermissions, getPayouts)
7 | router.get("/payout_details", getPayoutDetailsByVendor)
8 | router.get("/payout", getPayoutByVendor)
9 |
10 | function getPayouts(req, res) {
11 | payoutService
12 | .getPayouts(req.query.flag)
13 | .then(result => {
14 | res.json(result)
15 | })
16 | .catch(err => {
17 | res.json(err)
18 | })
19 | }
20 |
21 | function getPayoutDetailsByVendor(req, res) {
22 | const vendor = req.query.vendor
23 | payoutService
24 | .getPayoutDetailsByVendor(vendor)
25 | .then(result => {
26 | res.json(result)
27 | })
28 | .catch(err => {
29 | res.json(err)
30 | })
31 | }
32 |
33 | function getPayoutByVendor(req, res) {
34 | const vendor = req.query.vendor
35 | payoutService
36 | .getPayoutByVendor(vendor)
37 | .then(result => {
38 | res.json(result)
39 | })
40 | .catch(err => {
41 | res.json(err)
42 | })
43 | }
44 |
45 | module.exports = router
46 |
--------------------------------------------------------------------------------
/server/routes/products.js:
--------------------------------------------------------------------------------
1 | var router = require("express").Router()
2 | const multer = require("multer")
3 | const checkAuth = require("../middleware/auth")
4 |
5 | const productService = require("../services/productService")
6 |
7 | const inMemoryStorage = multer.memoryStorage()
8 | const uploadStrategy = multer({ storage: inMemoryStorage }).array("files", 10)
9 |
10 | // router.get("/products", checkJwt, (req, res) => {
11 | // res.send(data)
12 | // })
13 |
14 | router.get("/products", checkAuth, getAllProducts)
15 | router.get("/product", getProductById)
16 | router.get("/productsbyvendor", getProductsByVendor)
17 | router.post("/products", uploadStrategy, setProducts)
18 | router.put("/products", uploadStrategy, updateProducts)
19 | router.delete("/products", deleteProduct)
20 |
21 | //get all product info from mssql
22 | function getAllProducts(req, res) {
23 | productService
24 | .getAllProducts()
25 | .then(result => {
26 | res.json(result)
27 | })
28 | .catch(err => {
29 | res.json(err)
30 | })
31 | }
32 |
33 | //get product info by product_id from shopify and mssql
34 | function getProductById(req, res) {
35 | const product_id = req.query.product_id
36 | productService
37 | .getProductById(product_id)
38 | .then(result => {
39 | res.json(result)
40 | })
41 | .catch(err => {
42 | res.json(err)
43 | })
44 | }
45 |
46 | //get products info by vendor from shopify and mssql
47 | function getProductsByVendor(req, res) {
48 | const vendor = req.query.vendor
49 | productService
50 | .getProductsByVendor(vendor)
51 | .then(result => {
52 | res.json(result)
53 | })
54 | .catch(err => {
55 | res.json(err)
56 | })
57 | }
58 |
59 | //Adding product info to shopify and mssql
60 | function setProducts(req, res) {
61 | productService
62 | .setProducts(req)
63 | .then(result => {
64 | res.json(result)
65 | })
66 | .catch(err => {
67 | res.json(err)
68 | })
69 | }
70 |
71 | //updating product on shopify and mssql
72 | function updateProducts(req, res) {
73 | productService
74 | .updateProducts(req)
75 | .then(result => {
76 | res.json(result)
77 | })
78 | .catch(err => {
79 | res.json(err)
80 | })
81 | }
82 |
83 | //delete product from shopify and mssql
84 | function deleteProduct(req, res) {
85 | productService
86 | .deleteProduct(req)
87 | .then(result => {
88 | res.json(result)
89 | })
90 | .catch(err => {
91 | res.json(err)
92 | })
93 | }
94 |
95 | module.exports = router
96 |
--------------------------------------------------------------------------------
/server/server.js:
--------------------------------------------------------------------------------
1 | // server/server/js
2 | const express = require("express")
3 | const bodyParser = require("body-parser")
4 | const cors = require("cors")
5 | const app = express()
6 | const sql = require("mssql")
7 | const dotenvConf = require("dotenv").config()
8 |
9 | app.use(bodyParser.json())
10 | app.use(cors())
11 | app.use(express.urlencoded({ extended: true }))
12 |
13 | app.use(require("./routes"))
14 |
15 | // config for your database
16 | const config = {
17 | user: process.env.DB_USER,
18 | password: process.env.DB_PASS,
19 | server: process.env.DB_HOST,
20 | database: process.env.DB_NAME,
21 | options: {
22 | trustedConnection: true,
23 | encrypt: true,
24 | enableArithAbort: true,
25 | trustServerCertificate: true,
26 | },
27 | }
28 |
29 |
30 | //connect to mssql
31 | sql.connect(config)
32 |
33 | // listen on the port
34 | app.listen(process.env.PORT || 8000)
35 |
--------------------------------------------------------------------------------
/server/services/consignorService.js:
--------------------------------------------------------------------------------
1 | const consignorModel = require("../models/consignor-model")
2 |
3 | const consignorService = {
4 | getAllConsignors: getAllConsignors,
5 | addConsignor: addConsignor,
6 | updateConsignor: updateConsignor,
7 | getConsignorById: getConsignorById,
8 | getConsignorByVendor: getConsignorByVendor,
9 | delConsignor: delConsignor,
10 | }
11 |
12 | function getAllConsignors() {
13 | return new Promise((resolve, reject) => {
14 | consignorModel
15 | .getAllConsignors()
16 | .then(data => {
17 | resolve({ code: 200, data })
18 | })
19 | .catch(err => {
20 | reject(err.message)
21 | })
22 | })
23 | }
24 |
25 | function addConsignor(consignor_data) {
26 | return new Promise((resolve, reject) => {
27 | consignorModel
28 | .addConsignor(consignor_data)
29 | .then(data => {
30 | resolve({ code: 200 })
31 | })
32 | .catch(err => {
33 | reject(err.message)
34 | })
35 | })
36 | }
37 |
38 | function updateConsignor(consignor_data) {
39 | return new Promise((resolve, reject) => {
40 | consignorModel
41 | .updateConsignor(consignor_data)
42 | .then(data => {
43 | resolve({ code: 200 })
44 | })
45 | .catch(err => {
46 | reject(err.message)
47 | })
48 | })
49 | }
50 |
51 | function getConsignorById(id) {
52 | return new Promise((resolve, reject) => {
53 | consignorModel
54 | .getConsignorById(id)
55 | .then(data => {
56 | resolve({ code: 200, data })
57 | })
58 | .catch(err => {
59 | reject(err.message)
60 | })
61 | })
62 | }
63 |
64 | function getConsignorByVendor(vendor) {
65 | return new Promise((resolve, reject) => {
66 | consignorModel
67 | .getConsignorByVendor(vendor)
68 | .then(data => {
69 | resolve({ code: 200, data })
70 | })
71 | .catch(err => {
72 | reject(err.message)
73 | })
74 | })
75 | }
76 |
77 | function delConsignor(id) {
78 | return new Promise((resolve, reject) => {
79 | consignorModel
80 | .delConsignor(id)
81 | .then(data => {
82 | resolve({ code: 200, data })
83 | })
84 | .catch(err => {
85 | reject(err.message)
86 | })
87 | })
88 | }
89 |
90 | module.exports = consignorService
91 |
--------------------------------------------------------------------------------
/server/services/orderService.js:
--------------------------------------------------------------------------------
1 | const orderModel = require("../models/order-model")
2 | const shopify = require("./shopify")
3 |
4 | const orderService = {
5 | createOrders: createOrders,
6 | }
7 |
8 | function createOrders(req) {
9 | return new Promise((resolve, reject) => {
10 | var order_id = req.body.name
11 | var created_at = req.body.created_at
12 | var qty = 0
13 | var name = ""
14 | var price = 0
15 | var compare_at_price = ""
16 | var sku = ""
17 | var shipping = ""
18 | var taxable = ""
19 | var fulfillment_status = ""
20 | var vendor = ""
21 | var discount_amount = 0
22 | var last_updated = req.body.updated_at
23 | orderModel
24 | .createOrders(req)
25 | .then(data => {
26 | for (let i = 0; i < req.body.line_items.length; i++) {
27 | qty = req.body.line_items[i].quantity
28 | name = req.body.line_items[i].name
29 | price = req.body.line_items[i].price
30 | compare_at_price = 0
31 | sku = req.body.line_items[i].sku
32 | shipping = req.body.line_items[i].requires_shipping
33 | taxable = req.body.line_items[i].taxable
34 | fulfillment_status = req.body.line_items[i].fulfillment_status
35 | vendor = req.body.line_items[i].vendor
36 | orderModel
37 | .createOrderItem(
38 | order_id,
39 | created_at,
40 | qty,
41 | name,
42 | price,
43 | compare_at_price,
44 | sku,
45 | shipping,
46 | taxable,
47 | fulfillment_status,
48 | vendor,
49 | discount_amount,
50 | last_updated
51 | )
52 | .then(data => {
53 | console.log(data)
54 | })
55 | .catch(err => {
56 | reject(err.message)
57 | console.log(err)
58 | })
59 | }
60 | console.log(data)
61 | })
62 | .catch(err => {
63 | reject(err.message)
64 | console.log(err)
65 | })
66 |
67 | resolve({ code: 200 })
68 | })
69 | }
70 |
71 | module.exports = orderService
72 |
--------------------------------------------------------------------------------
/server/services/payoutService.js:
--------------------------------------------------------------------------------
1 | const payoutModel = require("../models/payout-model")
2 |
3 | const payoutService = {
4 | getPayouts: getPayouts,
5 | getPayoutDetailsByVendor: getPayoutDetailsByVendor,
6 | getPayoutByVendor: getPayoutByVendor,
7 | }
8 |
9 | function getPayouts(flag) {
10 | return new Promise((resolve, reject) => {
11 | payoutModel
12 | .getPayouts(flag)
13 | .then(data => {
14 | resolve({ code: 200, data })
15 | })
16 | .catch(err => {
17 | reject(err.message)
18 | console.log(err)
19 | })
20 | })
21 | }
22 |
23 | function getPayoutDetailsByVendor(vendor) {
24 | return new Promise((resolve, reject) => {
25 | payoutModel
26 | .getPayoutDetailsByVendor(vendor)
27 | .then(data => {
28 | resolve({ code: 200, data })
29 | })
30 | .catch(err => {
31 | reject(err.message)
32 | console.log(err)
33 | })
34 | })
35 | }
36 |
37 | function getPayoutByVendor(vendor) {
38 | return new Promise((resolve, reject) => {
39 | payoutModel
40 | .getPayoutByVendor(vendor)
41 | .then(data => {
42 | resolve({ code: 200, data })
43 | })
44 | .catch(err => {
45 | reject(err.message)
46 | console.log(err)
47 | })
48 | })
49 | }
50 |
51 | module.exports = payoutService
52 |
--------------------------------------------------------------------------------
/server/services/productService.js:
--------------------------------------------------------------------------------
1 | const productModel = require("../models/product-model")
2 | const shopify = require("./shopify")
3 |
4 | const productService = {
5 | getAllProducts: getAllProducts,
6 | getProductById: getProductById,
7 | getProductsByVendor: getProductsByVendor,
8 | setProducts: setProducts,
9 | updateProducts: updateProducts,
10 | deleteProduct: deleteProduct,
11 | }
12 |
13 | function getAllProducts() {
14 | return new Promise((resolve, reject) => {
15 | shopify.get(
16 | "/admin/products.json",
17 | function (error, shopify_data, headers) {
18 | var products = shopify_data.products
19 | productModel
20 | .getAllProducts()
21 | .then(data => {
22 | resolve({ code: 200, data: data, shopifyData: products })
23 | })
24 | .catch(err => {
25 | reject(err.message)
26 | })
27 | }
28 | )
29 | })
30 | }
31 |
32 | function getProductById(id) {
33 | const product_id = id
34 | return new Promise((resolve, reject) => {
35 | productModel
36 | .getProductById(product_id)
37 | .then(data => {
38 | resolve({ code: 200, data: data.data, shopifyData: data.shopifyData })
39 | })
40 | .catch(err => {
41 | reject(err.message)
42 | })
43 | })
44 | }
45 |
46 | function getProductsByVendor(vendor) {
47 | return new Promise((resolve, reject) => {
48 | productModel
49 | .getProductsByVendor(vendor)
50 | .then(data => {
51 | resolve({ code: 200, data: data.data, shopifyData: data.shopifyData })
52 | })
53 | .catch(err => {
54 | reject(err.message)
55 | })
56 | })
57 | }
58 |
59 | function setProducts(req) {
60 | const title = req.body.title
61 | const description = req.body.description
62 | const product_type = req.body.product_type
63 | const size = req.body.size
64 | const color = req.body.color
65 | const price = req.body.price
66 | const published_at = req.body.published_at
67 | const shopify_published_at = new Date(published_at)
68 |
69 | //declare post_data for adding product to shopify
70 | var post_data = {
71 | product: {
72 | title: title,
73 | body_html: description,
74 | vendor: "Tacoma Consignment",
75 | product_type: product_type,
76 | published_at: shopify_published_at,
77 | variants: [
78 | {
79 | Color: color,
80 | Size: size,
81 | price: price,
82 | },
83 | ],
84 | images: [],
85 | },
86 | }
87 |
88 | for (var i = 0; i < req.files.length; i++) {
89 | var tempImage = {
90 | position: i + 1,
91 | attachment: req.files[i].buffer.toString("base64"),
92 | width: 640,
93 | height: 480,
94 | filename: req.files[i].originalname,
95 | }
96 | post_data.product.images.push(tempImage)
97 | }
98 |
99 | return new Promise((resolve, reject) => {
100 | //adding products to shopify
101 | shopify.post(
102 | "/admin/products.json",
103 | post_data,
104 | function (error, shopify_data, headers) {
105 | var shopify_id = shopify_data.product.id
106 | productModel
107 | .setProducts(req, shopify_id)
108 | .then(data => {
109 | resolve({ code: 200, data: shopify_data })
110 | })
111 | .catch(err => {
112 | reject(err.message)
113 | })
114 | }
115 | )
116 | })
117 | }
118 |
119 | function updateProducts(req) {
120 | return new Promise((resolve, reject) => {
121 | //updating products to shopify and mssql
122 | productModel
123 | .updateProducts(req)
124 | .then(data => {
125 | resolve({ code: 200 })
126 | })
127 | .catch(err => {
128 | reject(err.message)
129 | })
130 | })
131 | }
132 |
133 | function deleteProduct(req) {
134 | return new Promise((resolve, reject) => {
135 | //delete product from shopify and mssql
136 | productModel
137 | .deleteProduct(req)
138 | .then(data => {
139 | resolve({ code: 200 })
140 | })
141 | .catch(err => {
142 | reject(err.message)
143 | })
144 | })
145 | }
146 |
147 | module.exports = productService
148 |
--------------------------------------------------------------------------------
/server/services/shopify.js:
--------------------------------------------------------------------------------
1 | var Shopify = require("shopify-node-api")
2 |
3 | var shopName = process.env.SHOPIFY_SHOP_NAME
4 | var apiKey = process.env.SHOPIFY_API_KEY
5 | var password = process.env.SHOPIFY_PASSWORD
6 |
7 | var shopify = new Shopify({
8 | shop: shopName, // MYSHOP.myshopify.com
9 | shopify_api_key: apiKey, // Your API key
10 | access_token: password, // Your API password
11 | })
12 |
13 | module.exports = shopify
--------------------------------------------------------------------------------
/services/consignorService.js:
--------------------------------------------------------------------------------
1 | const consignorModel = require("../models/consignor-model")
2 |
3 | const consignorService = {
4 | getAllConsignors: getAllConsignors,
5 | addConsignor: addConsignor,
6 | updateConsignor: updateConsignor,
7 | getConsignorById: getConsignorById,
8 | getConsignorByVendor: getConsignorByVendor,
9 | delConsignor: delConsignor,
10 | }
11 |
12 | function getAllConsignors() {
13 | return new Promise((resolve, reject) => {
14 | consignorModel
15 | .getAllConsignors()
16 | .then(data => {
17 | resolve({ code: 200, data })
18 | })
19 | .catch(err => {
20 | reject(err.message)
21 | })
22 | })
23 | }
24 |
25 | function addConsignor(consignor_data) {
26 | return new Promise((resolve, reject) => {
27 | consignorModel
28 | .addConsignor(consignor_data)
29 | .then(data => {
30 | resolve({ code: 200 })
31 | })
32 | .catch(err => {
33 | reject(err.message)
34 | })
35 | })
36 | }
37 |
38 | function updateConsignor(consignor_data) {
39 | return new Promise((resolve, reject) => {
40 | consignorModel
41 | .updateConsignor(consignor_data)
42 | .then(data => {
43 | resolve({ code: 200 })
44 | })
45 | .catch(err => {
46 | reject(err.message)
47 | })
48 | })
49 | }
50 |
51 | function getConsignorById(id) {
52 | return new Promise((resolve, reject) => {
53 | consignorModel
54 | .getConsignorById(id)
55 | .then(data => {
56 | resolve({ code: 200, data })
57 | })
58 | .catch(err => {
59 | reject(err.message)
60 | })
61 | })
62 | }
63 |
64 | function getConsignorByVendor(vendor) {
65 | return new Promise((resolve, reject) => {
66 | consignorModel
67 | .getConsignorByVendor(vendor)
68 | .then(data => {
69 | resolve({ code: 200, data })
70 | })
71 | .catch(err => {
72 | reject(err.message)
73 | })
74 | })
75 | }
76 |
77 | function delConsignor(id) {
78 | return new Promise((resolve, reject) => {
79 | consignorModel
80 | .delConsignor(id)
81 | .then(data => {
82 | resolve({ code: 200, data })
83 | })
84 | .catch(err => {
85 | reject(err.message)
86 | })
87 | })
88 | }
89 |
90 | module.exports = consignorService
91 |
--------------------------------------------------------------------------------
/services/orderService.js:
--------------------------------------------------------------------------------
1 | const orderModel = require("../models/order-model")
2 | const shopify = require("./shopify")
3 |
4 | const orderService = {
5 | createOrders: createOrders,
6 | }
7 |
8 | function createOrders(req) {
9 | return new Promise((resolve, reject) => {
10 | var order_id = req.body.name
11 | var created_at = req.body.created_at
12 | var qty = 0
13 | var name = ""
14 | var price = 0
15 | var compare_at_price = ""
16 | var sku = ""
17 | var shipping = ""
18 | var taxable = ""
19 | var fulfillment_status = ""
20 | var vendor = ""
21 | var discount_amount = 0
22 | var last_updated = req.body.updated_at
23 | orderModel
24 | .createOrders(req)
25 | .then(data => {
26 | for (let i = 0; i < req.body.line_items.length; i++) {
27 | qty = req.body.line_items[i].quantity
28 | name = req.body.line_items[i].name
29 | price = req.body.line_items[i].price
30 | compare_at_price = 0
31 | sku = req.body.line_items[i].sku
32 | shipping = req.body.line_items[i].requires_shipping
33 | taxable = req.body.line_items[i].taxable
34 | fulfillment_status = req.body.line_items[i].fulfillment_status
35 | vendor = req.body.line_items[i].vendor
36 | orderModel
37 | .createOrderItem(
38 | order_id,
39 | created_at,
40 | qty,
41 | name,
42 | price,
43 | compare_at_price,
44 | sku,
45 | shipping,
46 | taxable,
47 | fulfillment_status,
48 | vendor,
49 | discount_amount,
50 | last_updated
51 | )
52 | .then(data => {
53 | console.log(data)
54 | })
55 | .catch(err => {
56 | reject(err.message)
57 | console.log(err)
58 | })
59 | }
60 | console.log(data)
61 | })
62 | .catch(err => {
63 | reject(err.message)
64 | console.log(err)
65 | })
66 |
67 | resolve({ code: 200 })
68 | })
69 | }
70 |
71 | module.exports = orderService
72 |
--------------------------------------------------------------------------------
/services/payoutService.js:
--------------------------------------------------------------------------------
1 | const payoutModel = require("../models/payout-model")
2 |
3 | const payoutService = {
4 | getPayouts: getPayouts,
5 | getPayoutDetailsByVendor: getPayoutDetailsByVendor,
6 | getPayoutByVendor: getPayoutByVendor,
7 | }
8 |
9 | function getPayouts(flag) {
10 | return new Promise((resolve, reject) => {
11 | payoutModel
12 | .getPayouts(flag)
13 | .then(data => {
14 | resolve({ code: 200, data })
15 | })
16 | .catch(err => {
17 | reject(err.message)
18 | console.log(err)
19 | })
20 | })
21 | }
22 |
23 | function getPayoutDetailsByVendor(vendor) {
24 | return new Promise((resolve, reject) => {
25 | payoutModel
26 | .getPayoutDetailsByVendor(vendor)
27 | .then(data => {
28 | resolve({ code: 200, data })
29 | })
30 | .catch(err => {
31 | reject(err.message)
32 | console.log(err)
33 | })
34 | })
35 | }
36 |
37 | function getPayoutByVendor(vendor) {
38 | return new Promise((resolve, reject) => {
39 | payoutModel
40 | .getPayoutByVendor(vendor)
41 | .then(data => {
42 | resolve({ code: 200, data })
43 | })
44 | .catch(err => {
45 | reject(err.message)
46 | console.log(err)
47 | })
48 | })
49 | }
50 |
51 | module.exports = payoutService
52 |
--------------------------------------------------------------------------------
/services/productService.js:
--------------------------------------------------------------------------------
1 | const productModel = require("../models/product-model")
2 | const shopify = require("./shopify")
3 |
4 | const productService = {
5 | getAllProducts: getAllProducts,
6 | getProductById: getProductById,
7 | getProductsByVendor: getProductsByVendor,
8 | setProducts: setProducts,
9 | updateProducts: updateProducts,
10 | deleteProduct: deleteProduct,
11 | }
12 |
13 | function getAllProducts() {
14 | return new Promise((resolve, reject) => {
15 | shopify.get(
16 | "/admin/products.json",
17 | function (error, shopify_data, headers) {
18 | var products = shopify_data.products
19 | productModel
20 | .getAllProducts()
21 | .then(data => {
22 | resolve({ code: 200, data: data, shopifyData: products })
23 | })
24 | .catch(err => {
25 | reject(err.message)
26 | })
27 | }
28 | )
29 | })
30 | }
31 |
32 | function getProductById(id) {
33 | const product_id = id
34 | return new Promise((resolve, reject) => {
35 | productModel
36 | .getProductById(product_id)
37 | .then(data => {
38 | resolve({ code: 200, data: data.data, shopifyData: data.shopifyData })
39 | })
40 | .catch(err => {
41 | reject(err.message)
42 | })
43 | })
44 | }
45 |
46 | function getProductsByVendor(vendor) {
47 | return new Promise((resolve, reject) => {
48 | productModel
49 | .getProductsByVendor(vendor)
50 | .then(data => {
51 | resolve({ code: 200, data: data.data, shopifyData: data.shopifyData })
52 | })
53 | .catch(err => {
54 | reject(err.message)
55 | })
56 | })
57 | }
58 |
59 | function setProducts(req) {
60 | const title = req.body.title
61 | const description = req.body.description
62 | const product_type = req.body.product_type
63 | const size = req.body.size
64 | const color = req.body.color
65 | const price = req.body.price
66 | const published_at = req.body.published_at
67 | const shopify_published_at = new Date(published_at)
68 |
69 | //declare post_data for adding product to shopify
70 | var post_data = {
71 | product: {
72 | title: title,
73 | body_html: description,
74 | vendor: "Tacoma Consignment",
75 | product_type: product_type,
76 | published_at: shopify_published_at,
77 | variants: [
78 | {
79 | Color: color,
80 | Size: size,
81 | price: price,
82 | },
83 | ],
84 | images: [],
85 | },
86 | }
87 |
88 | for (var i = 0; i < req.files.length; i++) {
89 | var tempImage = {
90 | position: i + 1,
91 | attachment: req.files[i].buffer.toString("base64"),
92 | width: 640,
93 | height: 480,
94 | filename: req.files[i].originalname,
95 | }
96 | post_data.product.images.push(tempImage)
97 | }
98 |
99 | return new Promise((resolve, reject) => {
100 | //adding products to shopify
101 | shopify.post(
102 | "/admin/products.json",
103 | post_data,
104 | function (error, shopify_data, headers) {
105 | var shopify_id = shopify_data.product.id
106 | productModel
107 | .setProducts(req, shopify_id)
108 | .then(data => {
109 | resolve({ code: 200, data: shopify_data })
110 | })
111 | .catch(err => {
112 | reject(err.message)
113 | })
114 | }
115 | )
116 | })
117 | }
118 |
119 | function updateProducts(req) {
120 | return new Promise((resolve, reject) => {
121 | //updating products to shopify and mssql
122 | productModel
123 | .updateProducts(req)
124 | .then(data => {
125 | resolve({ code: 200 })
126 | })
127 | .catch(err => {
128 | reject(err.message)
129 | })
130 | })
131 | }
132 |
133 | function deleteProduct(req) {
134 | return new Promise((resolve, reject) => {
135 | //delete product from shopify and mssql
136 | productModel
137 | .deleteProduct(req)
138 | .then(data => {
139 | resolve({ code: 200 })
140 | })
141 | .catch(err => {
142 | reject(err.message)
143 | })
144 | })
145 | }
146 |
147 | module.exports = productService
148 |
--------------------------------------------------------------------------------
/services/shopify.js:
--------------------------------------------------------------------------------
1 | var Shopify = require("shopify-node-api")
2 |
3 | var shopName = process.env.SHOPIFY_SHOP_NAME
4 | var apiKey = process.env.SHOPIFY_API_KEY
5 | var password = process.env.SHOPIFY_PASSWORD
6 |
7 | var shopify = new Shopify({
8 | shop: shopName, // MYSHOP.myshopify.com
9 | shopify_api_key: apiKey, // Your API key
10 | access_token: password, // Your API password
11 | })
12 |
13 | module.exports = shopify
--------------------------------------------------------------------------------
/theme_source/figma-ui-kit-main.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elitedev201/Vue-shopify-api-integration/18111e9aa61c28c0034c4cae1f190d6972d3af84/theme_source/figma-ui-kit-main.zip
--------------------------------------------------------------------------------
/theme_source/materio-v1.0.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elitedev201/Vue-shopify-api-integration/18111e9aa61c28c0034c4cae1f190d6972d3af84/theme_source/materio-v1.0.zip
--------------------------------------------------------------------------------