How to put the increment invoice number to DatabaseReference - java

I am creating an invoice with increment numbers start from #1 #2 #3 ...., but I have no idea how to start with. Here is the structure I want to have:
Invoice#1
|- info...
Invoice#2
|- info...
Invoice#3
|- info...
DatabaseReference ref
= FirebaseDatabase.getInstance().getReference().child("Invoice#" {increment}); //how to put increment here? if I declare i=1 in myActivity.java, it only runs in one
and this is part of the Invoice model I have
public class Invoice {
String buyer, seller, typeOfPymt;
int total;
String billdate;
int invoice_num;
int discount;
int tax;
int grand_total;
public Invoice(String buyer, String seller, int grand_total, String billdate, int invoice_num, int discount) {
this.buyer = buyer;
this.seller = seller;
this.billdate = billdate;
this.invoice_num = invoice_num;
this.discount = discount;
this.grand_total = grand_total;
}
How can I add increments inside the Model?

There is no way you can pass an "increment" argument to the child() method that can help you read the last invoice number and generate a new incremented one.
In your database, a more appropriate approach would be to use as a key of your invoice a random key that is generated by the push() method and not those incrementing voice numbers. The main reason is scalability, as it is explained by #FrankvanPuffelen in the following post:
How to create auto incremented key in Firebase?
Using the above approach, the number of your invoice will become a property in your invoice object.

Related

How to iterate through a list and match transactions

I am working on a project to upload my trades directly to an app I am building, by consuming a CSV file produced by my broker, instead of having to manually enter trades in a journal or paying for one.
My problem is that the data is represented as transactions not trades, therefore I have to match transactions (Buys/sells) and create another object from that. The reason I want to create a "Trade" Object is to store a list of them in a database and pass those objects to other methods to calculate stuff.
Here is what the data looks like from my broker:
Here is the Header for the CSV file:
Account,T/D,S/D,Currency,Type,Side,Symbol,Qty,Price,Exec Time,Comm,SEC,TAF,NSCC,Nasdaq,ECN Remove,ECN Add,Gross Proceeds,Net Proceeds,Clr Broker,Liq,Note
Sample data of the CSV file containing multiple examples of transactions:
FAKEACCOUNT,12/22/2020,12/23/2020,USD,2,B,MSFT201224P00222500,1,0.77,09:50:45,0.59,0,0,0.033,0.09,0,0,-77,-77.713,LAMP,,
FAKEACCOUNT,12/23/2020,12/24/2020,USD,2,S,MSFT201224P00222500,7,1.3,09:47:32,4.13,0.03,0.01,0.033,0.63,0,0,910,905.167,VOLANT,,
FAKEACCOUNT,12/24/2020,12/29/2020,USD,2,B,COCP,450,1.7,07:31:58,2.25,0,0,0.033,0.007065,0,0,-765,-767.290065,LAMP,e,
FAKEACCOUNT,12/24/2020,12/29/2020,USD,2,B,COCP,75,1.65,08:08:06,0.99,0,0,0.033,0.0011775,0,0,-123.75,-124.7741775,LAMP,X,
FAKEACCOUNT,12/24/2020,12/29/2020,USD,2,B,COCP,15,1.63,09:29:23,0.99,0,0,0.033,0.0002355,0,0,-24.45,-25.4732355,LAMP,,
FAKEACCOUNT,12/28/2020,12/30/2020,USD,2,S,COCP,540,1.4709,10:30:36,2.7,0.02,0.07,0.033,0.008478,0,0,794.286,791.454522,MNGD,,
FAKEACCOUNT,12/29/2020,12/30/2020,USD,2,B,PYPL210108P00235000,1,5.35,09:34:21,0.59,0,0,0.033,0.09,0,0,-535,-535.713,VOLANT,,
FAKEACCOUNT,12/29/2020,12/30/2020,USD,2,S,PYPL210108P00235000,1,5.95,09:36:47,0.59,0.02,0.01,0.033,0.09,0,0,595,594.257,VOLANT,,
FAKEACCOUNT,12/29/2020,12/30/2020,USD,2,B,NFLX201231P00535000,1,5.68,11:58:17,0.59,0,0,0.033,0.09,0,0,-568,-568.713,VOLANT,,
FAKEACCOUNT,12/29/2020,12/30/2020,USD,2,B,SPY201230P00372000,1,0.91,12:01:26,0.59,0,0,0.033,0.09,0,0,-91,-91.713,VOLANT,,
FAKEACCOUNT,12/29/2020,12/30/2020,USD,2,S,SPY201230P00372000,1,0.97,12:07:18,0.59,0.01,0.01,0.033,0.09,0,0,97,96.267,VOLANT,,
FAKEACCOUNT,12/29/2020,12/30/2020,USD,2,S,NFLX201231P00535000,1,6.02,12:21:55,0.59,0.02,0.01,0.033,0.09,0,0,602,601.257,VOLANT,,
Here, I matched the same transactions per color to better explain the concept. In yellow are two transactions forming 1 trade. The opening transaction is a "Buy" (B), therefore to close it, the matching transaction should be a "Sell" (S).
Same concept, slightly more complicated in green. The opening trade is a "Buy" with 450 as quantity. The subsequent transactions are also "Buy" with the same symbol, therefore adding to the position (450 + 75 + 15 = 540 quantity). A matching transaction to close the trade should be "Sell", but it could also be in increments. So I should keep track of quantity once a trade is initialized. See how the last green transaction is a sell of 540 quantity with the same symbol, bringing the total quantity to zero for the trade, meaning the trade is completed (Closed).
I have made a Transaction class with all the required fields, a constructor, getters and setters, as well as a Trade class.
public class Transaction {
private String account;
private LocalDate transactionDate;
private LocalDate settledDate;
private String currency;
private int type;
private char side;
private String symbol;
private int quantity;
private double price;
private LocalTime executionTime;
private double commission;
private double secFee;
private double tafFee;
private double nsccFee;
private double nasdaqFee;
private double ecnRemove;
private double ecnAdd;
private double grossProceeds;
private double netProceeds;
public Transaction(String account, LocalDate transactionDate, LocalDate settledDate, String currency,
int type, char side, String symbol, int quantity, double price, LocalTime executionTime,
double commission, double secFee, double tafFee, double nsccFee, double nasdaqFee,
double ecnRemove, double ecnAdd, double grossProceeds, double netProceeds) {
this.account = account;
this.transactionDate = transactionDate;
this.settledDate = settledDate;
this.currency = currency;
this.type = type;
this.side = side;
this.symbol = symbol;
this.quantity = quantity;
this.price = price;
this.executionTime = executionTime;
this.commission = commission;
this.secFee = secFee;
this.tafFee = tafFee;
this.nsccFee = nsccFee;
this.nasdaqFee = nasdaqFee;
this.ecnRemove = ecnRemove;
this.ecnAdd = ecnAdd;
this.grossProceeds = grossProceeds;
this.netProceeds = netProceeds;
}
// Getters, setters and toString()
}
Trade Class:
public Trade(String symbol, String side, LocalDate openDate, LocalTime openTime, LocalDate closeDate,
LocalTime closeTime,
double averageOpenPrice, int shares, double averageClosingPrice, double risk, String setup,
String comments) {
//Geting unique ID based on time
Date date = Calendar.getInstance().getTime();
this.id = date.getTime();
this.symbol = symbol;
this.side = side;
this.openDate = openDate;
this.openTime = openTime;
this.closeDate = closeDate;
this.closeTime = closeTime;
this.averageOpenPrice = averageOpenPrice;
this.shares = shares;
this.averageClosingPrice = averageClosingPrice;
this.risk = risk;
this.setup = setup;
this.comments = comments;
pnl = calculatePnL(averageOpenPrice, averageClosingPrice, shares, side);
percentGain = calculatePercentGain(averageOpenPrice, averageClosingPrice, side);
}
}
My problem: I am stuck at iterating through the list of transactions and matching them, for two reasons:
Sometimes I scale out of positions meaning that I do not sell in 1 transactions (Multiple transactions to close trades), which means I would have to match multiple transactions.
There is the possibility of a trade being still partially opened in the list passed. I do not know how to handle that possibility.
Symbol could either be a "Ticker" Symbol or an Option symbol, not sure if relevant.
What I have tried:
From the consumed file I get a list of Transaction objects, and I though I would match transactions by symbol, side (Buy/sell) and quantity. The problem with that approach is that it might not be the same trade.
public ObservableList<Trade> parseTradesFromTransactions(ObservableList<Transaction> list) {
for(Transaction transaction : list) {
int closedTradecount = 0;
// Iterating through the list
String symbol = transaction.getSymbol();
LocalDate transactionDate = transaction.getTransactionDate();
int quantity = transaction.getQuantity();
char side = transaction.getSide();
// iterate through the rest and match
for(int i = 0; i < list.size(); i ++) {
if(symbol.equals(list.get(i).getSymbol())){
if(transaction.getSide() == 'B' && list.get(i).getSide() == 'S' && transaction.getQuantity() == list.get(i).getQuantity()){
closedTradecount++;
}
}
}
}
return tradeList;
}
I am very new to programming and handling data, and I want to do this right. Any help would be greatly appreciated because I can't wrap my head around matching transactions.
Thanks!
If I understand your logic correctly, you would need 2 data structures in your program:
A dynamic array (suggest using ArrayList) to hold all closed trades you collected.
A dictionary / map (suggest using HashMap) to hold all open trades and access them quickly by their symbol.
Your algorithm would look like this:
Iterate over all transactions.
For each transaction, check if its symbol is in the open trades map.
--> If it is, add the transaction to the exisitng trade. Check if it reduces the amount of symbol to 0.
----> If symobol == 0, close the trade, and move it from the map to the closed trades list.
----> if symbol > 0, continue to next transaction.
--> If it is not, create a new trade for the symbol and add it to the map.
Once all trades are processed, the map should be empty, and you can store the list in your DB.
The code would look something like this:
public class TransactionProcessor {
private ArrayList<Trade> mClosedTrades = new ArrayList<>();
private HashMap<String, Trade> mOpenTrades = new HashMap<>();
public void processTransaction(Transaction transaction) {
Trade curTrade; //for convinience
if (!mOpenTrades.containsKey(transaction.getSymbol())) {
curTrade = new Trade(transaction);
mOpenTrades.add(transaction.getSymbol(), curTrade);
} else {
curTrade = mOpenTrades.get(transaction.getSymbol());
//shortcut: this function returns true if current transaction closes the trade:
if (curTrade.addTransaction(transaction)) {
mClosedTrades.add(curTrade);
mOpenTrades.remove(curTrade.getSymbol());
}
}
}
}
For this code to work, you need to add two more functions to your Trade class.
First, add a constructor to your Trade class that initializes it directly from the first transaction, instead of passing each parameter individually.
public Trade(Transaction first) {
symbol = first.getSymbol();
// ... all other fields initialization ...
}
Second, move the logic of adding further transactions to the trade class:
public boolean addTransaction(Transaction newTrans) {
//optional: add code that makes sure this transaction belongs to this trade by checking the symbol
if (newTrans.getSide() == 'B') {
quantity += newTrans.getQuantity();
} else {
quantity -= newTrans.getQuantity();
}
return quantity == 0; //this is same as if q == 0 return true; else return false;
}
This code assumes that transactions in your CSV file are in order, so that you would never need to open a new trade while you still have quantity of any particular symbol.
Also, there is no error checking.
If there are errors in the CSV file, you could end up with negative quantity of some symbol.
If you are having trouble adding such code, you should open a separate question about it.
For your first problem,
Sometimes I scale out of positions meaning that I do not sell in 1 transactions (Multiple transactions to close trades), which means I would have to match multiple transactions.
Use groupingBy method :
Group your transactions by 'symbol' and collect as map.
Map<Symbol, List> postsPerType = transactions.stream()
.collect(groupingBy(Transactions::getSymbol));
This way you get all transactions grouped together.
There is the possibility of a trade being still partially opened in the list passed. I do not know how to handle that possibility.
Iterate above collected transactions and match the quantity by filtering out Buy and Sell transactions to ensure whether trade is completed.

