change readme.md. clean up console.logs. add check for exsisting invoices

This commit is contained in:
Dzmitry_Tamashevich@epam.com
2020-11-25 19:16:22 +03:00
committed by Daniel Hutzel
parent fe0562f38b
commit f439119e73
12 changed files with 60 additions and 86 deletions

View File

@@ -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

View File

@@ -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();

View File

@@ -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 };

View File

@@ -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);
}; };

View File

@@ -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",
}); });
} }

View File

@@ -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) => {

View File

@@ -178,7 +178,6 @@ const MyInvoicesPage = () => {
{invoiceElements && ( {invoiceElements && (
<Collapse expandIconPosition="left">{invoiceElements}</Collapse> <Collapse expandIconPosition="left">{invoiceElements}</Collapse>
)} )}
{"Pagination steel needed"}
</div> </div>
); );
}; };

View File

@@ -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 !== "" && (

View File

@@ -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(
([ ([

View File

@@ -49,7 +49,6 @@ const EditAction = ({
}; };
const handleCancel = () => { const handleCancel = () => {
console.log("Clicked cancel button");
setVisible(false); setVisible(false);
}; };

View File

@@ -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" })

View File

@@ -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) =>