change readme.md. clean up console.logs. add check for exsisting invoices
This commit is contained in:
committed by
Daniel Hutzel
parent
fe0562f38b
commit
f439119e73
@@ -4,22 +4,33 @@ Welcome to your new project.
|
|||||||
|
|
||||||
It contains these folders and files, following our recommended project layout:
|
It contains these folders and files, following our recommended project layout:
|
||||||
|
|
||||||
File or Folder | Purpose
|
| File or Folder | Purpose |
|
||||||
---------|----------
|
| -------------- | ------------------------------------ |
|
||||||
`app/` | Contains already bundled js code from [this repository](https://github.com/Dmitriynj/media-store-front)
|
| `app/` | Contains frontend app on react |
|
||||||
`db/` | your domain models and data go here
|
| `db/` | your domain models and data go here |
|
||||||
`srv/` | your service models and code go here
|
| `srv/` | your service models and code go here |
|
||||||
`package.json` | project metadata and configuration
|
| `package.json` | project metadata and configuration |
|
||||||
`readme.md` | this getting started guide
|
| `readme.md` | this getting started guide |
|
||||||
|
|
||||||
|
## Start development steps
|
||||||
|
|
||||||
## Next Steps
|
- At first open a new terminal and run `npm run deploy`. It should create new sqlite source and fill initial data from `db/data`. You can browse database in any sqlite client
|
||||||
|
- Run `cds watch`. This will start cds service on 4004 port in watch mode
|
||||||
|
- Open `app` folder and run `npm run start`. This will start frontend dev server on 3000 port. It supports debug in chrome and hot reloading out of the box by create-react-app
|
||||||
|
- Now all things are done for development
|
||||||
|
|
||||||
- Open a new terminal and run `cds watch`
|
## Deployment steps
|
||||||
- (in VS Code simply choose _**Terminal** > Run Task > cds watch_)
|
|
||||||
- Start adding content, for example, a [db/schema.cds](db/schema.cds).
|
|
||||||
- To adjust UI simply clone [this](https://github.com/Dmitriynj/media-store-front) repo. Run `yarn start` for development. When you are done, run `yarn build` and copy all files from '/build' to the '/app' folder of the current repo.
|
|
||||||
|
|
||||||
|
- Make sure you already have hanatrial instance in your cockpit dashboard (SAP Cloud Platform).
|
||||||
|
Or if you are using hana instance - change it in mta.yaml config file from hanatrial to hana
|
||||||
|
- Replace `"kind": "sql"` with `"kind": "hana"` in package.json require section
|
||||||
|
- Make sure that current folder does not contain any previous `*.mtar` build file and `gen` folder
|
||||||
|
If exists - remove it
|
||||||
|
- Run `cf login` for Cloud Foundry authentication
|
||||||
|
- Open `app` folder and run `npm run build`. This will start create new production frontend bundles
|
||||||
|
- Run `mbt build -t ./`. This will create new build in `*.mtar` file
|
||||||
|
- Run `cf deploy <.mtar file>` # for example, media-store_1.0.0.mtar
|
||||||
|
- Now your services should be deployed with hanatrial instance and filled with initial data
|
||||||
|
|
||||||
## Learn More
|
## Learn More
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { responseErrorInterceptor } from "./responseErrorInterceptor";
|
|||||||
|
|
||||||
const axiosInstance = axios.create({
|
const axiosInstance = axios.create({
|
||||||
baseURL: API,
|
baseURL: API,
|
||||||
timeout: 1000,
|
timeout: 2000,
|
||||||
});
|
});
|
||||||
const user = getUserFromLS();
|
const user = getUserFromLS();
|
||||||
const locale = getLocaleFromLS();
|
const locale = getLocaleFromLS();
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
import React, { useEffect, useRef } from "react";
|
|
||||||
|
|
||||||
const Editable = ({ value, onChange, type }) => {
|
|
||||||
const inputRef = useRef();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const { current } = inputRef;
|
|
||||||
|
|
||||||
current.value = value;
|
|
||||||
|
|
||||||
const handleFocus = () => {
|
|
||||||
console.log("input is focussed");
|
|
||||||
// current.disabled = false;
|
|
||||||
current.style.backgroundColor = "#f0f2f5";
|
|
||||||
};
|
|
||||||
const handleBlur = () => {
|
|
||||||
console.log("input is blurred");
|
|
||||||
// current.disabled = true;
|
|
||||||
current.style.backgroundColor = "white";
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleInput = (e) => onChange(e.target.value);
|
|
||||||
|
|
||||||
current.addEventListener("focus", handleFocus);
|
|
||||||
current.addEventListener("blur", handleBlur);
|
|
||||||
current.addEventListener("input", handleInput);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
current.removeEventListener("focus", handleFocus);
|
|
||||||
current.removeEventListener("blur", handleBlur);
|
|
||||||
current.removeEventListener("input", handleInput);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<input
|
|
||||||
ref={inputRef}
|
|
||||||
style={{
|
|
||||||
fontWeight: 600,
|
|
||||||
outline: "none",
|
|
||||||
border: "none",
|
|
||||||
backgroundColor: "white",
|
|
||||||
padding: "0 2px",
|
|
||||||
}}
|
|
||||||
type={type}
|
|
||||||
name="task"
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export { Editable };
|
|
||||||
@@ -40,7 +40,6 @@ const AppStateContextProvider = ({ children }) => {
|
|||||||
setUser(newUser);
|
setUser(newUser);
|
||||||
};
|
};
|
||||||
emitter.on("UPDATE_USER", updateUser);
|
emitter.on("UPDATE_USER", updateUser);
|
||||||
console.log("listener was registered");
|
|
||||||
return () => {
|
return () => {
|
||||||
emitter.removeListener("UPDATE_USER", updateUser);
|
emitter.removeListener("UPDATE_USER", updateUser);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const useErrors = () => {
|
|||||||
setError({
|
setError({
|
||||||
status: "",
|
status: "",
|
||||||
statusText: "Error",
|
statusText: "Error",
|
||||||
message: "Something went wrong",
|
message: "Something went wrong. Seems like request is too long",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,14 +25,17 @@ const tailLayout = {
|
|||||||
const Login = () => {
|
const Login = () => {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const { setLoading } = useAppState();
|
const { setLoading, setInvoicedItems } = useAppState();
|
||||||
const { handleError } = useErrors();
|
const { handleError } = useErrors();
|
||||||
|
|
||||||
const onFinish = (values) => {
|
const onFinish = (values) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
login({ email: values.email, password: values.password })
|
login({ email: values.email, password: values.password })
|
||||||
.then((response) => {
|
.then(({ data: user }) => {
|
||||||
emitter.emit("UPDATE_USER", response.data);
|
emitter.emit("UPDATE_USER", user);
|
||||||
|
if (user.roles.includes("employee")) {
|
||||||
|
setInvoicedItems([]);
|
||||||
|
}
|
||||||
history.push("/");
|
history.push("/");
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
|
|||||||
@@ -178,7 +178,6 @@ const MyInvoicesPage = () => {
|
|||||||
{invoiceElements && (
|
{invoiceElements && (
|
||||||
<Collapse expandIconPosition="left">{invoiceElements}</Collapse>
|
<Collapse expandIconPosition="left">{invoiceElements}</Collapse>
|
||||||
)}
|
)}
|
||||||
{"Pagination steel needed"}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -64,17 +64,13 @@ const PersonPage = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const personProperties = map(Object.keys(person), (currentKey) => (
|
const personProperties = map(Object.keys(person), (currentKey) => (
|
||||||
<Form.Item
|
<div key={currentKey}>
|
||||||
key={currentKey}
|
<Form.Item label={PERSON_PROP[currentKey]} name={currentKey}>
|
||||||
label={PERSON_PROP[currentKey]}
|
<Input />
|
||||||
name={currentKey}
|
</Form.Item>
|
||||||
>
|
</div>
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
));
|
));
|
||||||
|
|
||||||
console.log(person, "person");
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{person.lastName !== "" && (
|
{person.lastName !== "" && (
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ import { useAbortableEffect } from "../hooks/useAbortableEffect";
|
|||||||
import { requireEmployee } from "../util/constants";
|
import { requireEmployee } from "../util/constants";
|
||||||
import "./TracksPage.css";
|
import "./TracksPage.css";
|
||||||
|
|
||||||
let counter = 0;
|
|
||||||
|
|
||||||
const { Search } = Input;
|
const { Search } = Input;
|
||||||
const { Option } = Select;
|
const { Option } = Select;
|
||||||
|
|
||||||
@@ -52,7 +50,6 @@ const TracksContainer = () => {
|
|||||||
const getTracksRequest = fetchTacks();
|
const getTracksRequest = fetchTacks();
|
||||||
const getGenresReq = fetchGenres();
|
const getGenresReq = fetchGenres();
|
||||||
|
|
||||||
console.log("calling requests", counter++);
|
|
||||||
Promise.all([countTracksReq, getTracksRequest, getGenresReq])
|
Promise.all([countTracksReq, getTracksRequest, getGenresReq])
|
||||||
.then(
|
.then(
|
||||||
([
|
([
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ const EditAction = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
console.log("Clicked cancel button");
|
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ module.exports = async function () {
|
|||||||
|
|
||||||
this.on("invoice", async (req) => {
|
this.on("invoice", async (req) => {
|
||||||
const { tracks } = req.data;
|
const { tracks } = req.data;
|
||||||
const trackIds = tracks.map(({ ID }) => ID);
|
const newInvoicedTracks = tracks.map(({ ID }) => ID);
|
||||||
const customerId = req.user.attr.ID;
|
const customerId = req.user.attr.ID;
|
||||||
const total = tracks.reduce(
|
const total = tracks.reduce(
|
||||||
(acc, { unitPrice }) => acc + Number(unitPrice),
|
(acc, { unitPrice }) => acc + Number(unitPrice),
|
||||||
@@ -33,6 +33,27 @@ module.exports = async function () {
|
|||||||
|
|
||||||
const transaction = await db.tx(req);
|
const transaction = await db.tx(req);
|
||||||
|
|
||||||
|
// check if already exists
|
||||||
|
const invoicedTracks = await transaction.run(
|
||||||
|
SELECT.from(InvoiceItems)
|
||||||
|
.columns("track_ID")
|
||||||
|
.where(
|
||||||
|
"invoice_ID in",
|
||||||
|
SELECT("ID").from(Invoices).where({
|
||||||
|
customer_ID: req.user.attr.ID,
|
||||||
|
status: 1,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const isNewInvoiceHasInvoicedTracks = invoicedTracks.some(
|
||||||
|
({ track_ID: curID }) => newInvoicedTracks.includes(curID)
|
||||||
|
);
|
||||||
|
if (isNewInvoiceHasInvoicedTracks) {
|
||||||
|
await transaction.rollback();
|
||||||
|
req.reject(400, "Invoice contains already owned values");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// getting last ids for new records
|
// getting last ids for new records
|
||||||
let { ID: lastInvoiceId } = await transaction.run(
|
let { ID: lastInvoiceId } = await transaction.run(
|
||||||
SELECT.one(Invoices).columns("ID").orderBy({ ID: "desc" })
|
SELECT.one(Invoices).columns("ID").orderBy({ ID: "desc" })
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ const jwt = require("jsonwebtoken");
|
|||||||
const bcrypt = require("bcryptjs");
|
const bcrypt = require("bcryptjs");
|
||||||
|
|
||||||
const { ACCESS_TOKEN_SECRET, REFRESH_TOKEN_SECRET } = cds.env;
|
const { ACCESS_TOKEN_SECRET, REFRESH_TOKEN_SECRET } = cds.env;
|
||||||
const ACCESS_TOKEN_EXP_IN = "10s";
|
const ACCESS_TOKEN_EXP_IN = "10m";
|
||||||
const REFRESH_TOKEN_EXPIRES_IN = "30s";
|
const REFRESH_TOKEN_EXPIRES_IN = "20m";
|
||||||
|
|
||||||
const comparePasswords = async (password, hashedPassword) => {
|
const comparePasswords = async (password, hashedPassword) => {
|
||||||
return new Promise((resolve, reject) =>
|
return new Promise((resolve, reject) =>
|
||||||
|
|||||||
Reference in New Issue
Block a user