From 34463d87f1371257278298eabed8c73bb21964af Mon Sep 17 00:00:00 2001 From: mortoza Date: Mon, 30 Mar 2015 22:20:34 -0400 Subject: [PATCH 1/8] Create Product Entity class of Product --- src/main/java/org/example/backend/Product | 44 +++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 src/main/java/org/example/backend/Product diff --git a/src/main/java/org/example/backend/Product b/src/main/java/org/example/backend/Product new file mode 100644 index 0000000..8a91fb7 --- /dev/null +++ b/src/main/java/org/example/backend/Product @@ -0,0 +1,44 @@ +package org.example.backend; + +import java.io.Serializable; +import javax.persistence.Basic; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +/** + * + * @author Mortoza Khan + */ + +@Entity +public class Product implements Serializable { + + @Id + @Basic(optional = false) + @NotNull + @Column(name = "Id") + private Integer id; + @Size(max = 250) + @Column(name = "Name") + private String name; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} From 6a940fc6766b66bce1bdaacd05f75687873f28a6 Mon Sep 17 00:00:00 2001 From: mortoza Date: Mon, 7 Sep 2015 23:38:46 -0400 Subject: [PATCH 2/8] Create Invoicer Added nextOrderNumber --- Invoicer | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 Invoicer diff --git a/Invoicer b/Invoicer new file mode 100644 index 0000000..9c09dfb --- /dev/null +++ b/Invoicer @@ -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 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 invoices = new ArrayList<>(); + + @ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY) + private List 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 getInvoices() { + return invoices; + } + + public void setInvoices(List invoices) { + this.invoices = invoices; + } + + public List getAdministrators() { + return administrators; + } + + public void setAdministrators(List 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 getProducts() { + return products; + } + + public void setProducts(List 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++; + } + +} From 8b423a036574014ef501f4643fe437cef88d10fd Mon Sep 17 00:00:00 2001 From: mortoza Date: Thu, 17 Sep 2015 21:26:03 -0700 Subject: [PATCH 3/8] Create SalesOrderForm --- src/main/java/org/example/SalesOrderForm | 131 +++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 src/main/java/org/example/SalesOrderForm diff --git a/src/main/java/org/example/SalesOrderForm b/src/main/java/org/example/SalesOrderForm new file mode 100644 index 0000000..42decc2 --- /dev/null +++ b/src/main/java/org/example/SalesOrderForm @@ -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 { + + @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 = 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 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; + } + +} From e8015dbaab39974f69ce3e47bc2c117ddccb141b Mon Sep 17 00:00:00 2001 From: mortoza Date: Thu, 17 Sep 2015 21:27:08 -0700 Subject: [PATCH 4/8] Create SalesOrderView --- src/main/java/org/example/SalesOrderView | 122 +++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 src/main/java/org/example/SalesOrderView diff --git a/src/main/java/org/example/SalesOrderView b/src/main/java/org/example/SalesOrderView new file mode 100644 index 0000000..cb0459d --- /dev/null +++ b/src/main/java/org/example/SalesOrderView @@ -0,0 +1,122 @@ +package org.example; + +import com.vaadin.cdi.CDIView; +import com.vaadin.navigator.View; +import com.vaadin.navigator.ViewChangeListener; +import com.vaadin.server.FontAwesome; +import com.vaadin.ui.Alignment; +import com.vaadin.ui.Button; +import com.vaadin.ui.Notification; +import com.vaadin.ui.themes.ValoTheme; +import javax.annotation.PostConstruct; +import javax.inject.Inject; +import org.example.backend.SalesOrder; +import org.example.backend.UserSession; +import org.example.backend.service.InvoicerFacade; +import org.example.backend.service.SalesOrderFacade; +import org.vaadin.cdiviewmenu.ViewMenuUI; +import org.vaadin.viritin.button.ConfirmButton; +import org.vaadin.viritin.button.DownloadButton; +import org.vaadin.viritin.button.MButton; +import org.vaadin.viritin.fields.MTable; +import org.vaadin.viritin.layouts.MHorizontalLayout; +import org.vaadin.viritin.layouts.MVerticalLayout; + +@CDIView("salesOrder") +public class SalesOrderView extends MVerticalLayout implements View { + + @Inject + SalesOrderFacade facade; + + @Inject + InvoicerFacade invoicerFacade; + + @Inject + UserSession session; + + @Inject + SalesOrderForm form; + + @Inject + InvoicerSelect sender; + + MTable table = new MTable<>(SalesOrder.class) + .withFullWidth() + .withProperties("orderNumber", "to", "orderDate", "lastEdited", + "lastEditor","orderReference") + .withColumnHeaders("Nr", "To", "Date", "Last edited", "Edited by", "Order Reference") + .withGeneratedColumn("actions", this::getSalesOrderActions); + + @PostConstruct + public void initComponent() { + table.setColumnCollapsingAllowed(true); + table.setColumnWidth("orderDate", 105); + table.setColumnWidth("lastEdited", 105); + table.setColumnWidth("lastEditor", 110); + if (session.getUser().getAdministrates().isEmpty()) { + Notification.show("Add invoicer first!"); + ViewMenuUI.getMenu().navigateTo(MyAccount.class); + return; + } + sender.addMValueChangeListener(e -> listEntities()); + + form.setResetHandler(this::reset); + form.setSavedHandler(this::save); + + table.addMValueChangeListener(e -> { + if (e.getValue() != null) { + form.setEntity(e.getValue()); + form.openInModalPopup(); + } + }); + + listEntities(); + + Button addButton = new Button("Add", e -> { + final SalesOrder salesOrder = facade.createFor(sender.getValue()); + form.setEntity(salesOrder); + form.openInModalPopup(); + }); + expand(table); + } + + public static final int DEFAULT_DUE_DATE_DURATION = 14 * 24 * 60 * 60 * 1000; + + private void listEntities() { + table.setBeans(facade.findAll(sender.getValue())); + } + + public MHorizontalLayout getSalesOrderActions(SalesOrder salesOrder) { + final MHorizontalLayout actions = new MHorizontalLayout(); + + final MButton deleteButton = new ConfirmButton( + FontAwesome.TRASH_O, + "Are you sure you want to delete this invoice", + e -> { + facade.remove(salesOrder); + listEntities(); + } + ).withStyleName(ValoTheme.BUTTON_ICON_ONLY); + actions.add(deleteButton); + return actions; + } + + public void save(SalesOrder entity) { + facade.save(entity); + Notification.show("Saved!"); + form.getPopup().close(); + listEntities(); + } + + public void reset(SalesOrder entity) { + // just hide the form + form.getPopup().close(); + listEntities(); + } + + @Override + public + void enter(ViewChangeListener.ViewChangeEvent event) { + } + +} From 8de621b19fac816ece1a31d8162269a136961cad Mon Sep 17 00:00:00 2001 From: mortoza Date: Thu, 17 Sep 2015 21:28:09 -0700 Subject: [PATCH 5/8] Create SalesOrder --- src/main/java/org/example/backend/SalesOrder | 175 +++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 src/main/java/org/example/backend/SalesOrder diff --git a/src/main/java/org/example/backend/SalesOrder b/src/main/java/org/example/backend/SalesOrder new file mode 100644 index 0000000..456fcb3 --- /dev/null +++ b/src/main/java/org/example/backend/SalesOrder @@ -0,0 +1,175 @@ +package org.example.backend; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import javax.persistence.Transient; +import javax.validation.constraints.NotNull; +import javax.xml.bind.annotation.XmlTransient; + +/** + * + * @author Matti Tahvonen, Mortoza Khan + */ + +@Entity +public class SalesOrder extends AbstractEntity { + + public static enum Status { + New, GoodsIssued, Invoiced + } + + @NotNull + private Integer orderNumber; + + @NotNull(message = "Please select the customer...") + @ManyToOne + private Contact to; + + @ManyToOne + private Invoicer invoicer; + + @ManyToOne + private User lastEditor; + + @NotNull(message = "Null Date value is not accepted") + @Temporal(TemporalType.TIMESTAMP) + private Date lastEdited; + + @NotNull + @Temporal(TemporalType.TIMESTAMP) + private Date orderDate; + + @OneToMany(fetch=FetchType.EAGER, cascade=CascadeType.ALL, mappedBy = "salesOrder") + private List salesOrderRows = new ArrayList<>(); + + + private String orderReference; + + + + public User getLastEditor() { + return lastEditor; + } + + public void setLastEditor(User lastEditor) { + this.lastEditor = lastEditor; + lastEdited = new Date(); + } + + + public Date getLastEdited() { + return lastEdited; + } + + public void setLastEdited(Date lastEdited) { + this.lastEdited = lastEdited; + } + + public Integer getOrderNumber() { + return orderNumber; + } + + public void setOrderNumber(Integer orderNumber) { + this.orderNumber = orderNumber; + } + + public Date getOrderDate() { + return orderDate; + } + + public void setOrderDate(Date orderDate) { + this.orderDate = orderDate; + } + + public String getOrderReference() { + return orderReference; + } + + public void setOrderReference(String orderReference) { + this.orderReference = orderReference; + } + + public int getVersion() { + return version; + } + + public void setVersion(int version) { + this.version = version; + } + + public List getSalesOrderRows() { + return salesOrderRows; + } + + public void setSalesOrderRows(List salesOrderRows) { + this.salesOrderRows = salesOrderRows; + } + + + + @Transient + public Double getTotal() { + double sum = 0; + List salesOrderRows1 = getSalesOrderRows(); + for (SalesOrderRow r : salesOrderRows1) { + sum += r.getQuantity() * r.getPrice(); + } + return sum; + } + + @Transient + public String getReference() { + int ordernr = getOrderNumber(); + int checksum = 0; + int counter = 0; + int[] multipliers = {7, 3, 1}; + while (ordernr > 0) { + int d = ordernr % 10; + ordernr = ordernr / 10; + checksum += d * multipliers[counter % multipliers.length]; + counter++; + } + checksum = checksum % 10; + checksum = 10 - checksum; + checksum = checksum % 10; + String ref = "" + getOrderNumber() + checksum; + return ref; + } + + + @XmlTransient + public Invoicer getInvoicer() { + return invoicer; + } + + public void setInvoicer(Invoicer invoicer) { + this.invoicer = invoicer; + } + + + public Contact getTo() { + return to; + } + + public void setTo(Contact to) { + this.to = to; + } + + @Temporal(TemporalType.DATE) + public Date getSalesOrderDate() { + return orderDate; + } + + public void setSalesOrderDate(Date orderDate) { + this.orderDate = orderDate; + } + +} From 51c9682fcd0fbba8cd68cf9801bd63e7fb56c1b7 Mon Sep 17 00:00:00 2001 From: mortoza Date: Thu, 17 Sep 2015 21:28:56 -0700 Subject: [PATCH 6/8] Create SalesOrderRow --- .../java/org/example/backend/SalesOrderRow | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 src/main/java/org/example/backend/SalesOrderRow diff --git a/src/main/java/org/example/backend/SalesOrderRow b/src/main/java/org/example/backend/SalesOrderRow new file mode 100644 index 0000000..9fd25a0 --- /dev/null +++ b/src/main/java/org/example/backend/SalesOrderRow @@ -0,0 +1,121 @@ +package org.example.backend; + +import java.util.Date; +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; + +/** + * 18 Sep 2015 + * @author Matti Tahvonen, Mortoza Khan + */ +@Entity +public class SalesOrderRow extends AbstractEntity { + + + @ManyToOne + private Product product; + + @NotNull + private String description; + + @NotNull + @Temporal(TemporalType.DATE) + private Date requestShipDate; + + @Min(0) + @NotNull + private Double quantity = 1.0; + + @NotNull + private String unit = "h"; + + @Min(0) + @NotNull + private Double price = 1.0; + + @ManyToOne + private SalesOrder salesOrder; + + public SalesOrder getSalesOrder() { + return salesOrder; + } + + public void setSalesOrder(SalesOrder salesOrder) { + this.salesOrder = salesOrder; + } + + public Product getProduct() { + return product; + } + + public void setProduct(Product product) { + this.product = product; + } + + public String getUnit() { + return unit; + } + + public void setUnit(String unit) { + this.unit = unit; + } + + public Double getQuantity() { + return quantity; + } + + public void setQuantity(Double quantity) { + this.quantity = quantity; + } + + public Double getPrice() { + return price; + } + + public void setPrice(Double price) { + this.price = price; + } + + public Date getRequestShipDate() { + return requestShipDate; + } + + public void setRequestShipDate(Date requestShipDate) { + this.requestShipDate = requestShipDate; + } + + + + + /** + * Get the value of description + * + * @return the value of description + */ + public String getDescription() { + return description; + } + + /** + * Set the value of description + * + * @param description new value of description + */ + public void setDescription(String description) { + this.description = description; + } + + public Double getRowtotal() { + if (price == null || quantity == null) { + return 0.0; + } else { + return price * quantity; + } + } + +} From 0f6ada8370fb9ee2d9b19ef1da24712c88188ef6 Mon Sep 17 00:00:00 2001 From: mortoza Date: Thu, 17 Sep 2015 21:30:07 -0700 Subject: [PATCH 7/8] Create SalesOrderFacade --- .../example/backend/service/SalesOrderFacade | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 src/main/java/org/example/backend/service/SalesOrderFacade diff --git a/src/main/java/org/example/backend/service/SalesOrderFacade b/src/main/java/org/example/backend/service/SalesOrderFacade new file mode 100644 index 0000000..f06be99 --- /dev/null +++ b/src/main/java/org/example/backend/service/SalesOrderFacade @@ -0,0 +1,53 @@ +package org.example.backend.service; + +import java.util.Date; +import java.util.List; +import javax.ejb.Stateless; +import javax.inject.Inject; +import org.example.backend.Invoicer; +import org.example.backend.SalesOrder; +import org.example.backend.UserSession; + +/** + * 18 Sep 2015 + * @author Matti Tahvonen, Mortoza Khan + */ +@Stateless +public class SalesOrderFacade { + + @Inject + SalesOrderRepository repo; + + @Inject + InvoicerRepository invoicerRepo; + + public List findAll(Invoicer value) { + return repo.findAll(); + } + + public SalesOrder createFor(Invoicer invoicer) { + invoicer = invoicerRepo.findBy(invoicer.getId()); + SalesOrder salesOrder = new SalesOrder(); + salesOrder.setOrderNumber(invoicer.getAndIcrementNextOrderNumber()); + salesOrder.setInvoicer(invoicer); + salesOrder.setOrderDate(new Date()); + salesOrder.setLastEditor(session.getUser()); + invoicerRepo.save(invoicer); + repo.save(salesOrder); + return salesOrder; + } + + @Inject + UserSession session; + + public SalesOrder save(SalesOrder entity) { + entity.setLastEditor(session.getUser()); + return repo.save(entity); + } + + + public void remove(SalesOrder salesOrder) { + repo.remove(repo.findBy(salesOrder.getId())); + } + +} From 7b1e2ceb9539d147061729c905d1f656466db79f Mon Sep 17 00:00:00 2001 From: mortoza Date: Thu, 17 Sep 2015 21:30:49 -0700 Subject: [PATCH 8/8] Create SalesOrderRepository --- .../backend/service/SalesOrderRepository | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/main/java/org/example/backend/service/SalesOrderRepository diff --git a/src/main/java/org/example/backend/service/SalesOrderRepository b/src/main/java/org/example/backend/service/SalesOrderRepository new file mode 100644 index 0000000..1a864b0 --- /dev/null +++ b/src/main/java/org/example/backend/service/SalesOrderRepository @@ -0,0 +1,31 @@ + +package org.example.backend.service; + +import org.apache.deltaspike.data.api.EntityRepository; +import org.apache.deltaspike.data.api.Repository; +import org.example.backend.SalesOrder; + +/** + * 18 Sep 2015 + * @author Matti Tahvonen, Mortoza Khan + */ +@Repository(forEntity = SalesOrder.class) +public interface SalesOrderRepository extends EntityRepository { + + +} +package org.example.backend.service; + +import org.apache.deltaspike.data.api.EntityRepository; +import org.apache.deltaspike.data.api.Repository; +import org.example.backend.SalesOrder; + +/** + * 18 Sep 2015 + * @author Matti Tahvonen, Mortoza Khan + */ +@Repository(forEntity = SalesOrder.class) +public interface SalesOrderRepository extends EntityRepository { + + +}