mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-01-27 01:32:09 +00:00
**NOTE TO SYSADMINS: See "SQL Details" section below for information on SQL modifications.** Moves the data containing cargo items (i.e. the ones you order from ops and get in the cargo shuttle) from the online database to the codebase. Everything from suppliers to categories to individual items is now code-side and editable by developers/contributors. Refactors cargo items to use `singletons` instead of `datums` for `cargo_supplier`, `cargo_category`, and `cargo_item`. Multiple-instnace things like cargo_orders, etc. still use `datums`. Fixed a bunch of strange discrepancies in categories, suppliers, and pricing for various cargo items. I did a little bit, but it's exhausting to go through all of it right now. Clicking the 'Details' button on the Cargo Order app now actually gives you details instead of bluescreening. Also added some UI elements to the Cargo Order app - Cargo Control and Delivery remain untouched. Overhauled the Cargo Order console TGUI window. It now has tabs on the left, displays restricted access, supplier information, and boasts search functionality. ### SQL Details <details> <summary>SQL Details [Click to Expand]</summary> The following SQL tables should be deleted or deprecated from the server database, as they are no longer in use: - `ss13_cargo_items` - `ss13_cargo_categories` - `ss13_cargo_suppliers` The included migration file, `V011__codeside_cargo`, creates a new table `ss13_cargo_item_orderlog` to the DB. This **replaces** `ss13_cargo_orderlog_items`. Because of this, `ss13_cargo_orderlog_items` is deprecated and should either be deleted or locked & preserved for logging purposes. </details> ## Screenshots      --------- Signed-off-by: naut <55491249+nauticall@users.noreply.github.com> Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>
476 lines
16 KiB
Plaintext
476 lines
16 KiB
Plaintext
//NOTE: Cargo orders, categories and suppliers have been moved to singletons (10/11/2024).
|
|
|
|
/datum/cargo_order
|
|
var/list/items = list() //List of cargo_items in the order
|
|
var/order_id = 0 //ID of the order
|
|
var/price = 0 //Total price of the order
|
|
var/item_id = 1 //Current id of the item in the order
|
|
var/item_num = 0 //Number of items in the container - Used to limit the items in the crate
|
|
var/status = "basket" //Status of the order: basket - Adding items, submitted - Submitted to cargo, approved - Order sent to suppliers, rejected - Order has been denied, shipped - Has been shipped to the station, delivered - Order has been delivered
|
|
var/container_type = "" //Type of the container for the order - cate, box
|
|
var/list/required_access = list() //Access required to unlock the crate
|
|
var/can_add_items = 1 //If new items can be added to the order
|
|
var/ordered_by = null //Person that ordered the items
|
|
var/ordered_by_id = null //Character ID of the person that ordered the items
|
|
var/authorized_by = null //Person that authorized the order
|
|
var/authorized_by_id = null //Character ID of the person that authorized the items
|
|
var/received_by = null //Person the order has been delivered to by cargo
|
|
var/received_by_id = null //Character ID of the person that received the items
|
|
var/paid_by = null //Person that has paid for the order
|
|
var/paid_by_id = null //Character ID of the Person that paid for the items
|
|
var/time_submitted = null //Time the order has been sent to cargo
|
|
var/time_approved = null //Time the order has been approved by cargo
|
|
var/time_shipped = null //Time the order has been shipped to the station
|
|
var/time_delivered = null //Time the order has been delivered
|
|
var/time_paid = null //The the order has been paid
|
|
var/tracking_code = null //Use this code with the order ID to get details about the order
|
|
var/reason = null //Reason for the order
|
|
|
|
//Gets the tracking code for the order. Generates one if it does not exist already
|
|
/datum/cargo_order/proc/get_tracking_code()
|
|
if(!tracking_code)
|
|
tracking_code = rand(1000,9999)
|
|
return tracking_code
|
|
|
|
// Returns a list of the items in the order - Formatted as list to be json_encoded
|
|
/datum/cargo_order/proc/get_item_list()
|
|
var/list/item_list = list()
|
|
for (var/datum/cargo_order_item/coi in items)
|
|
item_list.Add(list(coi.get_list()))
|
|
return item_list
|
|
|
|
// Returns a list of all the objects in the order - Formatted as a list to be json_encoded
|
|
/datum/cargo_order/proc/get_object_list()
|
|
var/list/object_list = list()
|
|
for (var/datum/cargo_order_item/coi in items)
|
|
for(var/atom/object in coi.ci.items)
|
|
object_list.Add(object.name)
|
|
return object_list
|
|
|
|
// Gets a list of the order data - Formatted as list to be json_encoded
|
|
/datum/cargo_order/proc/get_list()
|
|
var/list/data = list()
|
|
data["order_id"] = order_id
|
|
data["tracking_code"] = get_tracking_code()
|
|
data["price"] = get_value(2)
|
|
data["price_customer"] = get_value(0)
|
|
data["price_cargo"] = get_value(1)
|
|
data["status"] = get_order_status(0)
|
|
data["status_pretty"] = get_order_status(1)
|
|
data["status_payment"] = get_payment_status(1)
|
|
data["ordered_by"] = ordered_by
|
|
data["authorized_by"] = authorized_by
|
|
data["received_by"] = received_by
|
|
data["paid_by"] = paid_by
|
|
data["needs_payment"] = paid_by != null ? 0:1
|
|
data["time_submitted"] = time_submitted
|
|
data["time_approved"] = time_approved
|
|
data["time_shipped"] = time_shipped
|
|
data["time_delivered"] = time_delivered
|
|
data["time_paid"] = time_paid
|
|
data["items"] = get_item_list()
|
|
data["shipment_cost"] = get_shipment_cost()
|
|
data["reason"] = reason
|
|
return data
|
|
|
|
//Adds a item to a order. Returns a status message
|
|
/datum/cargo_order/proc/add_item(var/datum/cargo_order_item/coi)
|
|
if(!coi)
|
|
return "Unable to add item - Internal Error"
|
|
|
|
//Check if the container type of the added item matches the one of the current order
|
|
if(container_type == "")
|
|
container_type = coi.ci.container_type
|
|
else if (container_type != coi.ci.container_type)
|
|
return "Unable to add item - Different container required" //You can only add items with the same container type to the order
|
|
|
|
//Check if more items can be added to the order
|
|
if(!can_add_items)
|
|
return "Unable to add item - Order can not contain more items"
|
|
|
|
if(!coi.ci.groupable) //The item is not groupable with other items and needs to be ordered on its own
|
|
if(get_item_count() > 0) // There are already other items in the order. -> Reject it
|
|
return "Unable to add item - Item can not be grouped and must be ordered separately"
|
|
else //No item in the order. Add it and set can_add_items to 0
|
|
can_add_items = 0
|
|
|
|
//Check if there is space in the container
|
|
if(item_num + coi.ci.amount > get_container_storage())
|
|
return "Unable to add item - Container full"
|
|
|
|
//Set item id of coi and increment item_id of co
|
|
coi.item_id = item_id
|
|
item_id += 1
|
|
|
|
//Increment the item number
|
|
item_num += coi.ci.amount
|
|
|
|
//Add coi to ordered item
|
|
items.Add(coi)
|
|
price += coi.price
|
|
|
|
//Update the access requirement of the order
|
|
if(coi.ci.access)
|
|
required_access.Add(coi.ci.access)
|
|
|
|
return "Item successfully added"
|
|
|
|
//Removes a item from a order - Returns a status message
|
|
/datum/cargo_order/proc/remove_item(var/remove_item_id)
|
|
//Find the item with the specified id in the items list
|
|
for (var/datum/cargo_order_item/coi in items)
|
|
if(coi)
|
|
if(coi.item_id == remove_item_id)
|
|
items.Remove(coi)
|
|
price -= coi.price
|
|
item_num -= coi.ci.amount
|
|
qdel(coi)
|
|
return "Item removed successfully"
|
|
return "Unable to remove item - Internal Error 608"
|
|
|
|
// Returns the value of the order
|
|
/datum/cargo_order/proc/get_value(var/type=0)
|
|
//Type specifies if the price cargo has to pay or the price the customer has to be should be returned
|
|
// 0 - Price the customer has to pay
|
|
// 1 - Price cargo has to pay
|
|
// 2 - Just the value of the items in the crate
|
|
switch(type)
|
|
if(0)
|
|
//The price of the contents of the crate + the price for the crate + the handling fee + the shipment fee
|
|
return price + SScargo.get_cratefee() + SScargo.get_handlingfee() + get_shipment_cost()
|
|
if(1)
|
|
//The price of the contents of the crate + the price of the crate + the shipment fee
|
|
return price + SScargo.get_cratefee() + get_shipment_cost()
|
|
if(2)
|
|
//Just the value of the items in the crate
|
|
return price
|
|
else
|
|
//As a fallback, return the value of the items
|
|
return price
|
|
|
|
// Returns the number of items in the order
|
|
/datum/cargo_order/proc/get_item_count()
|
|
return items.len
|
|
|
|
// Returns the type of the required container for the order
|
|
/datum/cargo_order/proc/get_container_type()
|
|
switch(container_type)
|
|
if(CARGO_CONTAINER_CRATE)
|
|
if(required_access.len > 0)
|
|
return /obj/structure/closet/crate/secure
|
|
else
|
|
return /obj/structure/closet/crate
|
|
if(CARGO_CONTAINER_BOX)
|
|
if(required_access.len > 0)
|
|
return /obj/structure/closet/crate/secure/large
|
|
else
|
|
return /obj/structure/largecrate
|
|
if(CARGO_CONTAINER_FREEZER)
|
|
return /obj/structure/closet/crate/freezer
|
|
if(CARGO_CONTAINER_BODYBAG)
|
|
return /obj/structure/closet/body_bag
|
|
else
|
|
LOG_DEBUG("Cargo: Tried to get container type for invalid container [container_type]")
|
|
return /obj/structure/largecrate
|
|
|
|
// Returns the number of items that can be stored in the container
|
|
/datum/cargo_order/proc/get_container_storage()
|
|
switch(container_type)
|
|
if(CARGO_CONTAINER_CRATE)
|
|
return 40 //Thats the default storage capacity of a crate
|
|
if(CARGO_CONTAINER_FREEZER)
|
|
return 40
|
|
if(CARGO_CONTAINER_BOX)
|
|
return 5 //You can fit 5 larger items into a box
|
|
else
|
|
LOG_DEBUG("Cargo: Tried to get storage size for invalid container [container_type]")
|
|
return 0 //Something went wrong
|
|
|
|
// Gets the list of the suppliers involved in the order
|
|
/datum/cargo_order/proc/get_supplier_list()
|
|
var/list/supplier_list = list()
|
|
for(var/datum/cargo_order_item/coi in items)
|
|
supplier_list[coi.ci.supplier] = coi.ci.supplier
|
|
return supplier_list
|
|
|
|
// Gets the shipment cost for the order
|
|
/datum/cargo_order/proc/get_shipment_cost()
|
|
var/list/supplier_list = get_supplier_list()
|
|
var/cost = 0
|
|
for(var/supplier in supplier_list)
|
|
var/singleton/cargo_supplier/cs = SScargo.cargo_suppliers[supplier]
|
|
if(cs)
|
|
cost += cs.shuttle_price
|
|
return cost
|
|
|
|
// Gets the order status
|
|
/datum/cargo_order/proc/get_order_status(var/pretty=1)
|
|
if(pretty)
|
|
switch(status)
|
|
if("submitted")
|
|
return "Submitted to Cargo"
|
|
if("approved")
|
|
return "Approved"
|
|
if("rejected")
|
|
return "Rejected"
|
|
if("shipped")
|
|
return "Shipped to the [station_name(TRUE)]"
|
|
if("delivered")
|
|
return "Delivered"
|
|
else
|
|
return "Unknown Status"
|
|
else
|
|
return status
|
|
//Returns the payment status
|
|
/datum/cargo_order/proc/get_payment_status(var/pretty=1)
|
|
if(pretty)
|
|
if(paid_by != null)
|
|
return "Paid by [paid_by]"
|
|
else
|
|
return "Unpaid"
|
|
else
|
|
if(paid_by != null)
|
|
return 1
|
|
else
|
|
return 0
|
|
|
|
// Returns a Invoice for the Order
|
|
/datum/cargo_order/proc/get_report_invoice()
|
|
var/list/order_data = list()
|
|
var/invoice_type = "Preliminary"
|
|
if(status == "delivered" && paid_by)
|
|
invoice_type = "Final"
|
|
order_data += "<h4>[invoice_type] Invoice #[order_id]</h4>"
|
|
order_data += "<hr>"
|
|
//List the personnel involved in the order
|
|
order_data += "<u>Ordered by:</u> [ordered_by]<br>"
|
|
order_data += "<u>Submitted at:</u> [time_submitted]<br>"
|
|
if(authorized_by)
|
|
order_data += "<u>Authorized by: </u> [authorized_by]<br>"
|
|
order_data += "<u>Approved at: </u> [time_approved]<br>"
|
|
if(time_shipped)
|
|
order_data += "<u>Shipped at:</u> [time_shipped]<br>"
|
|
if(received_by)
|
|
order_data += "<u>Received by:</u [received_by]><br>"
|
|
order_data += "<u>Delivered at:</u> [time_delivered]<br>"
|
|
order_data += "<hr>"
|
|
order_data += "<u>Order ID:</u> [order_id]<br>"
|
|
order_data += "<u>Tracking Code:</u> [get_tracking_code()]<br>"
|
|
order_data += "<u>Order Status:</u> [get_order_status(1)]<br>"
|
|
order_data += "<u>Payment Status:</u> [get_payment_status(1)]<br>"
|
|
if(paid_by)
|
|
order_data += "<u>Paid at:</u> [time_paid]<br>"
|
|
order_data += "<hr>"
|
|
if(required_access.len)
|
|
order_data += "<u>Required Access:</u><br>"
|
|
order_data += "<ul>"
|
|
for(var/A in required_access)
|
|
order_data += "<li>[get_access_desc(A)]</li>"
|
|
order_data += "</ul>"
|
|
order_data += "<hr>"
|
|
order_data += "<u>Order Fees:</u><br>"
|
|
order_data += "<ul>"
|
|
for(var/item in get_item_list())
|
|
order_data += "<li>[item["name"]]: [item["price"]]</li>"
|
|
order_data += "<li>Crate Fee: [SScargo.get_cratefee()]</li>"
|
|
order_data += "<li>Handling Fee: [SScargo.get_handlingfee()]</li>"
|
|
order_data += "<li>Shuttle Fee: [get_shipment_cost()]</li>"
|
|
order_data += "</ul>"
|
|
|
|
return order_data.Join("")
|
|
|
|
// Returns a Delivery Order for the Crate
|
|
/datum/cargo_order/proc/get_report_delivery_order()
|
|
var/list/order_data = list()
|
|
order_data += "<h4>Delivery Order #[order_id]</h4>"
|
|
order_data += "<hr>"
|
|
order_data += "<u>Submitted at:</u> [time_submitted]<br>"
|
|
order_data += "<u>Shipped at:</u> [time_shipped]<br>"
|
|
order_data += "<u>Contents:</u><br>"
|
|
order_data += "<ul>"
|
|
for(var/object in get_object_list())
|
|
order_data += "<li>[object]</li>"
|
|
order_data += "</ul>"
|
|
|
|
return order_data.Join("")
|
|
|
|
//Marks a order as submitted
|
|
/datum/cargo_order/proc/set_submitted(var/user_name, var/user_id, var/order_reason)
|
|
if(user_id <= 0)
|
|
user_id = null
|
|
|
|
ordered_by = user_name
|
|
ordered_by_id = user_id
|
|
reason = order_reason
|
|
status = "submitted"
|
|
time_submitted = worldtime2text()
|
|
order_id = SScargo.get_next_order_id()
|
|
SScargo.all_orders.Add(src)
|
|
return 1
|
|
|
|
//Marks a order as approved - Returns a status message
|
|
/datum/cargo_order/proc/set_approved(var/user_name, var/user_id)
|
|
if(user_id <= 0)
|
|
user_id = null
|
|
if(status == "submitted")
|
|
status = "approved"
|
|
time_approved = worldtime2text()
|
|
authorized_by = user_name
|
|
authorized_by_id = user_id
|
|
return "The order has been approved"
|
|
else
|
|
return "The order could not be approved - Invalid Status"
|
|
|
|
//Marks a order as rejected - Returns a status message
|
|
/datum/cargo_order/proc/set_rejected()
|
|
if(status == "submitted")
|
|
status = "rejected"
|
|
time_approved = worldtime2text()
|
|
return "The order has been rejected"
|
|
else
|
|
return "The order could not be rejected - Invalid Status"
|
|
|
|
//Marks a order as shipped
|
|
/datum/cargo_order/proc/set_shipped()
|
|
status = "shipped"
|
|
time_shipped = worldtime2text()
|
|
|
|
//Marks a order as delivered - Returns a status message
|
|
/datum/cargo_order/proc/set_delivered(var/user_name, var/user_id, var/paid=0)
|
|
if(user_id <= 0)
|
|
user_id = null
|
|
if(status == "shipped")
|
|
status = "delivered"
|
|
time_delivered = worldtime2text()
|
|
received_by = user_name
|
|
received_by_id = user_id
|
|
if(paid)
|
|
set_paid(user_name, user_id)
|
|
return "The order has been delivered"
|
|
else
|
|
return "The order could not be delivered - Invalid Status"
|
|
|
|
//Mark a order as paid
|
|
/datum/cargo_order/proc/set_paid(var/user_name, var/user_id)
|
|
if(user_id <= 0)
|
|
user_id = null
|
|
time_paid = worldtime2text()
|
|
paid_by = user_name
|
|
paid_by_id = user_id
|
|
return "The order has been paid for"
|
|
|
|
/// A cargo order item. Part of a category. Specifies the item, the supplier and the price of the item
|
|
/datum/cargo_order_item
|
|
var/singleton/cargo_item/ci //Item that has been ordered
|
|
var/price //Price of the item with the given supplier
|
|
var/item_id //Item id in the order
|
|
//TODO-CARGO: Maybe add the option to set a fake item for traitors here -> So that cargo cant see what they are really ordering
|
|
|
|
//Calculate Price
|
|
/datum/cargo_order_item/proc/calculate_price()
|
|
price = ci.adjusted_price
|
|
|
|
// Gets a list of the cargo order item - to be json encoded
|
|
/datum/cargo_order_item/proc/get_list()
|
|
var/list/data = list()
|
|
data["name"] = ci.name
|
|
data["supplier_data"] = ci.supplier_data
|
|
data["amount"] = ci.amount
|
|
data["price"] = price
|
|
data["item_id"] = item_id
|
|
return data
|
|
|
|
/datum/cargo_order_item/Destroy()
|
|
ci = null
|
|
return ..()
|
|
|
|
|
|
/*
|
|
A shipment sent to the station. Contains multiple orders
|
|
*/
|
|
/datum/cargo_shipment
|
|
var/list/orders = list() //List of orders in that shipment
|
|
var/shipment_num //Number of the shipment
|
|
var/shipment_cost_sell = 0 //The amount of money cargo got for the shipment
|
|
var/shipment_cost_purchase = 0 //The amount of money cargo paid for the shipment
|
|
var/shipment_invoice = null//The invoice for the shipment (detailing the expenses ,credits received and charges)
|
|
var/shuttle_fee //The shuttle fee at the time of calling it
|
|
var/shuttle_time //The time the shuttle took to get to the station
|
|
var/shuttle_called_by //The person that called the shuttle
|
|
var/shuttle_recalled_by //The person that recalled the shuttle
|
|
var/completed = 0
|
|
var/message = null //Message from central
|
|
|
|
/datum/cargo_shipment/proc/get_list(var/shipment_completion = 1)
|
|
if(shipment_completion != completed)
|
|
return null
|
|
else
|
|
var/list/data = list()
|
|
data["shipment_num"] = shipment_num
|
|
data["shipment_cost_sell"] = shipment_cost_sell
|
|
data["shipment_cost_purchase"] = shipment_cost_purchase
|
|
data["shipment_invoice"] = shipment_invoice
|
|
data["shuttle_fee"] = shuttle_fee
|
|
data["shuttle_time"] = shuttle_time
|
|
data["shuttle_called_by"] = shuttle_called_by
|
|
data["shuttle_recalled_by"] = shuttle_recalled_by
|
|
data["invoice"] = get_invoice()
|
|
return data
|
|
|
|
// Generates the invoice at the time of shipping
|
|
/datum/cargo_shipment/proc/generate_invoice()
|
|
var/list/invoice_data = list()
|
|
invoice_data += "<h1>Shipping Invoice</h1>"
|
|
|
|
invoice_data += "<p>Shipment Data</p>"
|
|
invoice_data += "<table>"
|
|
invoice_data += "<tr>"
|
|
invoice_data += "<td>Shipment Number:</td>"
|
|
invoice_data += "<td>[shipment_num]</td>"
|
|
invoice_data += "</tr>"
|
|
invoice_data += "<tr>"
|
|
invoice_data += "<td>Shipment Income:</td>"
|
|
invoice_data += "<td>[shipment_cost_sell]</td>"
|
|
invoice_data += "</tr>"
|
|
invoice_data += "<tr>"
|
|
invoice_data += "<td>Shipment Expense:</td>"
|
|
invoice_data += "<td>[shipment_cost_purchase]</td>"
|
|
invoice_data += "</tr>"
|
|
invoice_data += "</table>"
|
|
|
|
invoice_data += "<p>Shuttle Data</p>"
|
|
invoice_data += "<table>"
|
|
invoice_data += "<tr>"
|
|
invoice_data += "<td>Shuttle Fee::</td>"
|
|
invoice_data += "<td>[shuttle_fee]</td>"
|
|
invoice_data += "</tr>"
|
|
invoice_data += "<tr>"
|
|
invoice_data += "<td>Shuttle Time:</td>"
|
|
invoice_data += "<td>[shuttle_time]</td>"
|
|
invoice_data += "</tr>"
|
|
invoice_data += "<tr>"
|
|
invoice_data += "<td>Shuttle Called By:</td>"
|
|
invoice_data += "<td>[shuttle_called_by]</td>"
|
|
invoice_data += "</tr>"
|
|
invoice_data += "<tr>"
|
|
invoice_data += "<td>Shuttle Recalled By:</td>"
|
|
invoice_data += "<td>[shuttle_recalled_by]</td>"
|
|
invoice_data += "</tr>"
|
|
invoice_data += "</table>"
|
|
|
|
invoice_data += "<p>Central Command Message:</p>"
|
|
invoice_data += "<pre>[nl2br(message)]</pre>"
|
|
|
|
shipment_invoice = invoice_data.Join("")
|
|
completed = 1
|
|
return shipment_invoice
|
|
|
|
// Returns the invoice. Generates it if it does not exist
|
|
/datum/cargo_shipment/proc/get_invoice()
|
|
if(!shipment_invoice)
|
|
if(completed == 1)
|
|
generate_invoice()
|
|
else
|
|
return "Invoice Unavailable. Shipment not completed."
|
|
return shipment_invoice
|