implemented document creation

this required a major refactoring of the object model
This commit is contained in:
2025-07-10 12:49:32 +02:00
parent 21812d2b42
commit 163bcebf4f
43 changed files with 345 additions and 153 deletions

View File

@@ -1,11 +1,11 @@
description = "Umbrella : Documents"
dependencies{
implementation(project(":company"))
implementation(project(":core"))
implementation("de.srsoftware:configuration.api:1.0.2")
implementation("de.srsoftware:tools.jdbc:1.3.2")
implementation("de.srsoftware:tools.mime:1.1.2")
implementation("de.srsoftware:tools.optionals:1.0.0")
implementation("de.srsoftware:tools.util:2.0.3")
implementation("org.json:json:20240303")
}

View File

@@ -14,26 +14,18 @@ public class Constants {
public static final String CONFIG_DATABASE = "umbrella.modules.document.database";
public static final String CONTACTS = "contacts";
public static final String CUSTOMER_NUMBER_PREFIX = "customer_number_prefix";
public static final String DECIMAL_SEPARATOR = "decimal_separator";
public static final String DECIMALS = "decimals";
public static final String ERROR_ADDRESS_MISSING = "{0} address does not contain street address / post code / city";
public static final String LAST_CUSTOMER_NUMBER = "last_customer_number";
public static final String THOUSANDS_SEPARATOR = "thousands_separator";
public static final String PROJECT_ID = "project_id";
public static final String FIELD_AMOUNT = "amount";
public static final String FIELD_BANK_ACCOUNT = "bank_account";
public static final String FIELD_CODE = "code";
public static final String FIELD_COMPANY = "company";
public static final String FIELD_COMPANY_ID = "company_id";
public static final String FIELD_COURT = "court";
public static final String FIELD_CUSTOMER = "customer";
public static final String FIELD_CUSTOMER_EMAIL = "customer_email";
public static final String FIELD_CUSTOMER_NUMBER = "customer_number";
public static final String FIELD_CUSTOMER_TAX_NUMBER = "customer_tax_number";
public static final String FIELD_CURRENCY = "currency";
public static final String FIELD_DEFAULT_HEADER = "default_header";
public static final String FIELD_DEFAULT_FOOTER = "default_footer";
public static final String FIELD_DEFAULT_MAIL = "type_mail_text";
@@ -53,7 +45,6 @@ public class Constants {
public static final String FIELD_NET_PRICE = "net_price";
public static final String FIELD_NET_SUM = "net_sum";
public static final String FIELD_NEXT_TYPE = "next_type_id";
public static final String FIELD_PHONE = "phone";
public static final String FIELD_POS = "pos";
public static final String FIELD_POSITIONS = "positions";
public static final String FIELD_PRICE = "single_price";
@@ -61,7 +52,6 @@ public class Constants {
public static final String FIELD_PROJECTS = "projects";
public static final String FIELD_RECEIVER = "receiver";
public static final String FIELD_START_TIME = "start_time";
public static final String FIELD_TAX_NUMBER = "tax_number";
public static final String FIELD_TEMPLATE_ID = "template_id";
public static final String FIELD_TASKS = "tasks";
public static final String FIELD_TAX = "tax";

View File

@@ -3,25 +3,29 @@ package de.srsoftware.umbrella.documents;
import static de.srsoftware.tools.MimeType.MIME_FORM_URL;
import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
import static de.srsoftware.umbrella.core.Constants.ERROR_MISSING_FIELD;
import static de.srsoftware.umbrella.core.Constants.SENDER;
import static de.srsoftware.umbrella.core.Paths.LIST;
import static de.srsoftware.umbrella.core.Util.request;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingFieldException;
import static de.srsoftware.umbrella.documents.Constants.*;
import static de.srsoftware.umbrella.documents.model.Document.State.NEW;
import static java.lang.System.Logger.Level.DEBUG;
import static java.lang.System.Logger.Level.WARNING;
import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
import static java.net.HttpURLConnection.*;
import com.sun.net.httpserver.HttpExchange;
import de.srsoftware.configuration.Configuration;
import de.srsoftware.tools.Path;
import de.srsoftware.tools.SessionToken;
import de.srsoftware.umbrella.core.BaseHandler;
import de.srsoftware.umbrella.core.UmbrellaException;
import de.srsoftware.umbrella.core.api.CompanyService;
import de.srsoftware.umbrella.core.api.UserService;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.Token;
import de.srsoftware.umbrella.core.model.UmbrellaUser;
import de.srsoftware.umbrella.documents.model.Type;
import de.srsoftware.umbrella.documents.model.*;
import java.io.IOException;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
@@ -31,15 +35,17 @@ import org.json.JSONObject;
public class DocumentApi extends BaseHandler {
private final UserService users;
private final CompanyService companies;
private final Configuration config;
private final DocumentDb db;
private final UserService users;
public DocumentApi(UserService userHelper, Configuration config) throws UmbrellaException {
public DocumentApi(CompanyService companyService, Configuration config) throws UmbrellaException {
this.config = config;
var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> new UmbrellaException(ERROR_MISSING_FIELD,CONFIG_DATABASE));
var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingFieldException(CONFIG_DATABASE));
db = new SqliteDb(connect(dbFile));
users = userHelper;
companies = companyService;
users = companyService.userService();
}
@Override
@@ -111,7 +117,7 @@ public class DocumentApi extends BaseHandler {
private boolean listDocuments(HttpExchange ex, UmbrellaUser user, Token token) throws UmbrellaException {
try {
var json = json(ex);
if (!json.has(COMPANY)) throw new UmbrellaException(HTTP_BAD_REQUEST,ERROR_MISSING_FIELD, COMPANY);
if (!json.has(COMPANY)) throw missingFieldException(COMPANY);
long companyId = json.getLong(COMPANY);
var companies = getLegacyCompanies(ex,user, token);
var company = companies.get(companyId);
@@ -126,17 +132,34 @@ public class DocumentApi extends BaseHandler {
}
}
private boolean postDocument(HttpExchange ex, UmbrellaUser umbrellaUser) throws IOException, UmbrellaException {
private boolean postDocument(HttpExchange ex, UmbrellaUser user) throws IOException, UmbrellaException {
var json = json(ex);
if (!(json.has(COMPANY) && json.get(COMPANY) instanceof String cid) || cid.isBlank()) throw new UmbrellaException(HTTP_BAD_REQUEST,ERROR_MISSING_FIELD,COMPANY);
long companyId;
try {
companyId = Long.parseLong(cid);
} catch (NumberFormatException nfe){
throw new UmbrellaException(HTTP_BAD_REQUEST,nfe.getMessage());
}
if (!(json.has(SENDER) && json.get(SENDER) instanceof JSONObject senderData)) throw missingFieldException(SENDER);
if (!senderData.has(FIELD_COMPANY) || !(senderData.get(FIELD_COMPANY) instanceof Number companyId)) throw missingFieldException(FIELD_COMPANY);
var company = companies.get(companyId.longValue());
var members = companies.getMembers(companyId.longValue());
var match = false;
for (var member : members) match |= user.equals(member);
if (!match) return sendContent(ex,HTTP_FORBIDDEN,"You are mot a member of company "+companyId);
if (!json.has(FIELD_CUSTOMER) || !(json.get(FIELD_CUSTOMER) instanceof JSONObject customerData)) throw missingFieldException(FIELD_CUSTOMER);
if (!json.has(FIELD_TYPE) || !(json.get(FIELD_TYPE) instanceof Number docTypeId)) throw missingFieldException(FIELD_TYPE);
var type = db.getType(docTypeId.intValue());
var customer = Customer.of(customerData);
Template template = new Template(6,companyId.longValue(),"unknwon",null);
String currency = company.currency();
String sep = company.decimalSeparator();
var settings = db.getCustomerSettings(companyId.longValue(),type,customer.id());
var companySettings = db.getCompanySettings(companyId.longValue(),type);
var nextNumber = companySettings.nextDocId();
String lastHead = settings.header();
String lastFooter = settings.footer();
var sender = Sender.of(senderData);
LOG.log(DEBUG,json.toString(2));
return notImplemented(ex,"{0}.postDocument(…)",this);
var doc = new Document(0,companyId.longValue(),nextNumber,type, LocalDate.now(), NEW,template,null,lastHead,lastFooter,currency,sep,sender,customer,new PositionList());
var saved = db.save(doc);
db.step(companySettings);
return sendContent(ex,saved.toMap());
}
}

View File

@@ -2,7 +2,7 @@
package de.srsoftware.umbrella.documents;
import de.srsoftware.tools.Pair;
import de.srsoftware.umbrella.core.UmbrellaException;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.documents.model.CompanySettings;
import de.srsoftware.umbrella.documents.model.CustomerSettings;
import de.srsoftware.umbrella.documents.model.Document;

View File

@@ -6,6 +6,7 @@ import static de.srsoftware.tools.jdbc.Condition.equal;
import static de.srsoftware.tools.jdbc.Condition.in;
import static de.srsoftware.tools.jdbc.Query.*;
import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL;
import static de.srsoftware.umbrella.company.Constants.*;
import static de.srsoftware.umbrella.core.Constants.*;
import static de.srsoftware.umbrella.documents.Constants.*;
import static de.srsoftware.umbrella.documents.model.Document.DEFAULT_THOUSANDS_SEPARATOR;
@@ -16,7 +17,7 @@ import static java.time.ZoneOffset.UTC;
import de.srsoftware.tools.Pair;
import de.srsoftware.tools.jdbc.Query;
import de.srsoftware.umbrella.core.UmbrellaException;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.documents.model.*;
import de.srsoftware.umbrella.documents.model.Type;
import java.sql.Connection;

View File

@@ -1,34 +0,0 @@
/* © SRSoftware 2025 */
package de.srsoftware.umbrella.documents.model;
import static de.srsoftware.umbrella.core.Constants.*;
import static de.srsoftware.umbrella.documents.Constants.*;
import de.srsoftware.umbrella.core.UmbrellaException;
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) {
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);
} catch (JSONException e){
throw new UmbrellaException(500,"Failed to convert JSON to Company!").causedBy(e);
}
}
}

View File

@@ -2,10 +2,11 @@
package de.srsoftware.umbrella.documents.model;
import static de.srsoftware.umbrella.core.Constants.*;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingFieldException;
import static de.srsoftware.umbrella.documents.Constants.FIELD_TAX_ID;
import de.srsoftware.tools.Mappable;
import de.srsoftware.umbrella.core.UmbrellaException;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
@@ -63,10 +64,10 @@ public final class Customer implements Mappable {
}
public static Customer of(JSONObject json) throws UmbrellaException {
if (!json.has(ID) || !(json.get(ID) instanceof String id)) throw new UmbrellaException(400,ERROR_MISSING_FIELD,ID);
if (!json.has(NAME) || !(json.get(NAME) instanceof String name)) throw new UmbrellaException(400,ERROR_MISSING_FIELD,NAME);
if (!json.has(EMAIL) || !(json.get(EMAIL) instanceof String email)) throw new UmbrellaException(400,ERROR_MISSING_FIELD,EMAIL);
if (!json.has(FIELD_TAX_ID) || !(json.get(FIELD_TAX_ID) instanceof String taxId)) throw new UmbrellaException(400,ERROR_MISSING_FIELD,FIELD_TAX_ID);
if (!json.has(ID) || !(json.get(ID) instanceof String id)) throw missingFieldException(ID);
if (!json.has(NAME) || !(json.get(NAME) instanceof String name)) throw missingFieldException(NAME);
if (!json.has(EMAIL) || !(json.get(EMAIL) instanceof String email)) throw missingFieldException(EMAIL);
if (!json.has(FIELD_TAX_ID) || !(json.get(FIELD_TAX_ID) instanceof String taxId)) throw missingFieldException(FIELD_TAX_ID);
return new Customer(id,name,email,taxId);
}

View File

@@ -5,7 +5,7 @@ import static de.srsoftware.umbrella.core.Constants.*;
import static de.srsoftware.umbrella.documents.Constants.*;
import de.srsoftware.tools.Pair;
import de.srsoftware.umbrella.core.UmbrellaException;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import java.util.HashMap;
import java.util.Map;
import org.json.JSONObject;

View File

@@ -1,12 +1,12 @@
/* © SRSoftware 2025 */
package de.srsoftware.umbrella.documents.model;
import static de.srsoftware.umbrella.core.Constants.ERROR_MISSING_FIELD;
import static de.srsoftware.umbrella.core.Constants.NAME;
import static de.srsoftware.umbrella.core.Constants.*;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingFieldException;
import static de.srsoftware.umbrella.documents.Constants.*;
import de.srsoftware.tools.Mappable;
import de.srsoftware.umbrella.core.UmbrellaException;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
@@ -65,10 +65,10 @@ public final class Sender implements Mappable {
}
public static Sender of(JSONObject json) throws UmbrellaException {
if (!json.has(NAME) || !(json.get(NAME) instanceof String name)) throw new UmbrellaException(400,ERROR_MISSING_FIELD,NAME);
if (!json.has(FIELD_BANK_ACCOUNT) || !(json.get(FIELD_BANK_ACCOUNT) instanceof String bankAccount)) throw new UmbrellaException(400,ERROR_MISSING_FIELD,FIELD_BANK_ACCOUNT);
if (!json.has(FIELD_TAX_ID) || !(json.get(FIELD_TAX_ID) instanceof String taxId)) throw new UmbrellaException(400,ERROR_MISSING_FIELD,FIELD_TAX_ID);
if (!json.has(FIELD_COURT) || !(json.get(FIELD_COURT) instanceof String court)) throw new UmbrellaException(400,ERROR_MISSING_FIELD,FIELD_COURT);
if (!json.has(NAME) || !(json.get(NAME) instanceof String name)) throw missingFieldException(NAME);
if (!json.has(FIELD_BANK_ACCOUNT) || !(json.get(FIELD_BANK_ACCOUNT) instanceof String bankAccount)) throw missingFieldException(FIELD_BANK_ACCOUNT);
if (!json.has(FIELD_TAX_ID) || !(json.get(FIELD_TAX_ID) instanceof String taxId)) throw missingFieldException(FIELD_TAX_ID);
if (!json.has(FIELD_COURT) || !(json.get(FIELD_COURT) instanceof String court)) throw missingFieldException(FIELD_COURT);
return new Sender(name,bankAccount,taxId,court);
}