-
Notifications
You must be signed in to change notification settings - Fork 7
/
Invoice.scala
127 lines (91 loc) · 3.29 KB
/
Invoice.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package com.zilverline.examples.immutabledomain.jpa
import javax.persistence._
import scala.collection.JavaConversions._
import java.math.BigDecimal
import java.util.{ArrayList, Collections, Date, List}
import org.joda.time.{DateTimeUtils, LocalDate}
@Entity
class InvoiceItem {
@Id
@GeneratedValue
private var _id: Int = _
@ManyToOne
private var _invoice: Invoice = _
@Basic(optional = false)
private var _description: String = _
@Basic(optional = false)
private var _amount: BigDecimal = _
def this(invoice: Invoice, description: String, amount: BigDecimal) {
this ()
_invoice = invoice
_description = description
_amount = amount
}
def description = _description
def amount = _amount
}
@Entity
class Invoice {
@Id
@GeneratedValue
private var _id: Int = _
private var _recipient: String = _
@OneToMany(cascade = Array(CascadeType.ALL))
@OrderBy
private var _items: List[InvoiceItem] = new ArrayList
@Basic(optional = false)
private var _totalAmount: BigDecimal = BigDecimal.ZERO
@Temporal(TemporalType.DATE)
private var _sentDate: Date = _
@Temporal(TemporalType.DATE)
private var _dueDate: Date = _
@Temporal(TemporalType.DATE)
private var _paymentDate: Date = _
@Temporal(TemporalType.DATE)
private var _reminderDate: Date = _
def recipient_? = _recipient != null
def recipient = Option(_recipient)
def recipient_=(recipient: Option[String]) {
require(!sent_?, "recipient cannot be changed after invoice is sent")
_recipient = recipient.map(_.trim).filter(!_.isEmpty).orNull
}
def totalAmount = _totalAmount
def items_? = _items.nonEmpty
def items = Collections.unmodifiableList(_items)
def addItem(description: String, amount: BigDecimal) {
require(!sent_?, "items cannot be changed after invoice is sent")
_totalAmount = _totalAmount.add(amount)
_items.add(new InvoiceItem(this, description, amount))
}
def removeItem(index: Int) {
require(!sent_?, "items cannot be changed after invoice is sent")
val item = _items.remove(index)
_totalAmount = _totalAmount.subtract(item.amount)
}
def sent_? = _sentDate != null
def readyToSend_? = recipient_? && items_? && !sent_?
def send {
require(!sent_?, "invoice already sent")
require(readyToSend_?, "recipient and items must be specified before sending")
val now = new LocalDate
_sentDate = now.toDateTimeAtStartOfDay.toDate
_dueDate = now.plusDays(14).toDateTimeAtStartOfDay.toDate
}
def late_? = readyForPayment_? && _dueDate.getTime < DateTimeUtils.currentTimeMillis
def remind {
require(late_?, "invoice must be late for reminder")
_reminderDate = new LocalDate().toDateTimeAtStartOfDay.toDate
}
def readyForPayment_? = sent_? && !paid_?
def paid_? = _paymentDate != null
def paymentReceived {
require(sent_?, "invoice cannot be paid before sending")
require(!paid_?, "invoice already paid")
val now = new LocalDate
_paymentDate = now.toDateTimeAtStartOfDay.toDate
}
def sentDate = if (_sentDate == null) null else new LocalDate(_sentDate)
def dueDate = if (_dueDate == null) null else new LocalDate(_dueDate)
def paymentDate = if (_paymentDate == null) null else new LocalDate(_paymentDate)
def reminderDate = if (_reminderDate == null) null else new LocalDate(_reminderDate)
}