-
Notifications
You must be signed in to change notification settings - Fork 68
/
Product.cs
116 lines (94 loc) · 4.11 KB
/
Product.cs
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
using MyWarehouse.Domain.Common;
using MyWarehouse.Domain.Common.ValueObjects.Mass;
using MyWarehouse.Domain.Common.ValueObjects.Money;
using MyWarehouse.Domain.Exceptions;
using MyWarehouse.Domain.Transactions;
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace MyWarehouse.Domain.Products
{
public class Product : MyEntity
{
[Required]
[StringLength(ProductInvariants.NameMaxLength)]
public string Name { get; private set; }
[Required]
[StringLength(ProductInvariants.DescriptionMaxLength)]
public string Description { get; private set; }
[Required]
public Money Price { get; private set; }
[Required]
public Mass Mass { get; private set; }
public int NumberInStock { get; private set; }
private Product() // EF
{}
public Product(string name, string description, Money price, Mass mass)
{
UpdateName(name);
UpdateDescription(description);
CheckMass(mass?.Value ?? throw new ArgumentNullException(nameof(mass)));
CheckPrice(price?.Amount ?? throw new ArgumentNullException(nameof(price)));
Mass = mass;
Price = price;
NumberInStock = 0;
}
public void UpdateMass(float value)
{
CheckMass(value);
Mass = new Mass(value, Mass?.Unit ?? ProductInvariants.DefaultMassUnit);
}
public void UpdatePrice(decimal amount)
{
CheckPrice(amount);
Price = new Money(amount, Price?.Currency ?? ProductInvariants.DefaultPriceCurrency);
}
public void UpdateName(string value)
{
if (string.IsNullOrWhiteSpace(value))
throw new ArgumentException("Name cannot be empty.");
if (value.Length > ProductInvariants.NameMaxLength)
throw new ArgumentException($"Length of value ({value.Length}) exceeds maximum name length ({ProductInvariants.NameMaxLength}).");
Name = value;
}
public void UpdateDescription(string value)
{
if (string.IsNullOrWhiteSpace(value))
throw new ArgumentException("Description cannot be empty.");
if (value.Length > ProductInvariants.DescriptionMaxLength)
throw new ArgumentException($"Length of value ({value.Length}) exceeds maximum description length ({ProductInvariants.NameMaxLength}).");
Description = value;
}
/// <summary>
/// Adjust product stock based on a transaction occurred.
/// </summary>
internal void RecordTransaction(TransactionLine transactionLine)
{
if (transactionLine.Quantity < 1)
throw new ArgumentException("Product quantity in transaction must be 1 or greater.");
switch (transactionLine.Transaction.TransactionType)
{
case TransactionType.Sales:
if (transactionLine.Quantity > NumberInStock)
throw new InsufficientStockException(this, transactionLine.Quantity, NumberInStock);
NumberInStock -= transactionLine.Quantity;
break;
case TransactionType.Procurement:
NumberInStock += transactionLine.Quantity;
break;
default:
throw new InvalidEnumArgumentException($"Unexpected {nameof(TransactionType)}: '{transactionLine.Transaction.TransactionType}'.");
}
}
private static void CheckMass(float value)
{
if (value < ProductInvariants.MassMinimum)
throw new ArgumentException($"Value '{value}' is smaller than the minimum required mass of {ProductInvariants.MassMinimum}.");
}
private static void CheckPrice(decimal amount)
{
if (amount < ProductInvariants.PriceMinimum)
throw new ArgumentException($"Amount '{amount}' is smaller than the minimum required price of {ProductInvariants.MassMinimum}.");
}
}
}