Browse Source

working on company editing

Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
featue/module_registry
Stephan Richter 3 months ago
parent
commit
abfed21393
  1. 29
      company/src/main/java/de/srsoftware/umbrella/company/CompanyModule.java
  2. 22
      company/src/main/java/de/srsoftware/umbrella/company/SqliteDb.java
  3. 2
      company/src/main/java/de/srsoftware/umbrella/company/api/CompanyDb.java
  4. 142
      core/src/main/java/de/srsoftware/umbrella/core/model/Company.java
  5. 64
      frontend/src/routes/company/Index.svelte

29
company/src/main/java/de/srsoftware/umbrella/company/CompanyModule.java

@ -3,8 +3,9 @@ package de.srsoftware.umbrella.company; @@ -3,8 +3,9 @@ package de.srsoftware.umbrella.company;
import static de.srsoftware.umbrella.company.Constants.CONFIG_DATABASE;
import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
import static de.srsoftware.umbrella.core.Constants.ID;
import static de.srsoftware.umbrella.core.Paths.LIST;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingFieldException;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;
import com.sun.net.httpserver.HttpExchange;
import de.srsoftware.configuration.Configuration;
@ -50,6 +51,32 @@ public class CompanyModule extends BaseHandler implements CompanyService { @@ -50,6 +51,32 @@ public class CompanyModule extends BaseHandler implements CompanyService {
}
}
@Override
public boolean doPatch(Path path, HttpExchange ex) throws IOException {
addCors(ex);
try {
Optional<Token> token = SessionToken.from(ex).map(Token::of);
var user = users.loadUser(token);
if (user.isEmpty()) return unauthorized(ex);
var head = path.pop();
return switch (head) {
case null -> super.doGet(path, ex);
default -> patchProject(Long.parseLong(head), user.get(), ex);
};
} catch (NumberFormatException n) {
return send(ex,invalidFieldException(ID,"ID (Long)"));
} catch (UmbrellaException e) {
return send(ex,e);
}
}
private boolean patchProject(long companyId, UmbrellaUser user, HttpExchange ex) throws IOException {
var company = get(companyId);
if (!membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company.name());
var json = json(ex);
return sendContent(ex,companyDb.save(company.patch(json)));
}
@Override
public Company get(long companyId) throws UmbrellaException {
return companyDb.load(companyId);

22
company/src/main/java/de/srsoftware/umbrella/company/SqliteDb.java

@ -4,6 +4,7 @@ package de.srsoftware.umbrella.company; @@ -4,6 +4,7 @@ package de.srsoftware.umbrella.company;
import static de.srsoftware.tools.jdbc.Condition.equal;
import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL;
import static de.srsoftware.tools.jdbc.Query.select;
import static de.srsoftware.tools.jdbc.Query.update;
import static de.srsoftware.umbrella.company.Constants.TABLE_COMPANIES;
import static de.srsoftware.umbrella.company.Constants.TABLE_COMPANIES_USERS;
import static de.srsoftware.umbrella.core.Constants.*;
@ -40,6 +41,7 @@ public class SqliteDb implements CompanyDb { @@ -40,6 +41,7 @@ public class SqliteDb implements CompanyDb {
}
}
@Override
public Map<Long,Company> listCompaniesOf(long userId) throws UmbrellaException {
try {
@ -69,4 +71,24 @@ public class SqliteDb implements CompanyDb { @@ -69,4 +71,24 @@ public class SqliteDb implements CompanyDb {
throw databaseException("Could not load company {0}",companyId);
}
}
@Override
public Company save(Company company) {
try {
if (company.id() == 0){ // new
throw new RuntimeException("Not implemented");
} else { // update
if (company.isDirty()) {
update(TABLE_COMPANIES)
.set(NAME, ADDRESS, EMAIL, FIELD_PHONE, FIELD_BANK_ACCOUNT, FIELD_COURT, FIELD_CURRENCY, FIELD_TAX_NUMBER, DECIMALS, DECIMAL_SEPARATOR, THOUSANDS_SEPARATOR, LAST_CUSTOMER_NUMBER, CUSTOMER_NUMBER_PREFIX)
.where(ID,equal(company.id())).prepare(db)
.apply(company.name(), company.address(), company.email(), company.phone(), company.bankAccount(), company.court(), company.currency(), company.taxId(), company.decimals(), company.decimalSeparator(), company.thousandsSeparator(), company.lastCustomerNumber(), company.customerNumberPrefix())
.close();
}
return company;
}
} catch (SQLException e){
throw UmbrellaException.databaseException("Failed to save {0}…",company.name());
}
}
}

2
company/src/main/java/de/srsoftware/umbrella/company/api/CompanyDb.java

@ -12,4 +12,6 @@ public interface CompanyDb { @@ -12,4 +12,6 @@ public interface CompanyDb {
Map<Long,Company> listCompaniesOf(long id) throws UmbrellaException;
Company load(long companyId) throws UmbrellaException;
Company save(Company company);
}

142
core/src/main/java/de/srsoftware/umbrella/core/model/Company.java

@ -9,29 +9,102 @@ import de.srsoftware.tools.Mappable; @@ -9,29 +9,102 @@ import de.srsoftware.tools.Mappable;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Currency;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.json.JSONException;
import org.json.JSONObject;
public record Company(long id, String name, String address, String court, String taxId, String phone, String decimalSeparator, String thousandsSeparator, long lastCustomerNumber, int decimals, String customerNumberPrefix, String currency, String email, String bankAccount) implements Mappable {
public class Company implements Mappable {
private final long id;
private String name, address, court, taxId, phone, decimalSeparator, thousandsSeparator, customerNumberPrefix, currency, email, bankAccount;;
private long lastCustomerNumber;
private int decimals;
private final Set<String> dirtyFields = new HashSet<>();
private Company(long id){
this(id,null,null,null,null,null,null,null,0,2,null,null,null,null);
}
public Company(long id, String name, String address, String court, String taxId, String phone, String decimalSep, String thousandsSep, long lastCustomerNumber, int decimals, String customerNumberPrefix, String currency, String email, String bankAccount){
this.id = id;
this.name = name;
this.address = address;
this.court = court;
this.taxId = taxId;
this.phone = phone;
this.decimalSeparator = decimalSep;
this.thousandsSeparator = thousandsSep;
this.lastCustomerNumber = lastCustomerNumber;
this.decimals = decimals;
this.customerNumberPrefix = customerNumberPrefix;
this.currency = currency;
this.email = email;
this.bankAccount = bankAccount;
}
public String address(){
return address;
}
public String bankAccount() {
return bankAccount;
}
public Company clean(){
dirtyFields.clear();
return this;
}
public String court() {
return court;
}
public String currency() {
return currency;
}
public String customerNumberPrefix() {
return customerNumberPrefix;
}
public int decimals() {
return decimals;
}
public String decimalSeparator() {
return decimalSeparator;
}
public String email() {
return email;
}
public long id(){
return id;
}
public boolean isDirty() {
return !dirtyFields.isEmpty();
}
public boolean isDirty(String field){
return dirtyFields.contains(field);
}
public long lastCustomerNumber() {
return lastCustomerNumber;
}
public String name(){
return name;
}
public static Company of(JSONObject json) throws UmbrellaException {
try {
var id = json.getLong(ID);
var name = json.getString(NAME);
var address = json.getString(ADDRESS);
var court = json.getString(FIELD_COURT);
var taxId = json.getString(FIELD_TAX_NUMBER);
var phone = json.getString(FIELD_PHONE);
var decimalSep = json.getString(DECIMAL_SEPARATOR);
var thousandsSep = json.getString(THOUSANDS_SEPARATOR);
var lastCustomerNumber = json.getLong(LAST_CUSTOMER_NUMBER);
var decimals = json.getInt(DECIMALS);
var customerNumberPrefix = json.getString(CUSTOMER_NUMBER_PREFIX);
var currency = json.getString(FIELD_CURRENCY);
var email = json.getString(EMAIL);
var bankAccount = json.getString(FIELD_BANK_ACCOUNT);
return new Company(id,name,address,court,taxId,phone,decimalSep,thousandsSep,lastCustomerNumber,decimals,customerNumberPrefix,currency,email,bankAccount);
return new Company(json.getLong(ID)).patch(json).clean();
} catch (JSONException e){
throw new UmbrellaException(500,"Failed to convert JSON to Company!").causedBy(e);
}
@ -59,6 +132,42 @@ public record Company(long id, String name, String address, String court, String @@ -59,6 +132,42 @@ public record Company(long id, String name, String address, String court, String
}
}
public Company patch(JSONObject json) {
for (var key : json.keySet()){
switch (key){
case NAME: name = json.getString(NAME); break;
case ADDRESS: address = json.getString(ADDRESS); break;
case FIELD_COURT: court = json.getString(FIELD_COURT);
case FIELD_TAX_NUMBER: taxId = json.getString(FIELD_TAX_NUMBER); break;
case FIELD_PHONE: phone = json.getString(FIELD_PHONE); break;
case DECIMAL_SEPARATOR: decimalSeparator = json.getString(DECIMAL_SEPARATOR); break;
case THOUSANDS_SEPARATOR: thousandsSeparator = json.getString(THOUSANDS_SEPARATOR); break;
case LAST_CUSTOMER_NUMBER: lastCustomerNumber = json.getLong(LAST_CUSTOMER_NUMBER); break;
case DECIMALS: decimals = json.getInt(DECIMALS); break;
case CUSTOMER_NUMBER_PREFIX: customerNumberPrefix = json.getString(CUSTOMER_NUMBER_PREFIX); break;
case FIELD_CURRENCY: currency = json.getString(FIELD_CURRENCY); break;
case EMAIL: email = json.getString(EMAIL); break;
case FIELD_BANK_ACCOUNT: bankAccount = json.getString(FIELD_BANK_ACCOUNT); break;
default: key = null;
}
if (key != null) dirtyFields.add(key);
}
return this;
}
public String phone() {
return phone;
}
public String taxId() {
return taxId;
}
public String thousandsSeparator() {
return thousandsSeparator;
}
@Override
public String toString() {
return name;
@ -83,4 +192,5 @@ public record Company(long id, String name, String address, String court, String @@ -83,4 +192,5 @@ public record Company(long id, String name, String address, String court, String
entry(FIELD_BANK_ACCOUNT,emptyIfNull(bankAccount))
);
}
}

64
frontend/src/routes/company/Index.svelte

@ -1,7 +1,69 @@ @@ -1,7 +1,69 @@
<script>
import {t} from '../../translations.svelte.js';
import {onMount} from 'svelte';
import {api} from '../../urls.svelte.js';
import {t} from '../../translations.svelte.js';
import Editor from './Editor.svelte';
let companies = $state(null);
let error = $state(null);
let selected = $state(0);
async function loadCompanies(){
const url = api('company/list');
const resp = await fetch(url,{credentials:'include'});
if (resp.ok){
companies = await resp.json();
console.log(companies);
error = null;
} else {
error = await resp.text();
}
}
function showDetail(company_id){
selected = company_id;
}
onMount(loadCompanies)
</script>
<fieldset>
<legend>{t('companies')}</legend>
{#if error}
<span class="error">{error}</span>
{/if}
{#if companies}
<table class="companies">
<thead>
<tr>
<th>
{t('name')}
</th>
<th>
{t('email')}
</th>
<th>
{t('detail')}
</th>
</tr>
</thead>
<tbody>
{#each Object.entries(companies) as [cid, company]}
<tr onclick={e => showDetail(cid)}>
<td>{company.name}</td>
<td>{company.email}</td>
<td>{company.address.replace('\r','').replace('\n',' / ')}</td>
</tr>
{#if selected==cid}
<tr>
<td colspan="3">
<Editor {company} />
</td>
</tr>
{/if}
{/each}
</tbody>
</table>
{/if}
</fieldset>
Loading…
Cancel
Save