Skip to content
This repository has been archived by the owner on May 6, 2022. It is now read-only.

0.5 #43

Merged
merged 6 commits into from
Dec 7, 2021
Merged

0.5 #43

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Secret JWT token for authentication, don't share this with anyone.
JWT_ACCESS_TOKEN=

# If in debug mode or note
# (optional)
DEBUG=

# The mongo database uri to use, if not set it will use the default: mongodb://localhost/cpg
MONGO_URI=

# The domain to use for the api, if not set it will use the default: localhost
# Needs to look like: https://domain.com
# (optional)
DOMAIN=

# http or https, default: http
# (optional)
HTTP_SCHEMA=

# Session secret key for cookies
SESSION_SECRET=

# Which port to run on, default 8080
# (optional)
PORT=

# If you use OsTicket you can configure it here
# (optional)
OSTICKET_URL=
OSTICKET_API_KEY=

# If you have "swish" (Swedish company), you can use your number here for CPG
# (optional)
SWISH_PAYEE_NUMBER=

# Paypal credentials
# (optional)
PAYPAL_CLIENT_ID=
PAYPAL_CLIENT_SECRET=

# Stripe credentials
# (optional)
STRIPE_SK_LIVE=
STRIPE_SK_PUBLIC=
STRIPE_WEBHOOK_SECRET=

# This is a solution that will be probably removed in the near future
# but for the invoices adding these would be recommended.
COMPANY_NAME=
COMPANY_ADDRESS=
COMPANY_ZIP=
COMPANY_CITY=
COMPANY_COUNTRY=
COMPANY_PHONE=
COMPANY_EMAIL=
COMPANY_VAT=
COMPANY_CURRENCY=
COMPANY_LOGO_URL=
COMPANY_TAX_REGISTERED=
COMPANY_WEBSITE=

# For invoice you can add a template
# (optional)
PDF_TEMPLATE_URL=

# Plugins for CPG
# NOTE: Plugins can require different env variables to be set.
# (optional)
PLUGINS="[]"

# For the webhook, you add a secret to know the webhook is from CPG
# (optional)
WEBHOOK_SECRET=
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,41 @@
# ⭐ | CPG-API
CPG-API is being used to create products, invoices, orders, transactions and payments for customers, to grow your business.

# 🧰 | Setup
Setting up `CPG` can be done in various of ways, but by the far easiet is by using `Docker`.
You can pull the latest `docker` image from `tolfixorg/cpg:latest` from `DockerHub`.

`CPG` also needs `env` vars added, which you can find some documents from [`.env.example`](), those added with `(optional)` can be ignored if you don't feel the need of them, but the others are required to make `CPG` functional.

## Installing
`CPG` requires the following
* Node.js
* Typescript - 4.3.5
* MongoDB
* Git

1. Clone repository
```txt
git clone https://github.com/Tolfix/CPG-API
```
2. Install dependencies
```txt
npm install
```
3. Install `TypeScript`
```txt
npm install -g typescript@4.3.5
```
## Building
`CPG` is built from `TypeScript`, thus simple run it by using the compiler.
```txt
tsc -b
npm run build
```

## Running
You can run `CPG` by using `npm run start` or `node ./build/Main.js`.
Would recommend to use `pm2`.
# 🎨 | Plugins
Plugins allows you to install others features to CPG. Be aware it can be `dangerous` due to plugins get accessed to alot, you can trust `Tolfix` owns plugins, or plugins you created yourself, otherwise there is no guarantee.

Expand Down
50 changes: 49 additions & 1 deletion src/Routes/v2/Customers/Customers.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Application, Router } from "express";
import EnsureAdmin from "../../../Middlewares/EnsureAdmin";
import CustomerController from "./Customers.controller";
import { Full_Domain, JWT_Access_Token } from "../../../Config";
import { Full_Domain, GetSMTPEmails, JWT_Access_Token } from "../../../Config";
import jwt from "jsonwebtoken";
import bcrypt from "bcryptjs";
import { APIError, APISuccess } from "../../../Lib/Response";
Expand Down Expand Up @@ -138,6 +138,54 @@ export default class CustomerRouter
return APISuccess(order)(res);
});

this.router.get("/my/orders/:id/cancel", EnsureAuth(), async (req, res) => {
const orderId = req.params.id;

if(!orderId)
return APIError(`Invalid invoice id`)(res);

const customer = await CustomerModel.findOne({
// @ts-ignore
id: req.customer.id
});

if(!customer)
return APIError(`Unable to find customer`)(res);

const order = await OrderModel.findOne({
$or: [
{
customer_uid: customer.uid,
},
{
customer_uid: customer.id,
},
],
id: orderId,
});

if(!order)
return APIError(`Unable to find order`)(res);

order.order_status = "cancelled";
await order.save();

GetSMTPEmails().then(emails => {
for(const email of emails)
{
SendEmail(email, `Order Cancelled #${order.id}`, {
isHTML: true,
body: `
<h1>Order Cancelled</h1>
<p>Order #${order.id} has been cancelled</p>
`,
});
}
});

return APISuccess("Order cancelled.")(res);
});

this.router.post("/my/reset-password", async (req, res) => {
const email = req.body.email;
const customer = await CustomerModel.findOne({ "personal.email": email });
Expand Down
6 changes: 5 additions & 1 deletion src/Routes/v2/Orders/Orders.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import dateFormat from "date-and-time";
import nextRecycleDate from "../../../Lib/Dates/DateCycle";
import { createInvoiceFromOrder } from "../../../Lib/Orders/newInvoice";
import { idOrder } from "../../../Lib/Generator";
import { Company_Name, Full_Domain } from "../../../Config";
import { Company_Name, Full_Domain, Swish_Payee_Number } from "../../../Config";
import { sendInvoiceEmail } from "../../../Lib/Invoices/SendEmail";
import EnsureAuth from "../../../Middlewares/EnsureAuth";
import { IOrder } from "../../../Interfaces/Orders";
Expand All @@ -20,6 +20,7 @@ import { SendEmail } from "../../../Email/Send";
import NewOrderCreated from "../../../Email/Templates/Orders/NewOrderCreated";
import { IConfigurableOptions } from "../../../Interfaces/ConfigurableOptions";
import { CreatePaymentIntent } from "../../../Payments/Stripe";
import { createSwishQRCode } from "../../../Payments/Swish";

async function createOrder(customer: ICustomer, products: Array<{
product_id: IProduct["id"],
Expand Down Expand Up @@ -266,6 +267,9 @@ export default class OrderRoute
if(payment_method === "credit_card")
return APISuccess(`${Full_Domain}/v2/stripe/pay/${invoice.uid}`)(res);

if(payment_method === "swish" && Swish_Payee_Number)
return APISuccess(`data:image/png;base64,${await createSwishQRCode(Swish_Payee_Number, (invoice.amount)+(invoice.amount)*(invoice.tax_rate/100), `Invoice ${invoice.id}`)}`)(res);

return APISuccess(`Invoice sent.`)(res);
});

Expand Down