Add inventory line view
This commit is contained in:
parent
f02c7462f3
commit
26b087c041
69
elm/Main.elm
69
elm/Main.elm
@ -86,6 +86,15 @@ disableItems ids = Http.post
|
|||||||
, expect = Http.expectWhatever (\_ -> RcvOther)
|
, expect = Http.expectWhatever (\_ -> RcvOther)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deleteSnack : Int -> Cmd Msg
|
||||||
|
deleteSnack snack = Http.post
|
||||||
|
{ url = "/rpc/deleteSnack"
|
||||||
|
, body = Http.jsonBody (Enc.object
|
||||||
|
[ ("snack", Enc.int snack)
|
||||||
|
])
|
||||||
|
, expect = Http.expectWhatever (\_ -> RcvOther)
|
||||||
|
}
|
||||||
|
|
||||||
decodeOI = Dec.succeed OverviewItem
|
decodeOI = Dec.succeed OverviewItem
|
||||||
|> requiredAt ["item", "id"] Dec.int
|
|> requiredAt ["item", "id"] Dec.int
|
||||||
|> requiredAt ["item", "barcode"] Dec.string
|
|> requiredAt ["item", "barcode"] Dec.string
|
||||||
@ -94,6 +103,8 @@ decodeOI = Dec.succeed OverviewItem
|
|||||||
|> requiredAt ["item", "unitPrice"] Dec.float
|
|> requiredAt ["item", "unitPrice"] Dec.float
|
||||||
|> requiredAt ["item", "bought"] Dec.string
|
|> requiredAt ["item", "bought"] Dec.string
|
||||||
|> requiredAt ["overview", "activeMappings"] Dec.int
|
|> requiredAt ["overview", "activeMappings"] Dec.int
|
||||||
|
|> requiredAt ["item", "group"] Dec.int
|
||||||
|
|> requiredAt ["overview", "groupName"] Dec.string
|
||||||
|
|
||||||
getSnacksByItem : OverviewItem -> Cmd Msg
|
getSnacksByItem : OverviewItem -> Cmd Msg
|
||||||
getSnacksByItem item = rpc
|
getSnacksByItem item = rpc
|
||||||
@ -129,6 +140,8 @@ type alias OverviewItem =
|
|||||||
, price : Float
|
, price : Float
|
||||||
, bought : String
|
, bought : String
|
||||||
, activeMappings : Int
|
, activeMappings : Int
|
||||||
|
, groupId : Int
|
||||||
|
, groupName : String
|
||||||
}
|
}
|
||||||
|
|
||||||
type alias Location =
|
type alias Location =
|
||||||
@ -147,7 +160,7 @@ type State
|
|||||||
, desiredInventory : Dict Int Int
|
, desiredInventory : Dict Int Int
|
||||||
, overviewItems : List OverviewItem
|
, overviewItems : List OverviewItem
|
||||||
}
|
}
|
||||||
| SnacksEditor
|
| ViewingItem
|
||||||
{ item : OverviewItem
|
{ item : OverviewItem
|
||||||
, snacks : List Snack
|
, snacks : List Snack
|
||||||
}
|
}
|
||||||
@ -163,6 +176,7 @@ type Msg
|
|||||||
| CallDisableItems (List Int)
|
| CallDisableItems (List Int)
|
||||||
| CallAdjustInventory Int Int String
|
| CallAdjustInventory Int Int String
|
||||||
| CallGetSnacksById OverviewItem
|
| CallGetSnacksById OverviewItem
|
||||||
|
| CallDeleteSnack Int
|
||||||
-- Responses
|
-- Responses
|
||||||
| RcvLocations (Result Http.Error (List Location))
|
| RcvLocations (Result Http.Error (List Location))
|
||||||
| RcvOverview (Result Http.Error (List OverviewItem))
|
| RcvOverview (Result Http.Error (List OverviewItem))
|
||||||
@ -175,6 +189,7 @@ update msg outerState = case msg of
|
|||||||
CallAdjustInventory item amount desc -> (outerState, adjustInventory item amount desc)
|
CallAdjustInventory item amount desc -> (outerState, adjustInventory item amount desc)
|
||||||
CallDisableItems items -> (outerState, disableItems items)
|
CallDisableItems items -> (outerState, disableItems items)
|
||||||
CallGetSnacksById item -> (outerState, getSnacksByItem item)
|
CallGetSnacksById item -> (outerState, getSnacksByItem item)
|
||||||
|
CallDeleteSnack snack -> (outerState, deleteSnack snack)
|
||||||
_ -> case outerState of
|
_ -> case outerState of
|
||||||
LoadingLocations -> case msg of
|
LoadingLocations -> case msg of
|
||||||
RcvLocations (Ok locations) ->
|
RcvLocations (Ok locations) ->
|
||||||
@ -212,7 +227,7 @@ stateMachine msg global state = case state of
|
|||||||
, Cmd.none
|
, Cmd.none
|
||||||
)
|
)
|
||||||
RcvSnacks item (Ok snacks) ->
|
RcvSnacks item (Ok snacks) ->
|
||||||
(SnacksEditor { item = item, snacks = snacks }, Cmd.none)
|
(ViewingItem { item = item, snacks = snacks }, Cmd.none)
|
||||||
RcvOther ->
|
RcvOther ->
|
||||||
(state, getOverviewItems global.location.id)
|
(state, getOverviewItems global.location.id)
|
||||||
SelectItem itemId selected ->
|
SelectItem itemId selected ->
|
||||||
@ -234,9 +249,13 @@ stateMachine msg global state = case state of
|
|||||||
(state, transferInventory transfers)
|
(state, transferInventory transfers)
|
||||||
_ ->
|
_ ->
|
||||||
(state, Cmd.none)
|
(state, Cmd.none)
|
||||||
SnacksEditor { snacks } -> case msg of
|
ViewingItem { item } -> case msg of
|
||||||
GoBack ->
|
GoBack ->
|
||||||
(Overview { selectedItems = Set.empty, desiredInventory = Dict.empty, overviewItems = [] }, getOverviewItems global.location.id)
|
(Overview { selectedItems = Set.empty, desiredInventory = Dict.empty, overviewItems = [] }, getOverviewItems global.location.id)
|
||||||
|
RcvSnacks item_ (Ok snacks) ->
|
||||||
|
(ViewingItem { item = item_, snacks = snacks }, Cmd.none)
|
||||||
|
RcvOther ->
|
||||||
|
(state, getSnacksByItem item)
|
||||||
_ ->
|
_ ->
|
||||||
(state, Cmd.none)
|
(state, Cmd.none)
|
||||||
|
|
||||||
@ -263,7 +282,7 @@ view outerState = case outerState of
|
|||||||
viewState global state = case state of
|
viewState global state = case state of
|
||||||
Overview { selectedItems, desiredInventory, overviewItems } ->
|
Overview { selectedItems, desiredInventory, overviewItems } ->
|
||||||
let
|
let
|
||||||
header = tableCells th <| List.map text [ "", "ID", "Artikel", "Barcode", "Preis", "Kaufdatum", "Snackeinträge", "Inventar", "Aktionen" ]
|
header = tableCells th <| List.map text [ "", "ID", "Artikel", "EAN", "Preis", "Kaufdatum", "Snackeinträge", "Inventar", "Aktionen" ]
|
||||||
viewOverviewItem oi =
|
viewOverviewItem oi =
|
||||||
let
|
let
|
||||||
adjustedInventory = Maybe.withDefault oi.unitsLeft <| Dict.get oi.id desiredInventory
|
adjustedInventory = Maybe.withDefault oi.unitsLeft <| Dict.get oi.id desiredInventory
|
||||||
@ -309,7 +328,7 @@ viewState global state = case state of
|
|||||||
else [ onClick <| mkAdjustInventoryMsg oi.id <| adjustedInventory - oi.unitsLeft ])
|
else [ onClick <| mkAdjustInventoryMsg oi.id <| adjustedInventory - oi.unitsLeft ])
|
||||||
[ text <| "Inventar korrigieren" ++ viewAdjustedInventory (adjustedInventory - oi.unitsLeft) ]
|
[ text <| "Inventar korrigieren" ++ viewAdjustedInventory (adjustedInventory - oi.unitsLeft) ]
|
||||||
, button
|
, button
|
||||||
(if oi.activeMappings /= 0 || oi.unitsLeft /= 0
|
(if oi.unitsLeft /= 0
|
||||||
then [ disabled True ]
|
then [ disabled True ]
|
||||||
else [ onClick <| CallDisableItems [oi.id] ])
|
else [ onClick <| CallDisableItems [oi.id] ])
|
||||||
[ text "Eintrag deaktivieren" ]
|
[ text "Eintrag deaktivieren" ]
|
||||||
@ -318,26 +337,47 @@ viewState global state = case state of
|
|||||||
then [ disabled True ]
|
then [ disabled True ]
|
||||||
else [ onClick <| TransferInventory oi.id ])
|
else [ onClick <| TransferInventory oi.id ])
|
||||||
[ text <| String.fromInt sumSelected ++ " Einheiten umbuchen" ]
|
[ text <| String.fromInt sumSelected ++ " Einheiten umbuchen" ]
|
||||||
, button [ onClick <| CallGetSnacksById oi ] [ text "Snackeinträge bearbeiten" ]
|
, button [ onClick <| CallGetSnacksById oi ] [ text "Anzeigen" ]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
in
|
in
|
||||||
div []
|
div []
|
||||||
[ table [] <| [header] ++ List.map viewOverviewItem overviewItems
|
[ table [] <| [header] ++ List.map viewOverviewItem overviewItems
|
||||||
]
|
]
|
||||||
SnacksEditor { item, snacks } ->
|
ViewingItem { item, snacks } ->
|
||||||
let
|
let
|
||||||
header = tableCells th <| List.map text [ "ID", "Artikel", "Barcode", "Brutto" ]
|
header = tableCells th <| List.map text [ "ID", "Artikel", "B arcode", "Bruttoverkaufspreis", "Aktionen" ]
|
||||||
viewSnack snack = tableCells td
|
viewSnack snack = tableCells td
|
||||||
[ text <| String.fromInt snack.id
|
[ text <| String.fromInt snack.id
|
||||||
, text snack.name
|
, text snack.name
|
||||||
, text snack.barcode
|
, code [] [ text snack.barcode ]
|
||||||
, text <| showEuros snack.price
|
, text <| showEuros snack.price ++ " (+" ++ showEuros (roundTo 2 <| snack.price - item.price) ++ ")"
|
||||||
|
, div []
|
||||||
|
[ button [ onClick <| CallDeleteSnack snack.id ] [ text "Deaktivieren" ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
itemProp label value = tr []
|
||||||
|
[ th [ style "text-align" "left" ] [ text label ]
|
||||||
|
, td [] value
|
||||||
]
|
]
|
||||||
in
|
in
|
||||||
div []
|
div []
|
||||||
[ button [ onClick GoBack ] [ text "Zurück" ]
|
[ button [ onClick GoBack ] [ text "Zurück" ]
|
||||||
, p [] [ text <| "Snackeinträge für Inventareintrag " ++ String.fromInt item.id ++ " (" ++ showEuros item.price ++ " Netto)" ]
|
, fieldset []
|
||||||
|
[ legend [] [ text <| "Inventareintrag " ++ String.fromInt item.id ]
|
||||||
|
, table []
|
||||||
|
[ tbody []
|
||||||
|
[ itemProp "ID" [ text <| String.fromInt item.id ]
|
||||||
|
, itemProp "EAN" [ code [] [ text item.barcode ] ]
|
||||||
|
, itemProp "Artikel" [ text item.name ]
|
||||||
|
, itemProp "Gruppe" [ text <| item.groupName ++ " (" ++ String.fromInt item.groupId ++ ")" ]
|
||||||
|
, itemProp "Inventar" [ text <| String.fromInt item.unitsLeft ]
|
||||||
|
, itemProp "Kaufdatum" [ text <| Tuple.first <| splitAt 'T' item.bought ]
|
||||||
|
, itemProp "Nettoeinkaufspreis" [ text <| showEuros item.price ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
, h3 [] [ text "Snacks" ]
|
||||||
, table []
|
, table []
|
||||||
[ thead [] [ header ]
|
[ thead [] [ header ]
|
||||||
, tbody [] <| List.map viewSnack snacks
|
, tbody [] <| List.map viewSnack snacks
|
||||||
@ -376,3 +416,10 @@ showEuros x =
|
|||||||
(whole, fractional) = splitAt '.' (String.fromFloat x)
|
(whole, fractional) = splitAt '.' (String.fromFloat x)
|
||||||
in
|
in
|
||||||
whole ++ "," ++ String.slice 0 2 (fractional ++ "00") ++ "€"
|
whole ++ "," ++ String.slice 0 2 (fractional ++ "00") ++ "€"
|
||||||
|
|
||||||
|
roundTo : Int -> Float -> Float
|
||||||
|
roundTo decimals x =
|
||||||
|
let
|
||||||
|
m = toFloat <| 10^decimals
|
||||||
|
in
|
||||||
|
toFloat (round (x * m)) / m
|
||||||
|
@ -67,6 +67,9 @@ type SnackAPI =
|
|||||||
:<|> "updateSnack" :> Summary "Update a snack"
|
:<|> "updateSnack" :> Summary "Update a snack"
|
||||||
:> ReqBody '[JSON] UpdateSnackP
|
:> ReqBody '[JSON] UpdateSnackP
|
||||||
:> Post '[JSON] SnackId
|
:> Post '[JSON] SnackId
|
||||||
|
:<|> "deleteSnack" :> Summary "Delete a snack"
|
||||||
|
:> ReqBody '[JSON] DeleteSnackP
|
||||||
|
:> PostNoContent
|
||||||
|
|
||||||
data GetUnsoundBarcodesP = GetUnsoundBarcodesP
|
data GetUnsoundBarcodesP = GetUnsoundBarcodesP
|
||||||
{ location :: LocationId
|
{ location :: LocationId
|
||||||
@ -135,6 +138,10 @@ data UpdateSnackP = UpdateSnackP
|
|||||||
, taxGroup :: TaxGroupId
|
, taxGroup :: TaxGroupId
|
||||||
} deriving (Generic, FromJSON, ToSchema)
|
} deriving (Generic, FromJSON, ToSchema)
|
||||||
|
|
||||||
|
data DeleteSnackP = DeleteSnackP
|
||||||
|
{ snack :: SnackId
|
||||||
|
} deriving (Generic, FromJSON, ToSchema)
|
||||||
|
|
||||||
-- Orphan instances for database types
|
-- Orphan instances for database types
|
||||||
-- needed for serialization and swagger doc
|
-- needed for serialization and swagger doc
|
||||||
|
|
||||||
@ -197,6 +204,7 @@ server conn =
|
|||||||
:<|> createSnack
|
:<|> createSnack
|
||||||
:<|> getSnacksByItemId
|
:<|> getSnacksByItemId
|
||||||
:<|> updateSnack
|
:<|> updateSnack
|
||||||
|
:<|> deleteSnack
|
||||||
where
|
where
|
||||||
getUnsoundBarcodes :: GetUnsoundBarcodesP -> Handler [UnsoundBarcodeDTO]
|
getUnsoundBarcodes :: GetUnsoundBarcodesP -> Handler [UnsoundBarcodeDTO]
|
||||||
getUnsoundBarcodes params = do
|
getUnsoundBarcodes params = do
|
||||||
@ -252,6 +260,10 @@ server conn =
|
|||||||
params.price
|
params.price
|
||||||
params.taxGroup
|
params.taxGroup
|
||||||
|
|
||||||
|
deleteSnack params = do
|
||||||
|
liftIO $ Queries.runFunction conn $ Queries.snackDelete params.snack
|
||||||
|
pure NoContent
|
||||||
|
|
||||||
jonSwaggerDoc :: Swagger
|
jonSwaggerDoc :: Swagger
|
||||||
jonSwaggerDoc = toSwagger (Proxy :: Proxy JonAPI)
|
jonSwaggerDoc = toSwagger (Proxy :: Proxy JonAPI)
|
||||||
& info . title .~ "jon API"
|
& info . title .~ "jon API"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
html {
|
html {
|
||||||
font-size: 12px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
button, input {
|
button, input {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user