diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index 7c37fc7e..91c273da 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -9,6 +9,7 @@ use App\Ramcar\WarrantyClass; use App\Ramcar\DiscountApply; use App\Ramcar\TradeInType; use App\Ramcar\InvoiceCriteria; +use App\Ramcar\InvoiceStatus; use App\Entity\JobOrder; use App\Entity\BatteryManufacturer; use App\Entity\Customer; @@ -61,8 +62,9 @@ class JobOrderController extends BaseController return $this->render('job-order/form.html.twig', $params); } - public function incomingSubmit(Request $req, ValidatorInterface $validator) + public function incomingSubmit(Request $req, ValidatorInterface $validator, InvoiceCreator $ic) { + error_log(print_r($req->request->all(), true)); $this->denyAccessUnlessGranted('jo_in.list', null, 'No access.'); // initialize error list @@ -109,6 +111,41 @@ class JobOrderController extends BaseController ->setAgentNotes($req->request->get('agent_notes')) ->setDeliveryAddress($req->request->get('delivery_address')); + // instantiate invoice criteria + $criteria = new InvoiceCriteria(); + + $ierror = $this->invoicePromo($em, $criteria, $req->request->get('invoice_promo')); + $invoice_items = $req->request->get('invoice_items'); + + if (!$ierror && !empty($invoice_items)) + $ierror = $this->invoiceBatteries($em, $criteria, $invoice_items); + + if ($ierror) + { + $error_array['invoice'] = $ierror; + } + else + { + // generate the invoice + $iobj = $ic->processCriteria($criteria); + $iobj->setStatus(InvoiceStatus::DRAFT) + ->setCreatedBy($this->getUser()); + + // validate + $ierrors = $validator->validate($iobj); + + // add errors to list + foreach ($ierrors as $error) { + $error_array[$error->getPropertyPath()] = $error->getMessage(); + } + + // add invoice to JO + $obj->setInvoice($iobj); + + // save + $em->persist($iobj); + } + // validate $errors = $validator->validate($obj); @@ -729,7 +766,7 @@ class JobOrderController extends BaseController { $invoice['items'][] = [ 'title' => $item->getTitle(), - 'quantity' => $item->getQuantity(), // TODO: quantities are always 1, hardcoded into InvoiceCreator. no way of accepting quantities on InvoiceCriteria + 'quantity' => number_format($item->getQuantity()), // TODO: quantities are always 1, hardcoded into InvoiceCreator. no way of accepting quantities on InvoiceCriteria 'unit_price' => number_format($item->getPrice(), 2), 'amount' => number_format($item->getPrice() * $item->getQuantity(), 2) // TODO: should this calculation should be a saved value on InvoiceItem instead? ]; diff --git a/src/Entity/Invoice.php b/src/Entity/Invoice.php index e92e9abf..4f018c89 100644 --- a/src/Entity/Invoice.php +++ b/src/Entity/Invoice.php @@ -40,23 +40,23 @@ class Invoice // user that created the invoice /** - * @ORM\ManyToOne(targetEntity="User", inversedBy="invoice") + * @ORM\ManyToOne(targetEntity="User", inversedBy="invoices") * @ORM\JoinColumn(name="user_id", referencedColumnName="id") */ protected $created_by; // the job order the invoice was created from /** - * @ORM\ManyToOne(targetEntity="JobOrder", inversedBy="invoice") + * @ORM\OneToOne(targetEntity="JobOrder", inversedBy="invoice") * @ORM\JoinColumn(name="job_order_id", referencedColumnName="id") */ protected $job_order; // invoice items /** - * @ORM\OneToMany(targetEntity="InvoiceItem", mappedBy="invoice") + * @ORM\OneToMany(targetEntity="InvoiceItem", mappedBy="invoice", cascade={"persist"}) */ - protected $invoice_items; + protected $items; // total discount (amount, not %) /** @@ -94,10 +94,17 @@ class Invoice */ protected $status; + // promo used by this invoice + /** + * @ORM\ManyToOne(targetEntity="Promo") + * @ORM\JoinColumn(name="promo_id", referencedColumnName="id") + */ + protected $promo; + public function __construct() { $this->date_create = new DateTime(); - $this->invoice_items = new ArrayCollection(); + $this->items = new ArrayCollection(); } public function getID() @@ -156,20 +163,20 @@ class Invoice public function addItem(InvoiceItem $item) { - $this->invoice_items->add($item); + $this->items->add($item); $item->setInvoice($this); return $this; } public function clearItems() { - $this->invoice_items->clear(); + $this->items->clear(); return $this; } public function getItems() { - return $this->invoice_items; + return $this->items; } public function setDiscount($discount) @@ -237,4 +244,15 @@ class Invoice { return $this->status; } + + public function setPromo(Promo $promo) + { + $this->promo = $promo; + return $this; + } + + public function getPromo() + { + return $this->promo; + } } diff --git a/src/Entity/InvoiceItem.php b/src/Entity/InvoiceItem.php index 1ea66765..57758722 100644 --- a/src/Entity/InvoiceItem.php +++ b/src/Entity/InvoiceItem.php @@ -43,6 +43,13 @@ class InvoiceItem */ protected $price; + // battery the item is linked to + /** + * @ORM\ManyToOne(targetEntity="Battery") + * @ORM\JoinColumn(name="battery_id", referencedColumnName="id") + */ + protected $battery; + public function __construct() { $this->title = ''; @@ -97,4 +104,15 @@ class InvoiceItem { return $this->price; } + + public function setBattery(Battery $battery) + { + $this->battery = $battery; + return $this; + } + + public function getBattery() + { + return $this->battery; + } } diff --git a/src/Entity/JobOrder.php b/src/Entity/JobOrder.php index 17c5fbb0..677c1585 100644 --- a/src/Entity/JobOrder.php +++ b/src/Entity/JobOrder.php @@ -162,6 +162,9 @@ class JobOrder protected $delivery_address; // invoice + /** + * @ORM\OneToOne(targetEntity="Invoice", mappedBy="job_order") + */ protected $invoice; public function __construct() @@ -397,4 +400,16 @@ class JobOrder { return $this->delivery_address; } + + public function setInvoice(Invoice $invoice) + { + $this->invoice = $invoice; + $invoice->setJobOrder($this); + return $this; + } + + public function getInvoice() + { + return $this->invoice; + } } diff --git a/src/Entity/User.php b/src/Entity/User.php index 9bfea188..403c8f5f 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -91,6 +91,12 @@ class User implements AdvancedUserInterface, Serializable */ protected $tickets; + // invoices made by this user + /** + * @ORM\OneToMany(targetEntity="Invoice", mappedBy="created_by") + */ + protected $invoices; + public function __construct() { $this->roles = new ArrayCollection(); @@ -290,4 +296,9 @@ class User implements AdvancedUserInterface, Serializable { return $this->tickets; } + + public function getInvoices() + { + return $this->invoices; + } } diff --git a/src/Ramcar/InvoiceStatus.php b/src/Ramcar/InvoiceStatus.php new file mode 100644 index 00000000..596f2a85 --- /dev/null +++ b/src/Ramcar/InvoiceStatus.php @@ -0,0 +1,18 @@ + 'Draft', + 'finalized' => 'Finalized', + 'paid' => 'Paid', + 'cancelled' => 'Cancelled', + ]; +} diff --git a/src/Service/InvoiceCreator.php b/src/Service/InvoiceCreator.php index d101e802..5fb6de91 100644 --- a/src/Service/InvoiceCreator.php +++ b/src/Service/InvoiceCreator.php @@ -85,7 +85,8 @@ class InvoiceCreator $item->setInvoice($invoice) ->setTitle($batt->getModel()->getName() . ' ' . $batt->getSize()->getName()) ->setQuantity($qty) - ->setPrice($sell_price); + ->setPrice($sell_price) + ->setBattery($batt); $invoice->addItem($item); } @@ -149,6 +150,9 @@ class InvoiceCreator $total['discount'] = $discount; $total['total_price'] -= $discount; + + // process + $invoice->setPromo($promo); } public function processCriteria(InvoiceCriteria $criteria) diff --git a/templates/job-order/form.html.twig b/templates/job-order/form.html.twig index 952d8050..493b37eb 100644 --- a/templates/job-order/form.html.twig +++ b/templates/job-order/form.html.twig @@ -265,35 +265,39 @@