mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-21 09:35:49 +02:00
Show part lots on part's info page.
This commit is contained in:
parent
c2b43f2cfa
commit
7517d83f55
7 changed files with 312 additions and 44 deletions
|
@ -183,15 +183,6 @@ class Part extends AttachmentContainingDBElement
|
||||||
*/
|
*/
|
||||||
protected $partLots;
|
protected $partLots;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var int
|
|
||||||
* @ORM\Column(type="integer")
|
|
||||||
* @Assert\GreaterThanOrEqual(0)
|
|
||||||
*
|
|
||||||
* @ColumnSecurity(prefix="mininstock", type="integer")
|
|
||||||
*/
|
|
||||||
protected $mininstock = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var float
|
* @var float
|
||||||
* @ORM\Column(type="float")
|
* @ORM\Column(type="float")
|
||||||
|
@ -199,7 +190,7 @@ class Part extends AttachmentContainingDBElement
|
||||||
*
|
*
|
||||||
* @ColumnSecurity(prefix="mininstock", type="integer")
|
* @ColumnSecurity(prefix="mininstock", type="integer")
|
||||||
*/
|
*/
|
||||||
protected $minamount;
|
protected $minamount = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
|
@ -306,9 +297,9 @@ class Part extends AttachmentContainingDBElement
|
||||||
*
|
*
|
||||||
* @return int count of parts which must be in stock at least
|
* @return int count of parts which must be in stock at least
|
||||||
*/
|
*/
|
||||||
public function getMinInstock(): int
|
public function getMinAmount(): float
|
||||||
{
|
{
|
||||||
return $this->mininstock;
|
return $this->minamount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -687,6 +678,45 @@ class Part extends AttachmentContainingDBElement
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this part uses the float amount .
|
||||||
|
* This setting is based on the part unit (see MeasurementUnit->isInteger()).
|
||||||
|
* @return bool True if the float amount field should be used. False if the integer instock field should be used.
|
||||||
|
*/
|
||||||
|
public function useFloatAmount(): bool
|
||||||
|
{
|
||||||
|
if ($this->partUnit instanceof MeasurementUnit) {
|
||||||
|
return $this->partUnit->isInteger();
|
||||||
|
}
|
||||||
|
|
||||||
|
//When no part unit is set, treat it as part count, and so use the integer value.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the summed amount of this part (over all part lots)
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public function getAmountSum() : float
|
||||||
|
{
|
||||||
|
//TODO: Find a method to do this natively in SQL, the current method could be a bit slow
|
||||||
|
$sum = 0;
|
||||||
|
foreach($this->getPartLots() as $lot) {
|
||||||
|
//Dont use the instock value, if it is unkown
|
||||||
|
if ($lot->isInstockUnknown()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sum += $lot->getAmount();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$this->useFloatAmount()) {
|
||||||
|
return $sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
return round($sum);
|
||||||
|
}
|
||||||
|
|
||||||
/********************************************************************************
|
/********************************************************************************
|
||||||
*
|
*
|
||||||
* Setters
|
* Setters
|
||||||
|
@ -708,17 +738,18 @@ class Part extends AttachmentContainingDBElement
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the count of parts which should be in stock at least.
|
* Set the minimum amount of parts that have to be instock.
|
||||||
|
* See getPartUnit() for the associated unit.
|
||||||
*
|
*
|
||||||
* @param int $new_mininstock the new count of parts which should be in stock at least
|
* @param int $new_mininstock the new count of parts which should be in stock at least
|
||||||
*
|
*
|
||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
public function setMinInstock(int $new_mininstock): self
|
public function setMinAmount(float $new_mininstock): self
|
||||||
{
|
{
|
||||||
//Assert::natural($new_mininstock, 'The new minimum instock value must be positive! Got %s.');
|
//Assert::natural($new_mininstock, 'The new minimum instock value must be positive! Got %s.');
|
||||||
|
|
||||||
$this->mininstock = $new_mininstock;
|
$this->minamount = $new_minamount;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ class PartLot extends DBElement
|
||||||
protected $comment;
|
protected $comment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \DateTime Set a time until when the lot must be used.
|
* @var ?\DateTime Set a time until when the lot must be used.
|
||||||
* Set to null, if the lot can be used indefinitley.
|
* Set to null, if the lot can be used indefinitley.
|
||||||
* @ORM\Column(type="datetimetz", name="expiration_date", nullable=true)
|
* @ORM\Column(type="datetimetz", name="expiration_date", nullable=true)
|
||||||
*/
|
*/
|
||||||
|
@ -92,16 +92,11 @@ class PartLot extends DBElement
|
||||||
*/
|
*/
|
||||||
protected $instock_unknown;
|
protected $instock_unknown;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var int For integer sizes the instock is saved here.
|
|
||||||
* @ORM\Column(type="integer", nullable=true)
|
|
||||||
* @Assert\Positive()
|
|
||||||
*/
|
|
||||||
protected $instock;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var float For continuos sizes (length, volume, etc.) the instock is saved here.
|
* @var float For continuos sizes (length, volume, etc.) the instock is saved here.
|
||||||
* @ORM\Column(type="float", nullable=true)
|
* @ORM\Column(type="float")
|
||||||
|
* @Assert\Positive()
|
||||||
*/
|
*/
|
||||||
protected $amount;
|
protected $amount;
|
||||||
|
|
||||||
|
@ -122,4 +117,179 @@ class PartLot extends DBElement
|
||||||
{
|
{
|
||||||
return 'PL' . $this->getID();
|
return 'PL' . $this->getID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current part lot is expired.
|
||||||
|
* This is the case, if the expiration date is greater the the current date.
|
||||||
|
* @return bool|null True, if the part lot is expired. Returns null, if no expiration date was set.
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function isExpired(): ?bool
|
||||||
|
{
|
||||||
|
if ($this->expiration_date == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if the expiration date is bigger then current time
|
||||||
|
return $this->expiration_date < new \DateTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the description of the part lot. Similar to a "name" of the part lot.
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return $this->description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the description of the part lot.
|
||||||
|
* @param string $description
|
||||||
|
* @return PartLot
|
||||||
|
*/
|
||||||
|
public function setDescription(string $description): PartLot
|
||||||
|
{
|
||||||
|
$this->description = $description;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the comment for this part lot.
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getComment(): string
|
||||||
|
{
|
||||||
|
return $this->comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the comment for this part lot.
|
||||||
|
* @param string $comment
|
||||||
|
* @return PartLot
|
||||||
|
*/
|
||||||
|
public function setComment(string $comment): PartLot
|
||||||
|
{
|
||||||
|
$this->comment = $comment;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the expiration date for the part lot. Returns null, if no expiration date was set.
|
||||||
|
* @return \DateTime|null
|
||||||
|
*/
|
||||||
|
public function getExpirationDate(): ?\DateTime
|
||||||
|
{
|
||||||
|
return $this->expiration_date;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the expiration date for the part lot. Set to null, if the part lot does not expires.
|
||||||
|
* @param \DateTime $expiration_date
|
||||||
|
* @return PartLot
|
||||||
|
*/
|
||||||
|
public function setExpirationDate(?\DateTime $expiration_date): PartLot
|
||||||
|
{
|
||||||
|
$this->expiration_date = $expiration_date;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the storage locatiion, where this part lot is stored.
|
||||||
|
* @return Storelocation The store location where this part is stored
|
||||||
|
*/
|
||||||
|
public function getStorageLocation(): Storelocation
|
||||||
|
{
|
||||||
|
return $this->storage_location;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the storage location, where this part lot is stored
|
||||||
|
* @param Storelocation $storage_location
|
||||||
|
* @return PartLot
|
||||||
|
*/
|
||||||
|
public function setStorageLocation(Storelocation $storage_location): PartLot
|
||||||
|
{
|
||||||
|
$this->storage_location = $storage_location;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the part that is stored in this part lot.
|
||||||
|
* @return Part
|
||||||
|
*/
|
||||||
|
public function getPart(): Part
|
||||||
|
{
|
||||||
|
return $this->part;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the part that is stored in this part lot.
|
||||||
|
* @param Part $part
|
||||||
|
* @return PartLot
|
||||||
|
*/
|
||||||
|
public function setPart(Part $part): PartLot
|
||||||
|
{
|
||||||
|
$this->part = $part;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the instock value in the part lot is unknown.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isInstockUnknown(): bool
|
||||||
|
{
|
||||||
|
return $this->instock_unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the unknown instock status of this part lot.
|
||||||
|
* @param bool $instock_unknown
|
||||||
|
* @return PartLot
|
||||||
|
*/
|
||||||
|
public function setInstockUnknown(bool $instock_unknown): PartLot
|
||||||
|
{
|
||||||
|
$this->instock_unknown = $instock_unknown;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public function getAmount(): float
|
||||||
|
{
|
||||||
|
if (!$this->part->useFloatAmount()) {
|
||||||
|
return round($this->amount);
|
||||||
|
}
|
||||||
|
return (float) $this->amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setAmount(float $new_amount): PartLot
|
||||||
|
{
|
||||||
|
$this->amount = $new_amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isNeedsRefill(): bool
|
||||||
|
{
|
||||||
|
return $this->needs_refill;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $needs_refill
|
||||||
|
* @return PartLot
|
||||||
|
*/
|
||||||
|
public function setNeedsRefill(bool $needs_refill): PartLot
|
||||||
|
{
|
||||||
|
$this->needs_refill = $needs_refill;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -62,6 +62,8 @@ declare(strict_types=1);
|
||||||
namespace App\Entity\Parts;
|
namespace App\Entity\Parts;
|
||||||
|
|
||||||
use App\Entity\Base\PartsContainingDBElement;
|
use App\Entity\Base\PartsContainingDBElement;
|
||||||
|
use App\Entity\Base\StructuralDBElement;
|
||||||
|
use App\Form\Type\StructuralEntityType;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,7 +72,7 @@ use Doctrine\ORM\Mapping as ORM;
|
||||||
* @ORM\Entity(repositoryClass="App\Repository\StructuralDBElementRepository")
|
* @ORM\Entity(repositoryClass="App\Repository\StructuralDBElementRepository")
|
||||||
* @ORM\Table("`storelocations`")
|
* @ORM\Table("`storelocations`")
|
||||||
*/
|
*/
|
||||||
class Storelocation extends PartsContainingDBElement
|
class Storelocation extends StructuralDBElement
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @ORM\OneToMany(targetEntity="Storelocation", mappedBy="parent")
|
* @ORM\OneToMany(targetEntity="Storelocation", mappedBy="parent")
|
||||||
|
@ -83,11 +85,6 @@ class Storelocation extends PartsContainingDBElement
|
||||||
*/
|
*/
|
||||||
protected $parent;
|
protected $parent;
|
||||||
|
|
||||||
/**
|
|
||||||
* @ORM\OneToMany(targetEntity="Part", mappedBy="storelocation")
|
|
||||||
*/
|
|
||||||
protected $parts;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var bool
|
* @var bool
|
||||||
* @ORM\Column(type="boolean")
|
* @ORM\Column(type="boolean")
|
||||||
|
|
|
@ -23,21 +23,21 @@ final class Version20190812154222 extends AbstractMigration
|
||||||
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
|
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
|
||||||
|
|
||||||
$this->addSql('CREATE TABLE `measurement_units` (id INT AUTO_INCREMENT NOT NULL, unit VARCHAR(255) DEFAULT NULL, is_integer TINYINT(1) NOT NULL, use_si_prefix TINYINT(1) NOT NULL, comment LONGTEXT NOT NULL, parent_id INT DEFAULT NULL, not_selectable TINYINT(1) NOT NULL, name VARCHAR(255) NOT NULL, last_modified DATETIME NOT NULL, datetime_added DATETIME NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB');
|
$this->addSql('CREATE TABLE `measurement_units` (id INT AUTO_INCREMENT NOT NULL, unit VARCHAR(255) DEFAULT NULL, is_integer TINYINT(1) NOT NULL, use_si_prefix TINYINT(1) NOT NULL, comment LONGTEXT NOT NULL, parent_id INT DEFAULT NULL, not_selectable TINYINT(1) NOT NULL, name VARCHAR(255) NOT NULL, last_modified DATETIME NOT NULL, datetime_added DATETIME NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB');
|
||||||
$this->addSql('CREATE TABLE part_lots (id INT AUTO_INCREMENT NOT NULL, id_store_location INT DEFAULT NULL, id_part INT DEFAULT NULL, description LONGTEXT NOT NULL, comment LONGTEXT NOT NULL, expiration_date DATETIME DEFAULT NULL, instock_unknown TINYINT(1) NOT NULL, instock INT DEFAULT NULL, amount DOUBLE PRECISION DEFAULT NULL, needs_refill TINYINT(1) NOT NULL, last_modified DATETIME NOT NULL, datetime_added DATETIME NOT NULL, INDEX IDX_EBC8F9435D8F4B37 (id_store_location), INDEX IDX_EBC8F943C22F6CC4 (id_part), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB');
|
$this->addSql('CREATE TABLE part_lots (id INT AUTO_INCREMENT NOT NULL, id_store_location INT DEFAULT NULL, id_part INT DEFAULT NULL, description LONGTEXT NOT NULL, comment LONGTEXT NOT NULL, expiration_date DATETIME DEFAULT NULL, instock_unknown TINYINT(1) NOT NULL, amount DOUBLE PRECISION NOT NULL, needs_refill TINYINT(1) NOT NULL, last_modified DATETIME NOT NULL, datetime_added DATETIME NOT NULL, INDEX IDX_EBC8F9435D8F4B37 (id_store_location), INDEX IDX_EBC8F943C22F6CC4 (id_part), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB');
|
||||||
$this->addSql('CREATE TABLE currencies (id INT AUTO_INCREMENT NOT NULL, iso_code VARCHAR(255) NOT NULL, exchange_rate NUMERIC(11, 5) DEFAULT NULL, comment LONGTEXT NOT NULL, parent_id INT DEFAULT NULL, not_selectable TINYINT(1) NOT NULL, name VARCHAR(255) NOT NULL, last_modified DATETIME NOT NULL, datetime_added DATETIME NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB');
|
$this->addSql('CREATE TABLE currencies (id INT AUTO_INCREMENT NOT NULL, iso_code VARCHAR(255) NOT NULL, exchange_rate NUMERIC(11, 5) DEFAULT NULL, comment LONGTEXT NOT NULL, parent_id INT DEFAULT NULL, not_selectable TINYINT(1) NOT NULL, name VARCHAR(255) NOT NULL, last_modified DATETIME NOT NULL, datetime_added DATETIME NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB');
|
||||||
$this->addSql('ALTER TABLE part_lots ADD CONSTRAINT FK_EBC8F9435D8F4B37 FOREIGN KEY (id_store_location) REFERENCES `storelocations` (id)');
|
$this->addSql('ALTER TABLE part_lots ADD CONSTRAINT FK_EBC8F9435D8F4B37 FOREIGN KEY (id_store_location) REFERENCES `storelocations` (id)');
|
||||||
$this->addSql('ALTER TABLE part_lots ADD CONSTRAINT FK_EBC8F943C22F6CC4 FOREIGN KEY (id_part) REFERENCES `parts` (id)');
|
$this->addSql('ALTER TABLE part_lots ADD CONSTRAINT FK_EBC8F943C22F6CC4 FOREIGN KEY (id_part) REFERENCES `parts` (id)');
|
||||||
|
|
||||||
/** Migrate the part locations for parts with known instock */
|
/** Migrate the part locations for parts with known instock */
|
||||||
$this->addSql(
|
$this->addSql(
|
||||||
'INSERT INTO part_lots (id_part, id_store_location, instock, instock_unknown, last_modified, datetime_added) ' .
|
'INSERT INTO part_lots (id_part, id_store_location, amount, instock_unknown, last_modified, datetime_added) ' .
|
||||||
'SELECT parts.id, parts.id_storelocation, parts.instock, 0, NOW(), NOW() FROM parts ' .
|
'SELECT parts.id, parts.id_storelocation, parts.instock, 0, NOW(), NOW() FROM parts ' .
|
||||||
'WHERE parts.instock >= 0 AND parts.id_storelocation IS NOT NULL'
|
'WHERE parts.instock >= 0 AND parts.id_storelocation IS NOT NULL'
|
||||||
);
|
);
|
||||||
|
|
||||||
//Migrate part locations for parts with unknown instock
|
//Migrate part locations for parts with unknown instock
|
||||||
$this->addSql(
|
$this->addSql(
|
||||||
'INSERT INTO part_lots (id_part, id_store_location, instock, instock_unknown, last_modified, datetime_added) ' .
|
'INSERT INTO part_lots (id_part, id_store_location, amount, instock_unknown, last_modified, datetime_added) ' .
|
||||||
'SELECT parts.id, parts.id_storelocation, 0, 1, NOW(), NOW() FROM parts ' .
|
'SELECT parts.id, parts.id_storelocation, 0, 1, NOW(), NOW() FROM parts ' .
|
||||||
'WHERE parts.instock = -2 AND parts.id_storelocation IS NOT NULL'
|
'WHERE parts.instock = -2 AND parts.id_storelocation IS NOT NULL'
|
||||||
);
|
);
|
||||||
|
@ -56,7 +56,7 @@ final class Version20190812154222 extends AbstractMigration
|
||||||
$this->addSql('CREATE INDEX IDX_AC28B95CECD792C0 ON suppliers (default_currency_id)');
|
$this->addSql('CREATE INDEX IDX_AC28B95CECD792C0 ON suppliers (default_currency_id)');
|
||||||
$this->addSql('ALTER TABLE parts DROP FOREIGN KEY parts_id_storelocation_fk');
|
$this->addSql('ALTER TABLE parts DROP FOREIGN KEY parts_id_storelocation_fk');
|
||||||
$this->addSql('DROP INDEX IDX_6940A7FE8DF69834 ON parts');
|
$this->addSql('DROP INDEX IDX_6940A7FE8DF69834 ON parts');
|
||||||
$this->addSql('ALTER TABLE parts ADD id_part_unit INT DEFAULT NULL, ADD minamount DOUBLE PRECISION NOT NULL, ADD manufacturer_product_number VARCHAR(255) NOT NULL, ADD needs_review TINYINT(1) NOT NULL, ADD tags LONGTEXT NOT NULL, ADD mass DOUBLE PRECISION DEFAULT NULL, DROP id_storelocation, DROP instock, CHANGE id_category id_category INT DEFAULT NULL, CHANGE id_footprint id_footprint INT DEFAULT NULL, CHANGE order_orderdetails_id order_orderdetails_id INT DEFAULT NULL, CHANGE id_manufacturer id_manufacturer INT DEFAULT NULL, CHANGE id_master_picture_attachement id_master_picture_attachement INT DEFAULT NULL, CHANGE datetime_added datetime_added DATETIME NOT NULL, CHANGE last_modified last_modified DATETIME NOT NULL');
|
$this->addSql('ALTER TABLE parts ADD id_part_unit INT DEFAULT NULL, CHANGE mininstock minamount DOUBLE PRECISION NOT NULL, ADD manufacturer_product_number VARCHAR(255) NOT NULL, ADD needs_review TINYINT(1) NOT NULL, ADD tags LONGTEXT NOT NULL, ADD mass DOUBLE PRECISION DEFAULT NULL, DROP id_storelocation, DROP instock, CHANGE id_category id_category INT DEFAULT NULL, CHANGE id_footprint id_footprint INT DEFAULT NULL, CHANGE order_orderdetails_id order_orderdetails_id INT DEFAULT NULL, CHANGE id_manufacturer id_manufacturer INT DEFAULT NULL, CHANGE id_master_picture_attachement id_master_picture_attachement INT DEFAULT NULL, CHANGE datetime_added datetime_added DATETIME NOT NULL, CHANGE last_modified last_modified DATETIME NOT NULL');
|
||||||
$this->addSql('ALTER TABLE parts ADD CONSTRAINT FK_6940A7FE2626CEF9 FOREIGN KEY (id_part_unit) REFERENCES `measurement_units` (id)');
|
$this->addSql('ALTER TABLE parts ADD CONSTRAINT FK_6940A7FE2626CEF9 FOREIGN KEY (id_part_unit) REFERENCES `measurement_units` (id)');
|
||||||
$this->addSql('CREATE INDEX IDX_6940A7FE2626CEF9 ON parts (id_part_unit)');
|
$this->addSql('CREATE INDEX IDX_6940A7FE2626CEF9 ON parts (id_part_unit)');
|
||||||
$this->addSql('ALTER TABLE users CHANGE group_id group_id INT DEFAULT NULL, CHANGE password password VARCHAR(255) DEFAULT NULL, CHANGE first_name first_name VARCHAR(255) DEFAULT NULL, CHANGE last_name last_name VARCHAR(255) DEFAULT NULL, CHANGE department department VARCHAR(255) DEFAULT NULL, CHANGE email email VARCHAR(255) DEFAULT NULL, CHANGE config_language config_language VARCHAR(255) DEFAULT NULL, CHANGE config_timezone config_timezone VARCHAR(255) DEFAULT NULL, CHANGE config_theme config_theme VARCHAR(255) DEFAULT NULL, CHANGE datetime_added datetime_added DATETIME NOT NULL, CHANGE last_modified last_modified DATETIME NOT NULL');
|
$this->addSql('ALTER TABLE users CHANGE group_id group_id INT DEFAULT NULL, CHANGE password password VARCHAR(255) DEFAULT NULL, CHANGE first_name first_name VARCHAR(255) DEFAULT NULL, CHANGE last_name last_name VARCHAR(255) DEFAULT NULL, CHANGE department department VARCHAR(255) DEFAULT NULL, CHANGE email email VARCHAR(255) DEFAULT NULL, CHANGE config_language config_language VARCHAR(255) DEFAULT NULL, CHANGE config_timezone config_timezone VARCHAR(255) DEFAULT NULL, CHANGE config_theme config_theme VARCHAR(255) DEFAULT NULL, CHANGE datetime_added datetime_added DATETIME NOT NULL, CHANGE last_modified last_modified DATETIME NOT NULL');
|
||||||
|
|
|
@ -24,10 +24,10 @@
|
||||||
<span class="text-muted">{{ part.storelocation.fullPath ?? "-"}}</span>
|
<span class="text-muted">{{ part.storelocation.fullPath ?? "-"}}</span>
|
||||||
</h6> #}
|
</h6> #}
|
||||||
<h6><i class="fas fa-shapes fa-fw"></i>
|
<h6><i class="fas fa-shapes fa-fw"></i>
|
||||||
<span class="text-muted"> {#
|
<span class="text-muted">
|
||||||
<span title="{% trans %}instock.label{% endtrans %}">{{ part.instock }}</span> #}
|
<span title="{% trans %}instock.label{% endtrans %}">{{ part.amountSum }}</span>
|
||||||
/
|
/
|
||||||
<span title="{% trans %}mininstock.label{% endtrans %}">{{ part.mininstock }}</span>
|
<span title="{% trans %}mininstock.label{% endtrans %}">{{ part.minAmount }}</span>
|
||||||
</span>
|
</span>
|
||||||
</h6>
|
</h6>
|
||||||
<h6 class="" title="{% trans %}footprint.label{% endtrans %}">
|
<h6 class="" title="{% trans %}footprint.label{% endtrans %}">
|
||||||
|
|
55
templates/Parts/info/_part_lots.html.twig
Normal file
55
templates/Parts/info/_part_lots.html.twig
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
<table class="table table-striped table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{% trans %}part_lots.description{% endtrans %}</th>
|
||||||
|
<th>{% trans %}part_lots.storage_location{% endtrans %}</th>
|
||||||
|
<th>{% trans %}part_lots.amount{% endtrans %}</th>
|
||||||
|
<th></th> {# Tags row #}
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{% for lot in part.partLots %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ lot.description }}</td>
|
||||||
|
<td>
|
||||||
|
{{ lot.storageLocation.fullPath }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% if lot.instockUnknown %}
|
||||||
|
<span class="badge badge-pill badge-warning">
|
||||||
|
<i class="fas fa-question-circle fa-fw"></i> {% trans %}part_lots.instock_unknown{% endtrans %}
|
||||||
|
</span>
|
||||||
|
{% else %}
|
||||||
|
{{ lot.amount }}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<h6>
|
||||||
|
{% if lot.expirationDate %}
|
||||||
|
<span class="badge badge-info" title="{% trans %}part_lots.expiration_date{% endtrans %}">
|
||||||
|
<i class="fas fa-calendar-alt fa-fw"></i> {{ lot.expirationDate | localizeddate }}
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
{% if lot.expired %}
|
||||||
|
<br>
|
||||||
|
<span class="badge badge-warning">
|
||||||
|
<i class="fas fa-exclamation-circle fa-fw"></i>
|
||||||
|
{% trans %}part_lots.is_expired{% endtrans %}
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
{% if lot.needsRefill %}
|
||||||
|
<br>
|
||||||
|
<span class="badge badge-warning">
|
||||||
|
<i class="fas fa-dolly fa-fw"></i>
|
||||||
|
{% trans %}part_lots.need_refill{% endtrans %}
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
</h6>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
|
||||||
|
</table>
|
|
@ -28,9 +28,19 @@
|
||||||
<div class="">
|
<div class="">
|
||||||
<div class="">
|
<div class="">
|
||||||
<ul class="nav nav-tabs" id="partTab" role="tablist">
|
<ul class="nav nav-tabs" id="partTab" role="tablist">
|
||||||
|
{% if part.partLots %}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active" id="part_lots-tab" data-toggle="tab"
|
||||||
|
href="#part_lots" role="tab">
|
||||||
|
<i class="fas fa-box fa-fw"></i>
|
||||||
|
{% trans %}part.part_lots.label{% endtrans %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if part.comment is not empty %}
|
{% if part.comment is not empty %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link active" id="comment-tab" data-toggle="tab"
|
<a class="nav-link" id="comment-tab" data-toggle="tab"
|
||||||
href="#comment" role="tab">
|
href="#comment" role="tab">
|
||||||
<i class="fas fa-comment-alt fa-fw"></i>
|
<i class="fas fa-comment-alt fa-fw"></i>
|
||||||
{% trans %}comment.label{% endtrans %}
|
{% trans %}comment.label{% endtrans %}
|
||||||
|
@ -38,7 +48,7 @@
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link {% if part.comment is empty%} active{% endif %}" id="attachment-tab" data-toggle="tab"
|
<a class="nav-link" id="attachment-tab" data-toggle="tab"
|
||||||
href="#attachments" role="tab">
|
href="#attachments" role="tab">
|
||||||
<i class="fas fa-paperclip fa-fw"></i>
|
<i class="fas fa-paperclip fa-fw"></i>
|
||||||
{% trans %}attachment.labelp{% endtrans %}
|
{% trans %}attachment.labelp{% endtrans %}
|
||||||
|
@ -78,25 +88,30 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="tab-pane fade {% if part.comment is empty %} show active{% endif %}" id="attachments" role="tabpanel" aria-labelledby="profile-tab">
|
|
||||||
|
<div class="tab-pane fade show active" id="part_lots" role="tabpanel" aria-labelledby="part_lots-tab">
|
||||||
|
{% include "Parts/info/_part_lots.html.twig" %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tab-pane fade" id="attachments" role="tabpanel" aria-labelledby="attachment-tab">
|
||||||
{% include "Parts/info/_attachments_info.html.twig" %}
|
{% include "Parts/info/_attachments_info.html.twig" %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tab-pane fade" id="suppliers" role="tabpanel" aria-labelledby="profile-tab">
|
<div class="tab-pane fade" id="suppliers" role="tabpanel" aria-labelledby="supplier-tab">
|
||||||
{% include "Parts/info/_order_infos.html.twig" %}
|
{% include "Parts/info/_order_infos.html.twig" %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tab-pane fade" id="history" role="tabpanel" aria-labelledby="profile-tab">
|
<div class="tab-pane fade" id="history" role="tabpanel" aria-labelledby="history-tab">
|
||||||
TODO
|
TODO
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tab-pane fade" id="tools" role="tabpanel" aria-labelledby="contact-tab">
|
<div class="tab-pane fade" id="tools" role="tabpanel" aria-labelledby="tools-tab">
|
||||||
|
|
||||||
{% include "Parts/info/_tools.html.twig" %}
|
{% include "Parts/info/_tools.html.twig" %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tab-pane fade" id="extended_info" role="tabpanel" aria-labelledby="contact-tab">
|
<div class="tab-pane fade" id="extended_info" role="tabpanel" aria-labelledby="extended_info-tab">
|
||||||
|
|
||||||
{% include "Parts/info/_extended_infos.html.twig" %}
|
{% include "Parts/info/_extended_infos.html.twig" %}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue