Compare commits
15 Commits
feature/it
...
css/stock
| Author | SHA1 | Date | |
|---|---|---|---|
| ebf9a83b60 | |||
| 1d55325501 | |||
| 462d0bb66e | |||
| fda7f34b99 | |||
| 56b79e1ecf | |||
| 72cb91f865 | |||
| 3833f2f978 | |||
| 5e0b59bacf | |||
| 55f5a663fe | |||
| 8197a0796c | |||
| 74a1d526ae | |||
| 4cb9c6bd2f | |||
| fdffad6022 | |||
| a4bcb02459 | |||
| e887a13bbb |
@@ -41,7 +41,7 @@ subprojects {
|
|||||||
testImplementation(platform("org.junit:junit-bom:5.10.0"))
|
testImplementation(platform("org.junit:junit-bom:5.10.0"))
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter")
|
testImplementation("org.junit.jupiter:junit-jupiter")
|
||||||
implementation("de.srsoftware:configuration.api:1.0.2")
|
implementation("de.srsoftware:configuration.api:1.0.2")
|
||||||
implementation("de.srsoftware:tools.jdbc:2.0.4")
|
implementation("de.srsoftware:tools.jdbc:2.0.7")
|
||||||
implementation("de.srsoftware:tools.http:6.0.5")
|
implementation("de.srsoftware:tools.http:6.0.5")
|
||||||
implementation("de.srsoftware:tools.mime:1.1.3")
|
implementation("de.srsoftware:tools.mime:1.1.3")
|
||||||
implementation("de.srsoftware:tools.logging:1.3.2")
|
implementation("de.srsoftware:tools.logging:1.3.2")
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import TimeRecorder from './TimeRecorder.svelte';
|
|||||||
let key = $state(null);
|
let key = $state(null);
|
||||||
const router = useTinyRouter();
|
const router = useTinyRouter();
|
||||||
const modules = $state([]);
|
const modules = $state([]);
|
||||||
|
let expand = $state(false);
|
||||||
|
|
||||||
async function fetchModules(){
|
async function fetchModules(){
|
||||||
const url = `${location.protocol}//${location.host.replace('5173','8080')}/legacy/user/modules`;
|
const url = `${location.protocol}//${location.host.replace('5173','8080')}/legacy/user/modules`;
|
||||||
@@ -27,6 +28,7 @@ async function fetchModules(){
|
|||||||
|
|
||||||
function onclick(e){
|
function onclick(e){
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
expand = false;
|
||||||
let href = e.target.getAttribute('href');
|
let href = e.target.getAttribute('href');
|
||||||
if (href) router.navigate(href);
|
if (href) router.navigate(href);
|
||||||
return false;
|
return false;
|
||||||
@@ -34,6 +36,7 @@ function onclick(e){
|
|||||||
|
|
||||||
async function search(e){
|
async function search(e){
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
expand = false;
|
||||||
router.navigate(`/search?key=${key}`);
|
router.navigate(`/search?key=${key}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -47,11 +50,12 @@ onMount(fetchModules);
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<nav>
|
<nav class={expand?"":"collapsed"}>
|
||||||
<form onsubmit={search}>
|
<form onsubmit={search}>
|
||||||
<input type="text" bind:value={key} />
|
<input type="text" bind:value={key} />
|
||||||
<button type="submit">{t('search')}</button>
|
<button type="submit">{t('search')}</button>
|
||||||
</form>
|
</form>
|
||||||
|
<button class="symbol" onclick={e => expand = !expand}></button>
|
||||||
<a href="/user" {onclick} class="user">{t('users')}</a>
|
<a href="/user" {onclick} class="user">{t('users')}</a>
|
||||||
<a href="/company" {onclick} class="company">{t('companies')}</a>
|
<a href="/company" {onclick} class="company">{t('companies')}</a>
|
||||||
<a href="/project" {onclick} class="project">{t('projects')}</a>
|
<a href="/project" {onclick} class="project">{t('projects')}</a>
|
||||||
@@ -72,7 +76,7 @@ onMount(fetchModules);
|
|||||||
{#if module.name.trim()}<a href={module.url}>{module.name}</a>{/if}
|
{#if module.name.trim()}<a href={module.url}>{module.name}</a>{/if}
|
||||||
{/each}
|
{/each}
|
||||||
{#if user.name }
|
{#if user.name }
|
||||||
<a onclick={logout}>{t('logout_user',{user:user.name})}</a>
|
<a class="logout" onclick={logout}>{t('logout_user',{user:user.name})}</a>
|
||||||
{/if}
|
{/if}
|
||||||
<TimeRecorder />
|
<TimeRecorder />
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -14,6 +14,23 @@
|
|||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
let editable = $derived(document.state == 1);
|
let editable = $derived(document.state == 1);
|
||||||
|
let sums = $derived.by(calcSums);
|
||||||
|
|
||||||
|
function calcSums(){
|
||||||
|
let data = {}
|
||||||
|
let net = 0;
|
||||||
|
let gross = 0;
|
||||||
|
for (let pos of Object.values(document.positions)){
|
||||||
|
let net_price = pos.unit_price * pos.amount;
|
||||||
|
let tax = +pos.tax;
|
||||||
|
data[tax] = net_price + (data[tax] ? data[tax] : 0);
|
||||||
|
net += net_price;
|
||||||
|
}
|
||||||
|
for (let [tax, price] of Object.entries(data)) gross += price * (+tax+100)/100;
|
||||||
|
data['net'] = net/100;
|
||||||
|
data['gross'] = (gross/100).toFixed(2);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
async function updatePositions(resp){
|
async function updatePositions(resp){
|
||||||
let json = await resp.json();
|
let json = await resp.json();
|
||||||
@@ -73,9 +90,9 @@
|
|||||||
<tr class="sums">
|
<tr class="sums">
|
||||||
<td colspan="2"></td>
|
<td colspan="2"></td>
|
||||||
<td>{t('net_sum')}</td>
|
<td>{t('net_sum')}</td>
|
||||||
<td>{document.net_sum/100} {document.currency}</td>
|
<td>{sums['net']} {document.currency}</td>
|
||||||
<td colspan="2">{t('gross_sum')}</td>
|
<td colspan="2">{t('gross_sum')}</td>
|
||||||
<td>{document.gross_sum/100} {document.currency}</td>
|
<td>{sums['gross']} {document.currency}</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { useTinyRouter } from 'svelte-tiny-router';
|
import { useTinyRouter } from 'svelte-tiny-router';
|
||||||
import { api, target } from '../../urls.svelte.js';
|
import { api, post, target } from '../../urls.svelte.js';
|
||||||
import { error, yikes } from '../../warn.svelte';
|
import { error, yikes } from '../../warn.svelte';
|
||||||
import { t } from '../../translations.svelte.js';
|
import { t } from '../../translations.svelte.js';
|
||||||
import { display } from '../../time.svelte';
|
import { display } from '../../time.svelte';
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
let notes = $state(null);
|
let notes = $state(null);
|
||||||
let pages = $state(null);
|
let pages = $state(null);
|
||||||
let projects = $state(null);
|
let projects = $state(null);
|
||||||
|
let stock = $state(null);
|
||||||
let tasks = $state(null);
|
let tasks = $state(null);
|
||||||
let times = $state(null);
|
let times = $state(null);
|
||||||
|
|
||||||
@@ -38,19 +39,16 @@
|
|||||||
window.history.replaceState(history.state, '', url);
|
window.history.replaceState(history.state, '', url);
|
||||||
|
|
||||||
const data = { key : key, fulltext : fulltext };
|
const data = { key : key, fulltext : fulltext };
|
||||||
const options = {
|
|
||||||
credentials:'include',
|
post(api('bookmark/search'),data).then(handleBookmarks);
|
||||||
method: 'POST',
|
post(api('company/search '),data).then(handleCompanies);
|
||||||
body: JSON.stringify(data)
|
post(api('document/search'),data).then(handleDocuments);
|
||||||
};
|
post(api('notes/search' ),data).then(handleNotes);
|
||||||
fetch(api('bookmark/search'),options).then(handleBookmarks);
|
post(api('project/search' ),data).then(handleProjects);
|
||||||
fetch(api('company/search'),options).then(handleCompanies);
|
post(api('task/search' ),data).then(handleTasks);
|
||||||
fetch(api('document/search'),options).then(handleDocuments);
|
post(api('stock/search' ),data).then(handleStock);
|
||||||
fetch(api('notes/search'),options).then(handleNotes);
|
post(api('time/search' ),data).then(handleTimes);
|
||||||
fetch(api('project/search'),options).then(handleProjects);
|
post(api('wiki/search' ),data).then(handleWikiPages);
|
||||||
fetch(api('task/search'),options).then(handleTasks);
|
|
||||||
fetch(api('time/search'),options).then(handleTimes);
|
|
||||||
fetch(api('wiki/search'),options).then(handleWikiPages);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onclick(e){
|
function onclick(e){
|
||||||
@@ -107,6 +105,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handleStock(resp){
|
||||||
|
if (resp.ok){
|
||||||
|
const res = await resp.json();
|
||||||
|
stock = Object.keys(res).length ? res : null;
|
||||||
|
} else {
|
||||||
|
error(resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function handleTasks(resp){
|
async function handleTasks(resp){
|
||||||
if (resp.ok){
|
if (resp.ok){
|
||||||
const res = await resp.json();
|
const res = await resp.json();
|
||||||
@@ -212,6 +219,23 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if stock}
|
||||||
|
<fieldset>
|
||||||
|
<legend>
|
||||||
|
{t('stock')}
|
||||||
|
</legend>
|
||||||
|
<ul>
|
||||||
|
{#each Object.values(stock) as item}
|
||||||
|
<li>
|
||||||
|
<a href="/stock/{item.owner.type}/{item.owner.id}/item/{item.owner_number}" {onclick} >
|
||||||
|
{item.name} [{t('code')}: <span class="code">{item.code}</span>]
|
||||||
|
</a>
|
||||||
|
{@html item.description.rendered}
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
</fieldset>
|
||||||
|
{/if}
|
||||||
{#if notes}
|
{#if notes}
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>
|
<legend>
|
||||||
|
|||||||
@@ -73,7 +73,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function measured(evt,duration,d){
|
function measured(evt,duration,d){
|
||||||
if (d > 100) return;
|
if (d > 10) return;
|
||||||
if (duration < 500){
|
if (duration < 500){
|
||||||
onclick(evt);
|
onclick(evt);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ import static de.srsoftware.umbrella.core.ModuleRegistry.companyService;
|
|||||||
import static de.srsoftware.umbrella.core.ModuleRegistry.translator;
|
import static de.srsoftware.umbrella.core.ModuleRegistry.translator;
|
||||||
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.databaseException;
|
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.databaseException;
|
||||||
import static de.srsoftware.umbrella.stock.Constants.TABLE_ITEMS;
|
import static de.srsoftware.umbrella.stock.Constants.TABLE_ITEMS;
|
||||||
|
import static java.lang.System.Logger.Level.DEBUG;
|
||||||
|
|
||||||
|
import de.srsoftware.tools.ColorLogger;
|
||||||
import de.srsoftware.tools.Tuple;
|
import de.srsoftware.tools.Tuple;
|
||||||
import de.srsoftware.umbrella.core.ModuleRegistry;
|
import de.srsoftware.umbrella.core.ModuleRegistry;
|
||||||
import de.srsoftware.umbrella.core.model.*;
|
import de.srsoftware.umbrella.core.model.*;
|
||||||
@@ -33,6 +35,7 @@ public class ItemDb {
|
|||||||
try {
|
try {
|
||||||
var companyLocations = new HashMap<Long,Location>();
|
var companyLocations = new HashMap<Long,Location>();
|
||||||
var companyInfo = new HashMap<Long, Tuple<Company,String>>(); // map from companyId → (company, language)
|
var companyInfo = new HashMap<Long, Tuple<Company,String>>(); // map from companyId → (company, language)
|
||||||
|
LOG.log(DEBUG,"Reading items:\nid: code / name / unit / price / tax rate");
|
||||||
var rs = select(ALL).from(TABLE_ITEMS).exec(db);
|
var rs = select(ALL).from(TABLE_ITEMS).exec(db);
|
||||||
while (rs.next()){
|
while (rs.next()){
|
||||||
var id = rs.getLong(ID);
|
var id = rs.getLong(ID);
|
||||||
@@ -44,13 +47,17 @@ public class ItemDb {
|
|||||||
var unitPrice = rs.getLong(UNIT_PRICE);
|
var unitPrice = rs.getLong(UNIT_PRICE);
|
||||||
var tax = rs.getLong(TAX);
|
var tax = rs.getLong(TAX);
|
||||||
var tuple = companyInfo.get(companyId);
|
var tuple = companyInfo.get(companyId);
|
||||||
|
LOG.log(DEBUG," - read item {0}: {1} / {2} / {3} / {4} / {5} %",id,companyId,code,name,unit,unitPrice,tax);
|
||||||
String lang = null;
|
String lang = null;
|
||||||
Company company;
|
Company company;
|
||||||
if (tuple == null){
|
if (tuple == null){
|
||||||
|
LOG.log(DEBUG, " loading company {0}:",companyId);
|
||||||
company = companyService().get(companyId);
|
company = companyService().get(companyId);
|
||||||
|
LOG.log(DEBUG, " → {0}",company.name());
|
||||||
for (var member : companyService().getMembers(companyId)){
|
for (var member : companyService().getMembers(companyId)){
|
||||||
lang = member.language();
|
lang = member.language();
|
||||||
if (lang != null){
|
if (lang != null){
|
||||||
|
LOG.log(DEBUG, " → language = {0}",lang);
|
||||||
tuple = Tuple.of(company,lang);
|
tuple = Tuple.of(company,lang);
|
||||||
companyInfo.put(companyId,tuple);
|
companyInfo.put(companyId,tuple);
|
||||||
break;
|
break;
|
||||||
@@ -59,12 +66,15 @@ public class ItemDb {
|
|||||||
} else {
|
} else {
|
||||||
company = tuple.a;
|
company = tuple.a;
|
||||||
lang = tuple.b;
|
lang = tuple.b;
|
||||||
|
LOG.log(DEBUG, " using company: {0} ({1})",company.name(),lang);
|
||||||
|
|
||||||
}
|
}
|
||||||
var location = companyLocations.get(companyId);
|
var location = companyLocations.get(companyId);
|
||||||
if (location == null) {
|
if (location == null) {
|
||||||
location = stockDb.save(new DbLocation(0,company,null,"virtual items",null));
|
location = stockDb.save(new DbLocation(0,company,null,"virtual items",null));
|
||||||
companyLocations.put(companyId,location);
|
companyLocations.put(companyId,location);
|
||||||
}
|
}
|
||||||
|
LOG.log(DEBUG, " using location: {0}",location.resolve().name());
|
||||||
var stockItem = new Item(0,company,0,location,code,name,description);
|
var stockItem = new Item(0,company,0,location,code,name,description);
|
||||||
var props = stockItem.properties();
|
var props = stockItem.properties();
|
||||||
var keyUnitPrice = translator().translate(lang,UNIT_PRICE);
|
var keyUnitPrice = translator().translate(lang,UNIT_PRICE);
|
||||||
@@ -75,12 +85,12 @@ public class ItemDb {
|
|||||||
props.add(new Property(0,keyUnit,unit,null));
|
props.add(new Property(0,keyUnit,unit,null));
|
||||||
props.add(new Property(0,keyTax,tax,"%"));
|
props.add(new Property(0,keyTax,tax,"%"));
|
||||||
props.add(new Property(0,keyLegacyId,id,null));
|
props.add(new Property(0,keyLegacyId,id,null));
|
||||||
|
LOG.log(DEBUG," saving item {0}:",stockItem);
|
||||||
stockDb.save(stockItem);
|
stockDb.save(stockItem);
|
||||||
}
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw databaseException("Failed to migrate items from itemDB to stockDB!");
|
throw databaseException("Failed to migrate items from itemDB to stockDB!");
|
||||||
}
|
}
|
||||||
LOG.log(System.Logger.Level.WARNING,"migrateTo({0}) not implemented", stockDb);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ package de.srsoftware.umbrella.stock;
|
|||||||
|
|
||||||
import static de.srsoftware.tools.Optionals.is0;
|
import static de.srsoftware.tools.Optionals.is0;
|
||||||
import static de.srsoftware.tools.Optionals.nullIfEmpty;
|
import static de.srsoftware.tools.Optionals.nullIfEmpty;
|
||||||
import static de.srsoftware.tools.jdbc.Condition.equal;
|
import static de.srsoftware.tools.jdbc.Condition.*;
|
||||||
import static de.srsoftware.tools.jdbc.Condition.isNull;
|
import static de.srsoftware.tools.jdbc.Condition.like;
|
||||||
import static de.srsoftware.tools.jdbc.Query.*;
|
import static de.srsoftware.tools.jdbc.Query.*;
|
||||||
import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL;
|
import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL;
|
||||||
import static de.srsoftware.umbrella.core.Constants.*;
|
import static de.srsoftware.umbrella.core.Constants.*;
|
||||||
@@ -17,6 +17,7 @@ import static java.text.MessageFormat.format;
|
|||||||
import de.srsoftware.tools.jdbc.Query;
|
import de.srsoftware.tools.jdbc.Query;
|
||||||
import de.srsoftware.umbrella.core.BaseDb;
|
import de.srsoftware.umbrella.core.BaseDb;
|
||||||
import de.srsoftware.umbrella.core.api.Owner;
|
import de.srsoftware.umbrella.core.api.Owner;
|
||||||
|
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
||||||
import de.srsoftware.umbrella.core.model.*;
|
import de.srsoftware.umbrella.core.model.*;
|
||||||
import de.srsoftware.umbrella.core.model.Location;
|
import de.srsoftware.umbrella.core.model.Location;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
@@ -189,6 +190,30 @@ public class SqliteDb extends BaseDb implements StockDb {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<Long, Item> find(Collection<Owner> owners, Collection<String> keys, boolean fulltext) {
|
||||||
|
try {
|
||||||
|
var items = new HashMap<Long,Item>();
|
||||||
|
var ownerCodes = owners.stream().map(Owner::dbCode).toArray();
|
||||||
|
var query = select(ALL).from(TABLE_ITEMS).where(OWNER, in(ownerCodes));
|
||||||
|
if (fulltext) {
|
||||||
|
query.leftJoin(ID,TABLE_ITEM_PROPERTIES,ITEM_ID);
|
||||||
|
for (var key : keys) query.where(format("CONCAT({0},\" \",{1},\" \",{2})",NAME,DESCRIPTION,VALUE),like("%"+key+"%"));
|
||||||
|
} else {
|
||||||
|
for (var key : keys) query.where(NAME,like("%"+key+"%"));
|
||||||
|
}
|
||||||
|
var rs = query.exec(db);
|
||||||
|
while (rs.next()){
|
||||||
|
var item = Item.of(rs);
|
||||||
|
items.put(item.id(),item);
|
||||||
|
}
|
||||||
|
rs.close();
|
||||||
|
return items;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new UmbrellaException("Failed to load items from database");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<DbLocation> listChildLocations(long parentId) {
|
public Collection<DbLocation> listChildLocations(long parentId) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -6,10 +6,12 @@ import de.srsoftware.umbrella.core.model.*;
|
|||||||
import de.srsoftware.umbrella.core.model.Location;
|
import de.srsoftware.umbrella.core.model.Location;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public interface StockDb {
|
public interface StockDb {
|
||||||
Property addNewProperty(long itemId, String name, Object value, String unit);
|
Property addNewProperty(long itemId, String name, Object value, String unit);
|
||||||
Location delete(DbLocation location);
|
Location delete(DbLocation location);
|
||||||
|
Map<Long, Item> find(Collection<Owner> owners, Collection<String> keys, boolean fulltext);
|
||||||
Collection<DbLocation> listChildLocations(long parentId);
|
Collection<DbLocation> listChildLocations(long parentId);
|
||||||
Collection<DbLocation> listCompanyLocations(Company company);
|
Collection<DbLocation> listCompanyLocations(Company company);
|
||||||
Collection<Item> listItemsAt(Location location);
|
Collection<Item> listItemsAt(Location location);
|
||||||
@@ -24,5 +26,6 @@ public interface StockDb {
|
|||||||
Map<String,Object> pathToLocation(Location location);
|
Map<String,Object> pathToLocation(Location location);
|
||||||
DbLocation save(DbLocation location);
|
DbLocation save(DbLocation location);
|
||||||
Item save(Item item);
|
Item save(Item item);
|
||||||
|
|
||||||
Property setProperty(long itemId, long existingPropId, Object value);
|
Property setProperty(long itemId, long existingPropId, Object value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import static de.srsoftware.umbrella.core.Field.ITEM;
|
|||||||
import static de.srsoftware.umbrella.core.ModuleRegistry.companyService;
|
import static de.srsoftware.umbrella.core.ModuleRegistry.companyService;
|
||||||
import static de.srsoftware.umbrella.core.ModuleRegistry.userService;
|
import static de.srsoftware.umbrella.core.ModuleRegistry.userService;
|
||||||
import static de.srsoftware.umbrella.core.Paths.LIST;
|
import static de.srsoftware.umbrella.core.Paths.LIST;
|
||||||
|
import static de.srsoftware.umbrella.core.Paths.SEARCH;
|
||||||
|
import static de.srsoftware.umbrella.core.Util.mapValues;
|
||||||
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;
|
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;
|
||||||
import static de.srsoftware.umbrella.stock.Constants.*;
|
import static de.srsoftware.umbrella.stock.Constants.*;
|
||||||
import static java.lang.System.Logger.Level.WARNING;
|
import static java.lang.System.Logger.Level.WARNING;
|
||||||
@@ -174,6 +176,7 @@ public class StockModule extends BaseHandler implements StockService {
|
|||||||
case LIST -> postItemList(user.get(), path, ex);
|
case LIST -> postItemList(user.get(), path, ex);
|
||||||
case LOCATION -> postLocation(user.get(),ex);
|
case LOCATION -> postLocation(user.get(),ex);
|
||||||
case PROPERTY -> postProperty(user.get(),ex);
|
case PROPERTY -> postProperty(user.get(),ex);
|
||||||
|
case SEARCH -> postSearch(user.get(),ex);
|
||||||
case null, default -> super.doPost(path,ex);
|
case null, default -> super.doPost(path,ex);
|
||||||
};
|
};
|
||||||
} catch (UmbrellaException e){
|
} catch (UmbrellaException e){
|
||||||
@@ -389,6 +392,17 @@ public class StockModule extends BaseHandler implements StockService {
|
|||||||
return sendContent(ex,property);
|
return sendContent(ex,property);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean postSearch(UmbrellaUser user, HttpExchange ex) throws IOException {
|
||||||
|
var json = json(ex);
|
||||||
|
if (!(json.has(KEY) && json.get(KEY) instanceof String key)) throw missingFieldException(KEY);
|
||||||
|
var keys = Arrays.asList(key.split(" "));
|
||||||
|
var fulltext = json.has(FULLTEXT) && json.get(FULLTEXT) instanceof Boolean val && val;
|
||||||
|
Set<Owner> owners = new HashSet<>(companyService().listCompaniesOf(user).values());
|
||||||
|
owners.add(user);
|
||||||
|
var items = stockDb.find(owners,keys,fulltext);
|
||||||
|
return sendContent(ex,mapValues(items));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Object> redefineMe(long company_id) {
|
public Collection<Object> redefineMe(long company_id) {
|
||||||
// TODO
|
// TODO
|
||||||
|
|||||||
@@ -308,3 +308,10 @@ tr:hover .taglist .tag button {
|
|||||||
.easylist .filter{
|
.easylist .filter{
|
||||||
background: black;
|
background: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 900px) {
|
||||||
|
#app nav a{
|
||||||
|
background: black;
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -426,6 +426,48 @@ a.wikilink{
|
|||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 900px) {
|
||||||
|
#app nav button.symbol{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 900px) {
|
||||||
|
body{
|
||||||
|
padding-top: 13px;
|
||||||
|
}
|
||||||
|
#app nav{
|
||||||
|
grid-template-columns: 33% 34% 33%;
|
||||||
|
display: grid;
|
||||||
|
padding: 0 10px;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
#app nav form{
|
||||||
|
grid-column-end: span 2;
|
||||||
|
}
|
||||||
|
#app nav .logout{
|
||||||
|
grid-column-end: 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app nav.collapsed a{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app nav a {
|
||||||
|
font-size: 19px !important;
|
||||||
|
display: grid;
|
||||||
|
text-align: center;
|
||||||
|
border: 1px solid;
|
||||||
|
margin: 5px;
|
||||||
|
padding: 15px 0;
|
||||||
|
border-radius: 7px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@media screen and (max-width: 600px) {
|
@media screen and (max-width: 600px) {
|
||||||
.grid2{
|
.grid2{
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -455,6 +497,15 @@ a.wikilink{
|
|||||||
.easylist input{
|
.easylist input{
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
#app nav{
|
||||||
|
grid-template-columns: auto auto;
|
||||||
|
}
|
||||||
|
#app nav form{
|
||||||
|
grid-column-end: span 1;
|
||||||
|
}
|
||||||
|
#app nav .logout{
|
||||||
|
grid-column-end: 3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldset.vcard{
|
fieldset.vcard{
|
||||||
|
|||||||
@@ -298,3 +298,10 @@ tr:hover .taglist .tag button {
|
|||||||
.easylist .filter{
|
.easylist .filter{
|
||||||
background: black;
|
background: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 900px) {
|
||||||
|
#app nav a{
|
||||||
|
background: black;
|
||||||
|
color: orange;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -504,8 +504,75 @@ a.wikilink{
|
|||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 900px) {
|
||||||
|
#app nav button.symbol{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 900px) {
|
||||||
|
body{
|
||||||
|
padding-top: 30px;
|
||||||
|
}
|
||||||
|
#app nav{
|
||||||
|
grid-template-columns: 33% 34% 33%;
|
||||||
|
display: grid;
|
||||||
|
padding: 0 10px;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
#app nav form{
|
||||||
|
grid-column-end: span 2;
|
||||||
|
}
|
||||||
|
#app nav .logout{
|
||||||
|
grid-column-end: 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app nav.collapsed a{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app nav a {
|
||||||
|
font-size: 19px !important;
|
||||||
|
display: grid;
|
||||||
|
text-align: center;
|
||||||
|
border: 1px solid;
|
||||||
|
margin: 5px;
|
||||||
|
border-radius: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app nav a::before {
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
.grid3 {
|
||||||
|
grid-template-columns: auto auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid3 .properties{
|
||||||
|
grid-column-end: span 2;
|
||||||
|
order: 1;
|
||||||
|
}
|
||||||
|
.grid3 .tags{
|
||||||
|
order: 2;
|
||||||
|
}
|
||||||
|
.grid3 .notes{
|
||||||
|
grid-column-end: span 2;
|
||||||
|
order: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid3 .locations{
|
||||||
|
order: 5;
|
||||||
|
}
|
||||||
|
.grid3 .items{
|
||||||
|
order: 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@media screen and (max-width: 600px) {
|
@media screen and (max-width: 600px) {
|
||||||
.grid2{
|
.grid2,
|
||||||
|
.grid3{
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: auto;
|
grid-template-columns: auto;
|
||||||
}
|
}
|
||||||
@@ -533,6 +600,18 @@ a.wikilink{
|
|||||||
.easylist input{
|
.easylist input{
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
#app nav{
|
||||||
|
grid-template-columns: auto auto;
|
||||||
|
}
|
||||||
|
#app nav form,
|
||||||
|
.grid3 .notes,
|
||||||
|
.grid3 .tags,
|
||||||
|
.grid3 .properties{
|
||||||
|
grid-column-end: span 1;
|
||||||
|
}
|
||||||
|
#app nav .logout{
|
||||||
|
grid-column-end: 3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldset.vcard{
|
fieldset.vcard{
|
||||||
|
|||||||
@@ -283,3 +283,10 @@ tr:hover .taglist .tag button {
|
|||||||
border-color: blue;
|
border-color: blue;
|
||||||
color: blue;
|
color: blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 900px) {
|
||||||
|
#app nav a{
|
||||||
|
background: white;
|
||||||
|
color: blue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -426,6 +426,48 @@ a.wikilink{
|
|||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 900px) {
|
||||||
|
#app nav button.symbol{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 900px) {
|
||||||
|
body{
|
||||||
|
padding-top: 13px;
|
||||||
|
}
|
||||||
|
#app nav{
|
||||||
|
grid-template-columns: 33% 34% 33%;
|
||||||
|
display: grid;
|
||||||
|
padding: 0 10px;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
#app nav form{
|
||||||
|
grid-column-end: span 2;
|
||||||
|
}
|
||||||
|
#app nav .logout{
|
||||||
|
grid-column-end: 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app nav.collapsed a{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app nav a {
|
||||||
|
font-size: 19px !important;
|
||||||
|
display: grid;
|
||||||
|
text-align: center;
|
||||||
|
border: 1px solid;
|
||||||
|
margin: 5px;
|
||||||
|
padding: 15px 0;
|
||||||
|
border-radius: 7px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@media screen and (max-width: 600px) {
|
@media screen and (max-width: 600px) {
|
||||||
.grid2{
|
.grid2{
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -455,6 +497,15 @@ a.wikilink{
|
|||||||
.easylist input{
|
.easylist input{
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
#app nav{
|
||||||
|
grid-template-columns: auto auto;
|
||||||
|
}
|
||||||
|
#app nav form{
|
||||||
|
grid-column-end: span 1;
|
||||||
|
}
|
||||||
|
#app nav .logout{
|
||||||
|
grid-column-end: 3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldset.vcard{
|
fieldset.vcard{
|
||||||
|
|||||||
Reference in New Issue
Block a user