Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Order entry option before invoicing #20

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 163 additions & 0 deletions Invoicer
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package org.example.backend;

import java.util.ArrayList;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Lob;
import javax.persistence.ManyToMany;
import javax.persistence.NamedQueries;
import javax.persistence.OneToMany;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;

@Entity
@NamedQueries({})
@XmlRootElement
public class Invoicer extends AbstractEntity {

@OneToMany(mappedBy = "invoicer", fetch = FetchType.LAZY)
private List<Product> products = new ArrayList<>();

@Lob
@Basic(fetch=FetchType.EAGER)
private byte[] template;

@NotNull(message = "Name is required")
@Size(min = 3, max = 40, message = "name must be longer than 3 and less than 40 characters")
private String name;

@NotNull(message = "Address is required")
@Size(min = 1, max = 60, message = "Max 60 characters")
private String address;

@NotNull(message = "Phone is required")
@Size(min = 1, max = 60, message = "Max 60 characters")
private String phone;

@NotNull(message = "Email is required")
@Pattern(regexp = ".+@.+\\.[a-z]+", message = "Must be valid email")
@Size(min = 3, max = 40, message = "name must be longer than 3 and less than 40 characters")
private String email;

@NotNull
private String bankAccount;

private int nextInvoiceNumber = 1;

private int nextOrderNumber = 1;

@OneToMany(mappedBy = "invoicer")
private List<Invoice> invoices = new ArrayList<>();

@ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
private List<User> administrators = new ArrayList<>();

@XmlTransient
public byte[] getTemplate() {
return template;
}

public void setTemplate(byte[] template) {
this.template = template;
}

public int getNextInvoiceNumber() {
return nextInvoiceNumber;
}

public void setNextInvoiceNumber(int nextInvoiceNumber) {
this.nextInvoiceNumber = nextInvoiceNumber;
}

public String getBankAccount() {
return bankAccount;
}

public void setBankAccount(String bankAccount) {
this.bankAccount = bankAccount;
}

public String getPhone() {
return phone;
}

public void setPhone(String phone) {
this.phone = phone;
}

public List<Invoice> getInvoices() {
return invoices;
}

public void setInvoices(List<Invoice> invoices) {
this.invoices = invoices;
}

public List<User> getAdministrators() {
return administrators;
}

public void setAdministrators(List<User> administrators) {
this.administrators = administrators;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public List<Product> getProducts() {
return products;
}

public void setProducts(List<Product> products) {
this.products = products;
}

@Override
public String toString() {
return name;
}

public Integer getAndIcrementNextInvoiceNumber() {
return nextInvoiceNumber++;
}

public int getNextOrderNumber() {
return nextOrderNumber;
}

public void setNextOrderNumber(int nextOrderNumber) {
this.nextOrderNumber = nextOrderNumber;
}

public Integer getAndIcrementNextOrderNumber() {
return nextOrderNumber++;
}

}
131 changes: 131 additions & 0 deletions src/main/java/org/example/SalesOrderForm
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package org.example;

import com.vaadin.cdi.ViewScoped;
import com.vaadin.data.validator.AbstractValidator;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.DateField;
import com.vaadin.ui.Grid;
import com.vaadin.ui.TextField;
import com.vaadin.ui.Window;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import org.example.backend.Contact;
import org.example.backend.Product;
import org.example.backend.SalesOrder;
import org.example.backend.SalesOrderRow;
import org.example.backend.service.ProductFacade;
import org.vaadin.viritin.fields.ElementCollectionField;
import org.vaadin.viritin.fields.MTextField;
import org.vaadin.viritin.fields.TypedSelect;
import org.vaadin.viritin.form.AbstractForm;
import org.vaadin.viritin.label.Header;
import org.vaadin.viritin.layouts.MHorizontalLayout;
import org.vaadin.viritin.layouts.MVerticalLayout;

@ViewScoped
public class SalesOrderForm extends AbstractForm<SalesOrder> {

@Inject
ContactSelector to;

@Inject
ProductFacade productFacade;

DateField orderDate = new DateField("Date");

DateField dueDate = new DateField("Due Date");

TextField orderReference = new MTextField("Order Reference");

Header total = new Header("").setHeaderLevel(3);

public static final class RowEditorModel {

TypedSelect<Product> product = new TypedSelect<>(Product.class)
.withSelectType(ComboBox.class)
.withWidth("150px")
.setInputPrompt("Pick a product");
MTextField description = new MTextField().withFullWidth();
MTextField requestedShipDate = new MTextField("3em");
MTextField quantity = new MTextField().withWidth("3em");
MTextField unit = new MTextField().withWidth("3em");
MTextField price = new MTextField().withWidth("3em");

}

//NEED YOUR HELP IN @OneToMany relations table for Sales Order Detail
//in Table or Grid

ElementCollectionField<SalesOrderRow> salesOrderRows = new ElementCollectionField<>(
SalesOrderRow.class, RowEditorModel.class).expand("description")
.withEditorInstantiator(() -> {
RowEditorModel r = new RowEditorModel();
r.product.setOptions(
productFacade.findActiveByInvoicer(getEntity().getInvoicer()));
r.product.addMValueChangeListener(event -> {
if(event.getValue() != null) {
// Copy "default values" from Product to row
r.price.setValue(event.getValue().getPrice().toString());
r.unit.setValue(event.getValue().getUnit());

r.description.focus();
}
});
return r;
});


@PostConstruct
void init() {
// Allowing null in DB, but not when modified by the UI
to.setRequired(true);
to.addValidator(new AbstractValidator("Receiver must be set") {

@Override
protected boolean isValidValue(Object value) {
return value != null;
}

@Override
public Class getType() {
return Contact.class;
}
});
salesOrderRows.addValueChangeListener(e -> updateTotal());
}

@Override
protected Component createContent() {

return new MVerticalLayout(
new MHorizontalLayout(getToolbar()).add(total,
Alignment.MIDDLE_RIGHT)
.withFullWidth(),
new MVerticalLayout(
to,
new MHorizontalLayout(orderDate),
orderReference,
salesOrderRows
)
);
}

void updateTotal() {
try {
total.setText(getEntity().getTotal() + " €");
} catch (Exception e) {
total.setText("--");
}
}

@Override
public Window openInModalPopup() {
final Window p = super.openInModalPopup();
p.setWidth("80%");
p.setHeight("95%");
return p;
}

}
Loading