setters/getters and getName() and application error [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 6 years ago.
My customer.dat files looks like as follows:
4
Jon 1000
Jane 2000
Jake 20000
Drake 100000
The first number represents the total number of customers in that file, while the first string is the Name of the customer and the latter is the balance they have.
The following code is the application code I have written. I want it to read from the customer.dat and create an array. The problem with the application is that I created a customer ID, which checks the name the user inputs(if it exists in the array( and then sets a customer ID. However, whenever I run the application, no matter what name I type, even if I type Drake - and type "1" to view the portfolio, it ends up always showing the first name which is Jon.
Scanner infile2 = new Scanner(new File("customer.dat"));
customer[]mycustomers; // declaring an array to stock
int numofcustomers = infile2.nextInt();
mycustomers = new customer [numofcustomers];
for (int i = 0; i < numofcustomers; i++)
{
mycustomers[i] = new customer(infile2.next(),infile2.nextDouble(), numofcustomers);
System.out.println(mycustomers[i].toString());
}
Scanner input = new Scanner (System.in);
System.out.println("Please type in your name");
String Name = input.nextLine();
int cusID = 0;
for (int i = 0; i < numofcustomers; i++)
{
if ( Name == mycustomers[i].getName())
{
cusID = i;
}
}
System.out.println("Please type in 1 for a customer to view their portfolio, 2 to trade stocks or 3 to exit the application");
int choice = Integer.parseInt(input.nextLine());
if (choice == 1)
{
System.out.println(mycustomers[cusID].toString());
}
The following is a snippet of what is located in my customer.java which contains setters and getters:
public customer(String n, double b, int Size)
{
Name = n;
balance = b;
stock[] A = new stock[Size];
Portfolio = A;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
I'm not sure if I was able to describe the problem correctly, but if not, let me know if any more information is required.
First, Java naming conventions usually dictate you CamelCase class names (i.e. rename to Customer instead of customer).
I believe your problem is here:
Name == mycustomers[i].getName()
In Java, Strings are objects, and you have to use the equals() method to do a comparison, like so:
Name.equals(mycustomers[i].getName())
If you use the standard ==, the comparison is done on the object's memory location, so unless Name and getName() are literally the exact same String object (unlikely), that will be false. This means the if statement never evaluates to true, cusID remains 0 as you initialized it, and so you print out the first name in the list, Jon.
I would suggest, in addition to changing the above, that you initialize cusID to -1 so you can differentiate between a name that is not found in the list and the selection of the first element in the list. Also, what if two people by the same name are in the list? (Hint: The first one will never be selected in your current implementation.)

Using 2D parallel arrays to store data

I am supposed to let up to 16 guests order wine from a menu like this:
The program has to be modular. To place an order, the guest must be shown a list of product types and then variations based on that type. Once the orders are processed I have to show a final report with: total amount made by the winery, most ordered wine product type, and the wine product/variation combo ordered the most times.
I am not sure how to make a method that will search the counter array for the most ordered product type, and then another method that will search the counter array for the most ordered product/variation combo. That is what I need help with.
import javax.swing.JOptionPane;
public class Wine_Taste{
public static void main(String[] args){
String[]wines = {"Riesling", "Chardonnay", "Sauvignon Blanc", "Merlot"};
String[][]wineTypes=
{{"Dry- $4.50", "Off Dry-$4.00", "Sweet- $5.00",},
{"Apple- $6.00", "Lemon-$5.50","Vanilla- $6.00"},
{"Lime-$4.50", "Lemongrass- $6.50","Coconut- $7.00"},
{"Plum- $5.00", "Black Cherry- $7.50","Chocolate- $6.00"}};
}
double[][]prices= {{4.50, 4.00, 5.00},
{6.00, 5.50, 6.00},
{4.50, 6.50, 7.00},
{5.00, 7.50, 6.00}};
int[][]counter ={{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0}};
counter = go(wines,wineTypes,counter,prices);
public static int[][] go(String[] wines, String[][] wineTypes, int[][] counter, double[][] prices){
go2(counter);
double totalCost = 0;
String user;
int x =0;
while (x<=16){
for(int i = 0;i<wines.length;i++){
JOptionPane.showMessageDialog(null,wines[i]);
}
user = JOptionPane.showInputDialog("choose wine 0-3");
int i = Integer.parseInt(user);
for(int j=0;j<wineTypes[i].length;j++){
JOptionPane.showMessageDialog(wineTypes[i][j]);
}
user = JOptionPane.showInputDialog("choose option 0-3");
int j = Integer.parseInt(user);
totalCost += prices[i][j];
counter[i][j]++;
user = JOptionPane.showInputDialog("Order more? y/n");
if (user.equals("y")){
x++;
else{
JOptionPane.showMessageDialog(totalCost);
}
}
}
return counter;
}
}
}
I wouldn't design the program like that. Following some basic object oriented dev principles you can have a wine class with a wine type, price etc, for example:
public class Wine {
String name;
String type;
double price;
public Wine(String name, String type, double price) {
super();
this.name = name;
this.type = type;
this.price = price;
}
//+getters setters
}
Then you can have an order class that keeps the order specific data, like which wine was ordered, the total price etc.
If for any reason you want to keep using the approach of multiple (not easy to manage) arrays then I guess you can create a hashmap where the keys are the wine names and the values the popularity. You can increment by one when a new wine is ordered. You can increment as here:
How to update a value, given a key in a java hashmap?
If for any reason you don't want or can't use this approach then you can create two functions: getPopularProductVarCombo() for the most ordered type per wine, and getMostPopular() for the most popular of all.
To implement getMostPopular you have to find the max value of the array. Here is a good example on how to do this
Print largest number in a 2d array - why do my code print three numbers
To implement getPopularProductVarCombo() then find the max value per line. Any other additional info you might need can be fetched in a similar way.

Auto update ID in Java

This is my school assignment. I need an inventory system which auto-updates product ID when users key-in a new product. I created an array of object named Product with 4 attributes(name,ID,price,quantity). The ID should not need a user input.
This part is in the input() method,which is in a different class from the Object.I didn't pass the ID to the object class like I did to the other three attributes.
x[i] = new Product(name,price,stock);
id = x[i].setID();
part of the object class:
/**
* Constructor
*/
public Product(){
id = 0; name = ""; price = 0.00; quantity = 0;
}
public Product( String n, double p, int q){
setName(n); setPrice(p); setQuantity(q);
}
public void setID(){
this.id = id++;
}
Thank you.
What you have won't work, because id is an instance variable. This means that every product you create will have an ID of 0. And calling setID() on every product you create will set the ID of avery product to 1.
You need a static counter, which would belong to the class, and not to each of its instances:
public class Product {
private static int nextId = 0;
...
public Product(String name, double price, int quantity) {
this.id = Product.nextId;
Product.nextId++;
this.name = name;
this.price = price;
this.quantity = quantity;
}
}
Note that this wouldn't work well in a multi-threaded environment, and that double is a bad choice for prices, but you'll learn that later.
See the Java tutorial for more information about instance and static variables.
Are you looking for a way of generating a unique id for each Product object? If so, the way you've coded it now doesn't work, because each Product has its own id, which is completely independent of all other Product objects. There are a couple of ways you could approach this:-
Look into what static variables mean in Java
Maintain a variable in your code that gets incremented every time you create a Product object. Pass this variable into the constructor of Product.

Am i even doing this remotely right? Java Methods

Task at hand:Consider a class ratingScore that represents a numeric rating for some thing such as a move. Attributes: A description of what is being rated, The maximum possible rating, rating.
It will have methods to: get rating from ta user, Return the maximum rating posisble, return the rating, return a string showing the rating in a format suitable for display.
a. write a method heading for each method
b. write pre and post conditions for each method
c. write some java statements to test the class
d. implement the class.
I think i did what i was supposed to do, but it is a method and i am not sure that i put enough room for it to be changed much, this is what i have so far.
import java.util.*;
public class MovieRating
{
// instance variables
private String description = " A movie that shows how racism affect our lives and choices";
private int maxRating = 10;
private int rating;
// methods
//precondition: Must have maxRating, rating and description before you post it back to the user.
//rating between 1 and 10, maxRating is set to 10, description of a movie
public void writeOutput()
{
System.out.println("The max rating is: " + maxRating );
System.out.println("Your rating is: " + rating );
System.out.println("The rating for" + description + " is " + rating);
System.out.println("while the max rating was " + maxRating);
}
// PostCondition: Will write maxRating, rating and description to the user.
//Precondition: description, enter the rating
public void readInput()
{
Scanner keyboard = new Scanner(System.in);
System.out.println("What would you rate the movie \"American History x\" out of ten");
System.out.println(description);
rating = keyboard.nextInt();
}
//postcondition: rating will be set to user's input for the movie American History x.
}
This is my Tester program.. not much so far
public class MovieRatingTester
{
public static void main(String[] args)
{
//object of the class MovieRating
MovieRating rating1 = new MovieRating();
rating1.readInput();
rating1.writeOutput();
}
}
SO did i cover what was told to cover? i think i did but i think i did it the wrong way, let me know please.
Ok, my point of view is:
Your class, MovieRating is missing some basic elements of OOP, and that is what I think you suppose to learn in this homework.
The first element missing is a constructor method, what you did is automatically assigning each new MovieRating the same description. The job of the constructor function is giving a unique values to the Object when it first built in the system.
The constructor method is special, it is public and has the exact same name is the class, as we said, in this method you suppose to assign values to your object variables.
the second thing will be to put getters/setters, these are methods who has access to your private values and will be used to assign/get the values from them. Note the use of them in the code:
import java.util.*;
public class MovieRating
{
// instance variables
private String description;
private int maxRating;
private int rating;
/*This is the constructor
Note the use of .this - the expression is used to call the class form withing
itself*/
public MovieRating(String description, int maxRating, int rating) {
this.setDescription(description);
this.setMaxRating(maxRating);
this.setRating(rating);
}
/*These are the getters and setters - get is used for getting the value
and set is used for assigning a value to it*/
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getMaxRating() {
return maxRating;
}
public void setMaxRating(int maxRating) {
this.maxRating = maxRating;
}
public int getRating() {
return rating;
}
public void setRating(int rating) {
this.rating = rating;
}
//This is a method for the printing commands - notice the use of the get methods//
public void printRatings()
{
System.out.println("The max rating is: " + this.getMaxRating() );
System.out.println("Your rating is: " + this.getRating() );
System.out.println("The rating for" + this.getDescription() + " is " +
this.getRating());
System.out.println("while the max rating was " + this.getMaxRating();
}
// PostCondition: Will write maxRating, rating and description to the user.
/*Precondition: description, enter the rating
Note the use of this.setRating()*/
public void readInput()
{
Scanner keyboard = new Scanner(System.in);
System.out.println("What would you rate the movie \"American History x\" out of ten");
System.out.println(description);
this.setRating(keyboard.nextInt());
}
//postcondition: rating will be set to user's input for the movie American History x.
}
Using the constructor, you can create a different rating from your tester program
MovieRating rating1 = new MovieRating("description 1", 10, 5);
MovieRating rating2 = new MovieRating("description 2", 9, 7);
You should not ask / print the data from the Ratings class. These ratings can come from user input, but also from database, web, etc.
1 Add getters and setters for properties of MovieRating
2 Pass the read and write methods to the main. Something like
System.out.println("The rating for the movie |" + rating1.getTitle() + "| is " + rating1.getRating());
3 You are not aggregating ratings to a movie. You can't have two rating to the same movie (v.g., by different users) together. Convert the rating attribute into a Vector to solve it. Change setRating for addRating
There are many other things, but obviously this is a starters exercise and I do not want you to get confused. Work on these issues and check with your teacher.
Java (and OO in general) is all about abstractions. You want to keep your objects as general as possible so that you extend your programs functionality without modifying existing code. This may be beyond what your professor was looking for but here are my suggestions:
1) Rating - separate this into its own class
Again, the rating is totally separate from the movie - songs can have ratings, tv shows can have ratings. Today ratings can be 1-10, tomorrow ratings can up thumbs up or thumbs down, etc. A Movie "has a" rating. Let Rating decide how to prompt the user and how to display itself.
2) Now that you have a separate Movie class, I would take away the hard-coded title, description in my Movie class (this will let me create many movies and rate them).
Then I would eliminate System.out.println in writeOutput method (you can pass in the OutputStream to the function)
By hard-coding in System.in you are forcing implementation. What if tomorrow your professor says "now, instead of printing to the console, print to a file or a database"? You have to modify the code. Actually, instead of writeOutput, I would override the toString method that all Objects have and then just call System.in(movie.toString()) in main.
3) Your test method doesn't "test" anything - it is just executing a statement. Typically a test method will simulate input, execute the statements, and check for the proper state at the end. A good way to signal that the state is improper (if your test fails, like maybe your Movie Rating is -1), then you throw an exception.
4) This is un-OO related and just a preference, but I would put both Pre and Post conditions before the methods. This just makes it easier to find in my opinion.
The idea of OO is that you separate responsibilities/concerns into separate classes. Each class is responsible for itself. This helps to keep your code more flexible and maintainable. Good luck on the assignment!

Categories