6.5.2. Invoice Items Model

Now we are going to create a model for items in an invoice:

  1. namespace App;
  2. use Firebird\Eloquent\Model;
  3. use Illuminate\Database\Eloquent\Builder;
  4. class InvoiceLine extends Model {
  5. /**
  6. * Table associated with the model
  7. *
  8. * @var string
  9. */
  10. protected $table = 'INVOICE_LINE';
  11. /**
  12. * Primary key of the model
  13. *
  14. * @var string
  15. */
  16. protected $primaryKey = 'INVOICE_LINE_ID';
  17. /**
  18. * Our model does not have a timestamp
  19. *
  20. * @var bool
  21. */
  22. public $timestamps = false;
  23. /**
  24. * The name of the sequence for generating the primary key
  25. *
  26. * @var string
  27. */
  28. protected $sequence = 'GEN_INVOICE_LINE_ID';
  29. /**
  30. * Array of names of computed fields
  31. *
  32. * @var array
  33. */
  34. protected $appends = ['SUM_PRICE'];
  35. /**
  36. * Product
  37. *
  38. * @return \App\Product
  39. */
  40. public function product() {
  41. return $this->belongsTo('App\Product', 'PRODUCT_ID');
  42. }
  43. /**
  44. * Amount by item
  45. *
  46. * @return double
  47. */
  48. public function getSumPriceAttribute() {
  49. return $this->SALE_PRICE * $this->QUANTITY;
  50. }
  51. /**
  52. * Adding a model object to the database
  53. * Override this method, because in this case, we work with a stored procedure
  54. *
  55. * @param \Illuminate\Database\Eloquent\Builder $query
  56. * @param array $options
  57. * @return bool
  58. */
  59. protected function performInsert(Builder $query, array $options = []) {
  60. if ($this->fireModelEvent('creating') === false) {
  61. return false;
  62. }
  63. $connection = $this->getConnection();
  64. $attributes = $this->attributes;
  65. $connection->executeProcedure('SP_ADD_INVOICE_LINE', [
  66. $attributes['INVOICE_ID'],
  67. $attributes['PRODUCT_ID'],
  68. $attributes['QUANTITY']
  69. ]);
  70. // We will go ahead and set the exists property to true,
  71. // so that it is set when the created event is fired, just in case
  72. // the developer tries to update it during the event. This will allow
  73. // them to do so and run an update here.
  74. $this->exists = true;
  75. $this->wasRecentlyCreated = true;
  76. $this->fireModelEvent('created', false);
  77. return true;
  78. }
  79. /**
  80. * Saving changes to the current model instance in the database
  81. * Override this method, because in this case, we work with a stored procedure
  82. *
  83. * @param \Illuminate\Database\Eloquent\Builder $query
  84. * @param array $options
  85. * @return bool
  86. */
  87. protected function performUpdate(Builder $query, array $options = []) {
  88. $dirty = $this->getDirty();
  89. if (count($dirty) > 0) {
  90. // If the updating event returns false, we will cancel
  91. // the update operation so developers can hook Validation systems
  92. // into their models and cancel this operation if the model does
  93. // not pass validation. Otherwise, we update.
  94. if ($this->fireModelEvent('updating') === false) {
  95. return false;
  96. }
  97. $connection = $this->getConnection();
  98. $attributes = $this->attributes;
  99. $connection->executeProcedure('SP_EDIT_INVOICE_LINE', [
  100. $attributes['INVOICE_LINE_ID'],
  101. $attributes['QUANTITY']
  102. ]);
  103. $this->fireModelEvent('updated', false);
  104. }
  105. }
  106. /**
  107. * Deleting the current model instance from the database
  108. * Override this method, because in this case, we work with a stored procedure
  109. *
  110. * @return void
  111. */
  112. protected function performDeleteOnModel() {
  113. $connection = $this->getConnection();
  114. $attributes = $this->attributes;
  115. $connection->executeProcedure('SP_DELETE_INVOICE_LINE',
  116. [$attributes['INVOICE_LINE_ID']]);
  117. }
  118. }

The product function in this model returns the product, actually the App/Product model that was specified as the invoice item. The relation is established through the PRODUCT_ID field by the belongsTo method.

The SumPrice is a calculated field, calculated by the function getSumPriceAttribute. For a calculated field to be available in the model, its name must be specified in the $appends array that stores the names of calculated fields.

Operations

In this model, we redefined the insert, update and delete operations so that they are performed through stored procedures. Along with performing the insert, update and delete operations, these stored procedures recalculate the total in the invoice header. We could have avoided doing that, but then we would have had to modify several models in one transaction. Later, we will examine how to do it that way.