mirror of
https://github.com/snipe/snipe-it.git
synced 2024-12-24 21:24:13 -08:00
Merge branch 'develop' into bug/sc-17129/v6-integration-pie-chart-disappears-if-you
This commit is contained in:
commit
3951de1669
|
@ -2360,6 +2360,123 @@
|
|||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Delta5",
|
||||
"name": "Evan Taylor",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1975640?v=4",
|
||||
"profile": "https://github.com/Delta5",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "PetriAsi",
|
||||
"name": "Petri Asikainen",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/8735148?v=4",
|
||||
"profile": "https://github.com/PetriAsi",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "derdeagle",
|
||||
"name": "derdeagle",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/11424540?v=4",
|
||||
"profile": "https://github.com/derdeagle",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "vapier",
|
||||
"name": "Mike Frysinger",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/176950?v=4",
|
||||
"profile": "https://wh0rd.org/",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "AL4AL",
|
||||
"name": "ALPHA",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/22044358?v=4",
|
||||
"profile": "https://github.com/AL4AL",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "FliegenKLATSCH",
|
||||
"name": "FliegenKLATSCH",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1042587?v=4",
|
||||
"profile": "https://www.ifern.de",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "jerm",
|
||||
"name": "Jeremy Price",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/442138?v=4",
|
||||
"profile": "https://github.com/jerm",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Toreg87",
|
||||
"name": "Toreg87",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/84392209?v=4",
|
||||
"profile": "https://github.com/Toreg87",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Computroniks",
|
||||
"name": "Matthew Nickson",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/67638596?v=4",
|
||||
"profile": "https://github.com/Computroniks",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "jethron",
|
||||
"name": "Jethro Nederhof",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1646397?v=4",
|
||||
"profile": "https://jethron.id.au",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "01ste02",
|
||||
"name": "Oskar Stenberg",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/23289826?v=4",
|
||||
"profile": "https://github.com/01ste02",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Robert-Azelis",
|
||||
"name": "Robert-Azelis",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/82208283?v=4",
|
||||
"profile": "https://github.com/Robert-Azelis",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "alwism",
|
||||
"name": "Alexander William Smith",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/60648387?v=4",
|
||||
"profile": "https://github.com/alwism",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
62
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
62
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
|
@ -1,62 +0,0 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
|
||||
---
|
||||
|
||||
#### Please confirm you have done the following before posting your bug report:
|
||||
|
||||
- [ ] I have enabled debug mode
|
||||
- [ ] I have read [checked the Common Issues page](https://snipe-it.readme.io/docs/common-issues)
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Server (please complete the following information):**
|
||||
- Snipe-IT Version
|
||||
- OS: [e.g. Ubuntu, CentOS]
|
||||
- Web Server: [e.g. Apache, IIS]
|
||||
- PHP Version
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. iOS]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Smartphone (please complete the following information):**
|
||||
- Device: [e.g. iPhone6]
|
||||
- OS: [e.g. iOS8.1]
|
||||
- Browser [e.g. stock browser, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Error Messages**
|
||||
- WITH DEBUG TURNED ON, if you're getting an error in your browser, include that error
|
||||
- If a stacktrace is provided in the error, include that too.
|
||||
- Any errors that appear in your browser's error console.
|
||||
- Confirm whether the error is reproducible on the demo: https://snipeitapp.com/demo.
|
||||
- Include any additional information you can find in `storage/logs` and your webserver's logs.
|
||||
- Include the output from `php -m` (this should display what modules you have enabled.)
|
||||
|
||||
**Additional context**
|
||||
- Is this a fresh install or an upgrade?
|
||||
- What OS and web server you're running Snipe-IT on
|
||||
- What method you used to install Snipe-IT (install.sh, manual installation, docker, etc)
|
||||
- Include what you've done so far in the installation, and if you got any error messages along the way.
|
||||
- Indicate whether or not you've manually edited any data directly in the database
|
||||
|
||||
Add any other context about the problem here.
|
||||
|
||||
Please do not post an issue without answering the related questions above. If you have opened a different issue and already answered these questions, answer them again, once for every ticket. It will be next to impossible for us to help you.
|
23
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
23
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
|
@ -1,23 +0,0 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
|
||||
---
|
||||
|
||||
**Server (please complete the following information):**
|
||||
- Snipe-IT Version
|
||||
- OS: [e.g. Ubuntu, CentOS]
|
||||
- Web Server: [e.g. Apache, IIS]
|
||||
- PHP Version
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
129
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
129
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
|
@ -0,0 +1,129 @@
|
|||
name: Bug Report
|
||||
description: Create a report to help us improve
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Debug mode
|
||||
description: Please confirm you have done the following before posting your bug report
|
||||
options:
|
||||
- label: I have enabled debug mode
|
||||
required: true
|
||||
- label: I have read [checked the Common Issues page](https://snipe-it.readme.io/docs/common-issues)
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the bug
|
||||
description: A clear and concise description of what the bug is.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Reproduction steps
|
||||
description: Steps to reproduce the behavior.
|
||||
value: |
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Expected behavior
|
||||
description: A clear and concise description of what you expected to happen.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Screenshots
|
||||
description: 'If applicable, add screenshots to help explain your problem.'
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "### Server"
|
||||
- type: input
|
||||
attributes:
|
||||
label: Snipe-IT Version
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: server_operatingSystem
|
||||
attributes:
|
||||
label: Operating System
|
||||
description: 'e.g. Ubuntu, Windows'
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Web Server
|
||||
description: 'e.g. Apache, IIS'
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: PHP Version
|
||||
validations:
|
||||
required: true
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "### Desktop"
|
||||
- type: input
|
||||
id: desktop_operatingSystem
|
||||
attributes:
|
||||
label: Operating System
|
||||
description: 'e.g. Ubuntu, Windows'
|
||||
- type: input
|
||||
id: desktop_browser
|
||||
attributes:
|
||||
label: Browser
|
||||
description: 'e.g. Google Chrome, Safari'
|
||||
- type: input
|
||||
id: desktop_version
|
||||
attributes:
|
||||
label: Version
|
||||
description: 'e.g. 93'
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "### Mobile"
|
||||
- type: input
|
||||
attributes:
|
||||
label: Device
|
||||
description: 'e.g. iPhone 6, Pixel 4a'
|
||||
- type: input
|
||||
id: mobile_operatingSystem
|
||||
attributes:
|
||||
label: Operating System
|
||||
description: 'e.g. iOS 8.1, Android 9'
|
||||
- type: input
|
||||
id: mobile_browser
|
||||
attributes:
|
||||
label: Browser
|
||||
description: 'e.g. Google Chrome, Safari'
|
||||
- type: input
|
||||
id: mobile_version
|
||||
attributes:
|
||||
label: Version
|
||||
description: 'e.g. 93'
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Error messages
|
||||
description: |
|
||||
WITH DEBUG TURNED ON, if you're getting an error in your browser, include that error
|
||||
If a stacktrace is provided in the error, include that too.
|
||||
Any errors that appear in your browser's error console.
|
||||
Confirm whether the error is reproducible on the demo: https://snipeitapp.com/demo.
|
||||
Include any additional information you can find in `storage/logs` and your webserver's logs.
|
||||
Include the output from `php -m` (this should display what modules you have enabled.)
|
||||
render: shell
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: |
|
||||
Is this a fresh install or an upgrade?
|
||||
What OS and web server you're running Snipe-IT on
|
||||
What method you used to install Snipe-IT (install.sh, manual installation, docker, etc)
|
||||
Include what you've done so far in the installation, and if you got any error messages along the way.
|
||||
Indicate whether or not you've manually edited any data directly in the database
|
||||
Add any other context about the problem here.
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: Please do not post an issue without answering the related questions above. If you have opened a different issue and already answered these questions, answer them again, once for every ticket. It will be next to impossible for us to help you.
|
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
blank_issues_enabled: false
|
42
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
42
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
name: Feature Request
|
||||
description: Suggest an idea for this project
|
||||
body:
|
||||
- type: input
|
||||
attributes:
|
||||
label: Snipe-IT Version
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: server_operatingSystem
|
||||
attributes:
|
||||
label: Operating System
|
||||
description: 'e.g. Ubuntu, Windows'
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Web Server
|
||||
description: 'e.g. Apache, IIS'
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: PHP Version
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Is your feature request related to a problem? Please describe. A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the solution you'd like A clear and concise description of what you want to happen.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe alternatives you've considered A clear and concise description of any alternative solutions or features you've considered.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context Add any other context or screenshots about the feature request here.
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -63,3 +63,5 @@ _ide_helper.php
|
|||
.phpstorm.meta.php
|
||||
_ide_helper_models.php
|
||||
/.phplint-cache
|
||||
storage/ldap_client_tls.cert
|
||||
storage/ldap_client_tls.key
|
||||
|
|
34
Dockerfile
34
Dockerfile
|
@ -1,5 +1,5 @@
|
|||
FROM ubuntu:bionic
|
||||
LABEL maintainer Brady Wetherington <uberbrady@gmail.com>
|
||||
FROM ubuntu:20.04
|
||||
LABEL maintainer="Brady Wetherington <bwetherington@grokability.com>"
|
||||
|
||||
# No need to add `apt-get clean` here, reference:
|
||||
# - https://github.com/snipe/snipe-it/pull/9201
|
||||
|
@ -14,15 +14,15 @@ RUN export DEBIAN_FRONTEND=noninteractive; \
|
|||
apt-utils \
|
||||
apache2 \
|
||||
apache2-bin \
|
||||
libapache2-mod-php7.2 \
|
||||
php7.2-curl \
|
||||
php7.2-ldap \
|
||||
php7.2-mysql \
|
||||
php7.2-gd \
|
||||
php7.2-xml \
|
||||
php7.2-mbstring \
|
||||
php7.2-zip \
|
||||
php7.2-bcmath \
|
||||
libapache2-mod-php7.4 \
|
||||
php7.4-curl \
|
||||
php7.4-ldap \
|
||||
php7.4-mysql \
|
||||
php7.4-gd \
|
||||
php7.4-xml \
|
||||
php7.4-mbstring \
|
||||
php7.4-zip \
|
||||
php7.4-bcmath \
|
||||
patch \
|
||||
curl \
|
||||
wget \
|
||||
|
@ -38,7 +38,7 @@ autoconf \
|
|||
libc-dev \
|
||||
pkg-config \
|
||||
libmcrypt-dev \
|
||||
php7.2-dev \
|
||||
php7.4-dev \
|
||||
ca-certificates \
|
||||
unzip \
|
||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
@ -47,16 +47,16 @@ unzip \
|
|||
RUN curl -L -O https://github.com/pear/pearweb_phars/raw/master/go-pear.phar
|
||||
RUN php go-pear.phar
|
||||
|
||||
RUN pecl install mcrypt-1.0.2
|
||||
RUN pecl install mcrypt-1.0.3
|
||||
|
||||
RUN bash -c "echo extension=/usr/lib/php/20170718/mcrypt.so > /etc/php/7.2/mods-available/mcrypt.ini"
|
||||
RUN bash -c "echo extension=/usr/lib/php/20190902/mcrypt.so > /etc/php/7.4/mods-available/mcrypt.ini"
|
||||
|
||||
RUN phpenmod mcrypt
|
||||
RUN phpenmod gd
|
||||
RUN phpenmod bcmath
|
||||
|
||||
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/7.2/apache2/php.ini
|
||||
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/7.2/cli/php.ini
|
||||
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/7.4/apache2/php.ini
|
||||
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/7.4/cli/php.ini
|
||||
|
||||
RUN useradd -m --uid 1000 --gid 50 docker
|
||||
|
||||
|
@ -133,4 +133,4 @@ RUN chmod +x /startup.sh /usr/bin/supervisor-exit-event-listener
|
|||
CMD ["/startup.sh"]
|
||||
|
||||
EXPOSE 80
|
||||
EXPOSE 443
|
||||
EXPOSE 443
|
|
@ -1,4 +1,4 @@
|
|||
FROM alpine:3.13
|
||||
FROM alpine:3.14.2
|
||||
# Apache + PHP
|
||||
RUN apk add --no-cache \
|
||||
apache2 \
|
||||
|
@ -82,4 +82,4 @@ ENTRYPOINT ["/sbin/tini", "--"]
|
|||
|
||||
CMD ["/entrypoint.sh"]
|
||||
|
||||
EXPOSE 80
|
||||
EXPOSE 80
|
1
Procfile
Normal file
1
Procfile
Normal file
|
@ -0,0 +1 @@
|
|||
web: php heroku/startup.php && heroku-php-apache2 public/
|
12
README.md
12
README.md
|
@ -1,5 +1,5 @@
|
|||
![Build Status](https://app.chipperci.com/projects/0e5f8979-31eb-4ee6-9abf-050b76ab0383/status/master) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/snipe-it/localized.svg)](https://crowdin.com/project/snipe-it) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/snipe/snipe-it?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Docker Pulls](https://img.shields.io/docker/pulls/snipe/snipe-it.svg)](https://hub.docker.com/r/snipe/snipe-it/) [![Twitter Follow](https://img.shields.io/twitter/follow/snipeitapp.svg?style=social)](https://twitter.com/snipeitapp) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/553ce52037fc43ea99149785afcfe641)](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&utm_medium=referral&utm_content=snipe/snipe-it&utm_campaign=Badge_Grade)
|
||||
[![All Contributors](https://img.shields.io/badge/all_contributors-259-orange.svg?style=flat-square)](#contributors)
|
||||
![Build Status](https://app.chipperci.com/projects/0e5f8979-31eb-4ee6-9abf-050b76ab0383/status/master) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/snipe-it/localized.svg)](https://crowdin.com/project/snipe-it) [![Docker Pulls](https://img.shields.io/docker/pulls/snipe/snipe-it.svg)](https://hub.docker.com/r/snipe/snipe-it/) [![Twitter Follow](https://img.shields.io/twitter/follow/snipeitapp.svg?style=social)](https://twitter.com/snipeitapp) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/553ce52037fc43ea99149785afcfe641)](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&utm_medium=referral&utm_content=snipe/snipe-it&utm_campaign=Badge_Grade)
|
||||
[![All Contributors](https://img.shields.io/badge/all_contributors-271-orange.svg?style=flat-square)](#contributors) [![Discord](https://badgen.net/badge/icon/discord?icon=discord&label)](https://discord.gg/yZFtShAcKk) [![huntr](https://cdn.huntr.dev/huntr_security_badge_mono.svg)](https://huntr.dev)
|
||||
|
||||
## Snipe-IT - Open Source Asset Management System
|
||||
|
||||
|
@ -19,6 +19,8 @@ For instructions on installing and configuring Snipe-IT on your server, check ou
|
|||
|
||||
If you're having trouble with the installation, please check the [Common Issues](https://snipe-it.readme.io/docs/common-issues) and [Getting Help](https://snipe-it.readme.io/docs/getting-help) documentation, and search this repository's open *and* closed issues for help.
|
||||
|
||||
[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)
|
||||
|
||||
-----
|
||||
### User's Manual
|
||||
For help using Snipe-IT, check out the [user's manual](https://snipe-it.readme.io/docs/overview).
|
||||
|
@ -55,11 +57,11 @@ Since the release of the JSON REST API, several third-party developers have been
|
|||
|
||||
- [Python Module](https://github.com/jbloomer/SnipeIT-PythonAPI) by [@jbloomer](https://github.com/jbloomer)
|
||||
- [SnipeSharp - .NET module in C#](https://github.com/barrycarey/SnipeSharp) by [@barrycarey](https://github.com/barrycarey)
|
||||
- [InQRy](https://github.com/Microsoft/InQRy) by [@Microsoft](https://github.com/Microsoft)
|
||||
- [InQRy -unmaintained-](https://github.com/Microsoft/InQRy) by [@Microsoft](https://github.com/Microsoft)
|
||||
- [SnipeitPS](https://github.com/snazy2000/SnipeitPS) by [@snazy2000](https://github.com/snazy2000) - Powershell API Wrapper for Snipe-it
|
||||
- [jamf2snipe](https://github.com/ParadoxGuitarist/jamf2snipe) by [@ParadoxGuitarist](https://github.com/ParadoxGuitarist) - Python script to sync assets between a JAMFPro instance and a Snipe-IT instance
|
||||
- [Marksman](https://github.com/Scope-IT/marksman) - A Windows agent for Snipe-IT
|
||||
- [Snipe-IT plugin for Jira Service Desk (beta)](https://marketplace.atlassian.com/apps/1220379/snipe-it-for-jira-service-desk-beta?hosting=cloud&tab=overview) - for the upcoming Snipe-IT v5 only
|
||||
- [Snipe-IT plugin for Jira Service Desk](https://marketplace.atlassian.com/apps/1220964/snipe-it-for-jira)
|
||||
- [Python 3 CSV importer](https://github.com/gastamper/snipeit-csvimporter) - allows importing assets into Snipe-IT based on Item Name rather than Asset Tag.
|
||||
- [Snipe-IT Kubernetes Helm Chart](https://github.com/t3n/helm-charts/tree/master/snipeit) - For more information, [click here](https://hub.helm.sh/charts/t3n/snipeit).
|
||||
- [Snipe-IT Bulk Edit](https://github.com/bricelabelle/snipe-it-bulkedit) - Google Script files to use Google Sheets as a bulk checkout/checkin/edit tool for Snipe-it.
|
||||
|
@ -126,6 +128,8 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
|
|||
| [<img src="https://avatars.githubusercontent.com/u/9255772?v=4" width="110px;"/><br /><sub>Mark Stenglein</sub>](https://markstenglein.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ocelotsloth "Code") | [<img src="https://avatars.githubusercontent.com/u/35658596?v=4" width="110px;"/><br /><sub>ajsy</sub>](https://github.com/ajsy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ajsy "Code") | [<img src="https://avatars.githubusercontent.com/u/3628035?v=4" width="110px;"/><br /><sub>Jan Kiesewetter</sub>](https://github.com/t3easy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=t3easy "Code") | [<img src="https://avatars.githubusercontent.com/u/79449630?v=4" width="110px;"/><br /><sub>Tetrachloromethane250</sub>](https://github.com/Tetrachloromethane250)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Tetrachloromethane250 "Code") | [<img src="https://avatars.githubusercontent.com/u/22004482?v=4" width="110px;"/><br /><sub>Lars Kajes</sub>](https://www.kajes.se/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=kajes "Code") | [<img src="https://avatars.githubusercontent.com/u/13993216?v=4" width="110px;"/><br /><sub>Joly0</sub>](https://github.com/Joly0)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Joly0 "Code") | [<img src="https://avatars.githubusercontent.com/u/1501022?v=4" width="110px;"/><br /><sub>theburger</sub>](https://github.com/limeless)<br />[💻](https://github.com/snipe/snipe-it/commits?author=limeless "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/36065681?v=4" width="110px;"/><br /><sub>David Valin Alonso</sub>](https://github.com/deivishome)<br />[💻](https://github.com/snipe/snipe-it/commits?author=deivishome "Code") | [<img src="https://avatars.githubusercontent.com/u/8290389?v=4" width="110px;"/><br /><sub>andreaci</sub>](https://github.com/andreaci)<br />[💻](https://github.com/snipe/snipe-it/commits?author=andreaci "Code") | [<img src="https://avatars.githubusercontent.com/u/1828542?v=4" width="110px;"/><br /><sub>Jelle Sebreghts</sub>](http://www.jellesebreghts.be)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Jelle-S "Code") | [<img src="https://avatars.githubusercontent.com/u/11180862?v=4" width="110px;"/><br /><sub>Michael Pietsch</sub>](https://github.com/Skywalker-11)<br /> | [<img src="https://avatars.githubusercontent.com/u/22068886?v=4" width="110px;"/><br /><sub>Masudul Haque Shihab</sub>](https://github.com/sh1hab)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sh1hab "Code") | [<img src="https://avatars.githubusercontent.com/u/16099942?v=4" width="110px;"/><br /><sub>Supapong Areeprasertkul</sub>](http://www.freedomdive.com/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=zybersup "Code") | [<img src="https://avatars.githubusercontent.com/u/207358?v=4" width="110px;"/><br /><sub>Peter Sarossy</sub>](https://github.com/psarossy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=psarossy "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/11823649?v=4" width="110px;"/><br /><sub>Renee Margaret McConahy</sub>](https://github.com/nepella)<br />[💻](https://github.com/snipe/snipe-it/commits?author=nepella "Code") | [<img src="https://avatars.githubusercontent.com/u/5553884?v=4" width="110px;"/><br /><sub>JohnnyPicnic</sub>](https://github.com/JohnnyPicnic)<br />[💻](https://github.com/snipe/snipe-it/commits?author=JohnnyPicnic "Code") | [<img src="https://avatars.githubusercontent.com/u/8799594?v=4" width="110px;"/><br /><sub>markbrule</sub>](https://github.com/markbrule)<br />[💻](https://github.com/snipe/snipe-it/commits?author=markbrule "Code") | [<img src="https://avatars.githubusercontent.com/u/1962801?v=4" width="110px;"/><br /><sub>Mike Campbell</sub>](https://github.com/mikecmpbll)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mikecmpbll "Code") | [<img src="https://avatars.githubusercontent.com/u/11973217?v=4" width="110px;"/><br /><sub>tbrconnect</sub>](https://github.com/tbrconnect)<br />[💻](https://github.com/snipe/snipe-it/commits?author=tbrconnect "Code") | [<img src="https://avatars.githubusercontent.com/u/12447225?v=4" width="110px;"/><br /><sub>kcoyo</sub>](https://github.com/kcoyo)<br />[💻](https://github.com/snipe/snipe-it/commits?author=kcoyo "Code") | [<img src="https://avatars.githubusercontent.com/u/494017?v=4" width="110px;"/><br /><sub>Travis Miller</sub>](https://travismiller.com/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=travismiller "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/8735148?v=4" width="110px;"/><br /><sub>Petri Asikainen</sub>](https://github.com/PetriAsi)<br />[💻](https://github.com/snipe/snipe-it/commits?author=PetriAsi "Code") | [<img src="https://avatars.githubusercontent.com/u/11424540?v=4" width="110px;"/><br /><sub>derdeagle</sub>](https://github.com/derdeagle)<br />[💻](https://github.com/snipe/snipe-it/commits?author=derdeagle "Code") | [<img src="https://avatars.githubusercontent.com/u/176950?v=4" width="110px;"/><br /><sub>Mike Frysinger</sub>](https://wh0rd.org/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=vapier "Code") | [<img src="https://avatars.githubusercontent.com/u/22044358?v=4" width="110px;"/><br /><sub>ALPHA</sub>](https://github.com/AL4AL)<br />[💻](https://github.com/snipe/snipe-it/commits?author=AL4AL "Code") | [<img src="https://avatars.githubusercontent.com/u/1042587?v=4" width="110px;"/><br /><sub>FliegenKLATSCH</sub>](https://www.ifern.de)<br />[💻](https://github.com/snipe/snipe-it/commits?author=FliegenKLATSCH "Code") | [<img src="https://avatars.githubusercontent.com/u/442138?v=4" width="110px;"/><br /><sub>Jeremy Price</sub>](https://github.com/jerm)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jerm "Code") | [<img src="https://avatars.githubusercontent.com/u/84392209?v=4" width="110px;"/><br /><sub>Toreg87</sub>](https://github.com/Toreg87)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Toreg87 "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/67638596?v=4" width="110px;"/><br /><sub>Matthew Nickson</sub>](https://github.com/Computroniks)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Computroniks "Code") | [<img src="https://avatars.githubusercontent.com/u/1646397?v=4" width="110px;"/><br /><sub>Jethro Nederhof</sub>](https://jethron.id.au)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jethron "Code") | [<img src="https://avatars.githubusercontent.com/u/23289826?v=4" width="110px;"/><br /><sub>Oskar Stenberg</sub>](https://github.com/01ste02)<br />[💻](https://github.com/snipe/snipe-it/commits?author=01ste02 "Code") | [<img src="https://avatars.githubusercontent.com/u/82208283?v=4" width="110px;"/><br /><sub>Robert-Azelis</sub>](https://github.com/Robert-Azelis)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Robert-Azelis "Code") | [<img src="https://avatars.githubusercontent.com/u/60648387?v=4" width="110px;"/><br /><sub>Alexander William Smith</sub>](https://github.com/alwism)<br />[💻](https://github.com/snipe/snipe-it/commits?author=alwism "Code") |
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
|
||||
|
|
154
app.json
Normal file
154
app.json
Normal file
|
@ -0,0 +1,154 @@
|
|||
{
|
||||
"name": "Snipe-IT",
|
||||
"description": "Open source asset management.",
|
||||
"keywords": [
|
||||
"asset management",
|
||||
"it asset"
|
||||
],
|
||||
"website": "https://snipeitapp.com/",
|
||||
"repository": "https://github.com/snipe/snipe-it",
|
||||
"logo": "https://pbs.twimg.com/profile_images/976748875733020672/K-HnZCCK_400x400.jpg",
|
||||
"success_url": "/setup",
|
||||
"env": {
|
||||
"APP_ENV": {
|
||||
"description": "Laravel environment mode. Unless developing the application, this should be production.",
|
||||
"value": "production"
|
||||
},
|
||||
"APP_DEBUG": {
|
||||
"description": "Laravel debug mode. Unless developing the application or actively debugging a problem, this should be set to false.",
|
||||
"value": "false"
|
||||
},
|
||||
"APP_KEY": {
|
||||
"description": "A secret key for verifying the integrity of signed cookies. (See either https://snipe-it.readme.io/docs/generate-your-app-key or generate at https://coderstoolbox.online/toolbox/generate-symfony-secret)",
|
||||
"value": ""
|
||||
},
|
||||
"APP_URL": {
|
||||
"description": "URL where your Snipe-IT install will be available at.",
|
||||
"value": "https://your-app-name.herokuapp.com"
|
||||
},
|
||||
"APP_TIMEZONE": {
|
||||
"description": "Which timezone do you want to use for your install? (http://php.net/manual/en/timezones.php)",
|
||||
"value": "UTC"
|
||||
},
|
||||
"APP_LOCALE": {
|
||||
"description": "Which language do you want to use for your install? (https://snipe-it.readme.io/docs/configuration#setting-a-language)",
|
||||
"value": "en"
|
||||
},
|
||||
"MAX_RESULTS": {
|
||||
"description": "The maximum number of search results that can be returned at one time.",
|
||||
"value": "500"
|
||||
},
|
||||
"MAIL_DRIVER": {
|
||||
"description": "Mail driver - Generally SMTP on Heroku - https://snipe-it.readme.io/docs/configuration#required-outgoing-mail-settings",
|
||||
"value": "smtp"
|
||||
},
|
||||
"MAIL_HOST": {
|
||||
"description": "SMTP Server Hostname",
|
||||
"value": "smtp.your.domain.name"
|
||||
},
|
||||
"MAIL_PORT": {
|
||||
"description": "SMTP Server Port",
|
||||
"value": "25"
|
||||
},
|
||||
"MAIL_USERNAME": {
|
||||
"description": "SMTP Server Username",
|
||||
"value": "YOURUSERNAME"
|
||||
},
|
||||
"MAIL_PASSWORD": {
|
||||
"description": "SMTP Server Password",
|
||||
"value": "YOURPASSWORD"
|
||||
},
|
||||
"MAIL_ENCRYPTION": {
|
||||
"description": "Encryption protocol for email sending.",
|
||||
"value": "null"
|
||||
},
|
||||
"MAIL_FROM_ADDR": {
|
||||
"description": "Email from address",
|
||||
"value": "no-reply@domain.name"
|
||||
},
|
||||
"MAIL_FROM_NAME": {
|
||||
"description": "Email from Name",
|
||||
"value": "Snipe-IT"
|
||||
},
|
||||
"MAIL_REPLYTO_ADDR": {
|
||||
"description": "Email Reply-To address",
|
||||
"value": "your@domain.name"
|
||||
},
|
||||
"MAIL_REPLYTO_NAME": {
|
||||
"description": "Email Reply-To Name",
|
||||
"value": "Snipe-IT"
|
||||
},
|
||||
"MAIL_AUTO_EMBED": {
|
||||
"description": "Whether or not to embed images in emails (via CID or base64) versus linking to them.",
|
||||
"value": "true"
|
||||
},
|
||||
"MAIL_AUTO_EMBED_METHOD": {
|
||||
"description": "Method that should be used for attaching inline images.",
|
||||
"value": "base64"
|
||||
},
|
||||
"SESSION_LIFETIME": {
|
||||
"description": "Specify the time in minutes that the session should remain valid.",
|
||||
"value": "12000"
|
||||
},
|
||||
"EXPIRE_ON_CLOSE": {
|
||||
"description": "Specify whether or not the logged in session should be expired when the user closes their browser window.",
|
||||
"value": "false"
|
||||
},
|
||||
"ENCRYPT": {
|
||||
"description": "Specify whether you wish to use encrypted cookies for your Snipe-IT sessions.",
|
||||
"value": "true"
|
||||
},
|
||||
"COOKIE_NAME": {
|
||||
"description": "The name of the cookie set by Snipe-IT for session management.",
|
||||
"value": "snipeit_session"
|
||||
},
|
||||
"COOKIE_DOMAIN": {
|
||||
"description": "The domain name that the session cookie should be sent for.",
|
||||
"value": "your-app-name.herokuapp.com"
|
||||
},
|
||||
"SECURE_COOKIES": {
|
||||
"description": "Should cookies only be sent for HTTPS connections? Generally true on Heroku.",
|
||||
"value": "true"
|
||||
},
|
||||
"LOGIN_MAX_ATTEMPTS": {
|
||||
"description": "The maximum number of failed attempts allowed before the user is throttled.",
|
||||
"value": "5"
|
||||
},
|
||||
"LOGIN_LOCKOUT_DURATION": {
|
||||
"description": "The duration (in seconds) that the user should be blocked from attempting to authenticate again.",
|
||||
"value": "60"
|
||||
},
|
||||
"APP_LOG": {
|
||||
"description": "Driver to send logs to. (errorlog for stderr)",
|
||||
"value": "errorlog"
|
||||
},
|
||||
"ALLOW_IFRAMING": {
|
||||
"description": "Allow Snipe-IT to be loaded using an iFrame?",
|
||||
"value": "false"
|
||||
},
|
||||
"GOOGLE_MAPS_API": {
|
||||
"description": "Include your Google Maps API key here if you'd like Snipe-IT to load maps from Google on your locations and suppliers pages.",
|
||||
"required": false
|
||||
},
|
||||
"BACKUP_ENV": {
|
||||
"description": "Set this to true if you wish to backup your .env file in your Admin > Backups process.",
|
||||
"value": "true"
|
||||
},
|
||||
"ENABLE_HSTS": {
|
||||
"description": "Whether or not to send the HSTS security policy header.",
|
||||
"value": "false"
|
||||
}
|
||||
},
|
||||
"formation": {
|
||||
"web": {
|
||||
"quantity": 1,
|
||||
"size": "free"
|
||||
}
|
||||
},
|
||||
"image": "heroku/php",
|
||||
"addons": [
|
||||
"cleardb:ignite",
|
||||
"heroku-redis:hobby-dev",
|
||||
"papertrail:choklad"
|
||||
]
|
||||
}
|
|
@ -2,23 +2,9 @@
|
|||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Category;
|
||||
use App\Models\Company;
|
||||
use App\Models\Component;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\Department;
|
||||
use App\Models\Depreciation;
|
||||
use App\Models\Group;
|
||||
use App\Models\Import;
|
||||
use App\Models\License;
|
||||
use App\Models\LicenseSeat;
|
||||
use App\Models\Location;
|
||||
use App\Models\Manufacturer;
|
||||
use App\Models\Statuslabel;
|
||||
use App\Models\Supplier;
|
||||
use App\Models\CustomField;
|
||||
use Schema;
|
||||
use DB;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
|
@ -29,15 +15,14 @@ class PaveIt extends Command
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'snipeit:pave
|
||||
{--soft : Perform a "Soft" Delete, leaving all migrations, table structure, and the first user in place.}';
|
||||
protected $signature = 'snipeit:pave {--force : Skip the interactive yes/no prompt for confirmation}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Pave the database to start over. This should ALMOST NEVER BE USED. (It is primarily a quick tool for developers.)';
|
||||
protected $description = 'Clear the database tables, leaving all migrations, table structure, and the first user in place. (It is primarily a quick tool for developers.) If you want to destroy all tables as well, use php artisan db:wipe.';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
|
@ -56,106 +41,51 @@ class PaveIt extends Command
|
|||
*/
|
||||
public function handle()
|
||||
{
|
||||
if ($this->confirm("\n****************************************************\nTHIS WILL DELETE ALL OF THE DATA IN YOUR DATABASE. \nThere is NO undo. This WILL destroy ALL of your data. \n****************************************************\n\nDo you wish to continue? No backsies! [y|N]")) {
|
||||
if ($this->option('soft')) {
|
||||
Accessory::getQuery()->delete();
|
||||
Asset::getQuery()->delete();
|
||||
Category::getQuery()->delete();
|
||||
Company::getQuery()->delete();
|
||||
Component::getQuery()->delete();
|
||||
Consumable::getQuery()->delete();
|
||||
Department::getQuery()->delete();
|
||||
Depreciation::getQuery()->delete();
|
||||
License::getQuery()->delete();
|
||||
LicenseSeat::getQuery()->delete();
|
||||
Location::getQuery()->delete();
|
||||
Manufacturer::getQuery()->delete();
|
||||
AssetModel::getQuery()->delete();
|
||||
Statuslabel::getQuery()->delete();
|
||||
Supplier::getQuery()->delete();
|
||||
Group::getQuery()->delete();
|
||||
Import::getQuery()->delete();
|
||||
|
||||
DB::statement('delete from accessories_users');
|
||||
DB::statement('delete from asset_logs');
|
||||
DB::statement('delete from asset_maintenances');
|
||||
DB::statement('delete from login_attempts');
|
||||
DB::statement('delete from asset_uploads');
|
||||
DB::statement('delete from action_logs');
|
||||
DB::statement('delete from checkout_requests');
|
||||
DB::statement('delete from checkout_acceptances');
|
||||
DB::statement('delete from consumables_users');
|
||||
DB::statement('delete from custom_field_custom_fieldset');
|
||||
DB::statement('delete from custom_fields');
|
||||
DB::statement('delete from custom_fieldsets');
|
||||
DB::statement('delete from components_assets');
|
||||
DB::statement('delete from kits');
|
||||
DB::statement('delete from kits_accessories');
|
||||
DB::statement('delete from kits_consumables');
|
||||
DB::statement('delete from kits_licenses');
|
||||
DB::statement('delete from kits_models');
|
||||
DB::statement('delete from login_attempts');
|
||||
DB::statement('delete from models_custom_fields');
|
||||
DB::statement('delete from permission_groups');
|
||||
DB::statement('delete from password_resets');
|
||||
DB::statement('delete from requested_assets');
|
||||
DB::statement('delete from requests');
|
||||
DB::statement('delete from throttle');
|
||||
DB::statement('delete from users_groups');
|
||||
DB::statement('delete from users WHERE id!=1');
|
||||
} else {
|
||||
\DB::statement('drop table IF EXISTS accessories_users');
|
||||
\DB::statement('drop table IF EXISTS accessories');
|
||||
\DB::statement('drop table IF EXISTS asset_logs');
|
||||
\DB::statement('drop table IF EXISTS action_logs');
|
||||
\DB::statement('drop table IF EXISTS asset_maintenances');
|
||||
\DB::statement('drop table IF EXISTS asset_uploads');
|
||||
\DB::statement('drop table IF EXISTS assets');
|
||||
\DB::statement('drop table IF EXISTS categories');
|
||||
\DB::statement('drop table IF EXISTS checkout_requests');
|
||||
\DB::statement('drop table IF EXISTS checkout_acceptances');
|
||||
\DB::statement('drop table IF EXISTS companies');
|
||||
\DB::statement('drop table IF EXISTS components');
|
||||
\DB::statement('drop table IF EXISTS components_assets');
|
||||
\DB::statement('drop table IF EXISTS consumables_users');
|
||||
\DB::statement('drop table IF EXISTS consumables');
|
||||
\DB::statement('drop table IF EXISTS custom_field_custom_fieldset');
|
||||
\DB::statement('drop table IF EXISTS custom_fields');
|
||||
\DB::statement('drop table IF EXISTS custom_fieldsets');
|
||||
\DB::statement('drop table IF EXISTS depreciations');
|
||||
\DB::statement('drop table IF EXISTS departments');
|
||||
\DB::statement('drop table IF EXISTS groups');
|
||||
\DB::statement('drop table IF EXISTS history');
|
||||
\DB::statement('drop table IF EXISTS kits');
|
||||
\DB::statement('drop table IF EXISTS kits_accessories');
|
||||
\DB::statement('drop table IF EXISTS kits_consumables');
|
||||
\DB::statement('drop table IF EXISTS kits_licenses');
|
||||
\DB::statement('drop table IF EXISTS kits_models');
|
||||
\DB::statement('drop table IF EXISTS models_custom_fields');
|
||||
\DB::statement('drop table IF EXISTS permission_groups');
|
||||
\DB::statement('drop table IF EXISTS license_seats');
|
||||
\DB::statement('drop table IF EXISTS licenses');
|
||||
\DB::statement('drop table IF EXISTS locations');
|
||||
\DB::statement('drop table IF EXISTS login_attempts');
|
||||
\DB::statement('drop table IF EXISTS manufacturers');
|
||||
\DB::statement('drop table IF EXISTS models');
|
||||
\DB::statement('drop table IF EXISTS migrations');
|
||||
\DB::statement('drop table IF EXISTS oauth_access_tokens');
|
||||
\DB::statement('drop table IF EXISTS oauth_auth_codes');
|
||||
\DB::statement('drop table IF EXISTS oauth_clients');
|
||||
\DB::statement('drop table IF EXISTS oauth_personal_access_clients');
|
||||
\DB::statement('drop table IF EXISTS oauth_refresh_tokens');
|
||||
\DB::statement('drop table IF EXISTS password_resets');
|
||||
\DB::statement('drop table IF EXISTS requested_assets');
|
||||
\DB::statement('drop table IF EXISTS requests');
|
||||
\DB::statement('drop table IF EXISTS settings');
|
||||
\DB::statement('drop table IF EXISTS status_labels');
|
||||
\DB::statement('drop table IF EXISTS suppliers');
|
||||
\DB::statement('drop table IF EXISTS throttle');
|
||||
\DB::statement('drop table IF EXISTS users_groups');
|
||||
\DB::statement('drop table IF EXISTS users');
|
||||
\DB::statement('drop table IF EXISTS imports');
|
||||
if (!$this->option('force')) {
|
||||
$confirmation = $this->confirm("\n****************************************************\nTHIS WILL DELETE ALL OF THE DATA IN YOUR DATABASE. \nThere is NO undo. This WILL destroy ALL of your data, \nINCLUDING ANY non-Snipe-IT tables you have in this database. \n****************************************************\n\nDo you wish to continue? No backsies! ");
|
||||
if (!$confirmation) {
|
||||
$this->error('ABORTING');
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
// List all the tables in the database so we don't have to worry about missing some as the app grows
|
||||
$tables = DB::connection()->getDoctrineSchemaManager()->listTableNames();
|
||||
|
||||
$except_tables = [
|
||||
'oauth_access_tokens',
|
||||
'oauth_clients',
|
||||
'oauth_personal_access_clients',
|
||||
'migrations',
|
||||
'settings',
|
||||
'users',
|
||||
];
|
||||
|
||||
// We only need to find out what these are so we can nuke these columns on the assets table.
|
||||
$custom_fields = CustomField::get();
|
||||
foreach ($custom_fields as $custom_field) {
|
||||
$this->info('DROP the '.$custom_field->db_column.' column from assets as well.');
|
||||
|
||||
if (\Schema::hasColumn('assets', $custom_field->db_column)) {
|
||||
\Schema::table('assets', function ($table) use ($custom_field) {
|
||||
$table->dropColumn($custom_field->db_column);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($tables as $table) {
|
||||
if (in_array($table, $except_tables)) {
|
||||
$this->info($table. ' is SKIPPED.');
|
||||
} else {
|
||||
\DB::statement('truncate '.$table);
|
||||
$this->info($table. ' is TRUNCATED.');
|
||||
}
|
||||
}
|
||||
|
||||
// Leave in the demo oauth keys so we don't have to reset them every day in the demos
|
||||
\DB::statement('delete from oauth_clients WHERE id > 2');
|
||||
\DB::statement('delete from oauth_access_tokens WHERE id > 2');
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use Illuminate\Console\Command;
|
||||
|
@ -39,6 +40,7 @@ class ResetDemoSettings extends Command
|
|||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
$this->info('Resetting the demo settings.');
|
||||
$settings = Setting::first();
|
||||
$settings->per_page = 20;
|
||||
|
@ -71,6 +73,7 @@ class ResetDemoSettings extends Command
|
|||
$settings->saml_slo = null;
|
||||
$settings->saml_custom_settings = null;
|
||||
|
||||
|
||||
$settings->save();
|
||||
|
||||
if ($user = User::where('username', '=', 'admin')->first()) {
|
||||
|
@ -78,7 +81,9 @@ class ResetDemoSettings extends Command
|
|||
$user->save();
|
||||
}
|
||||
|
||||
\Storage::disk('local_public')->put('snipe-logo.png', file_get_contents(public_path('img/demo/snipe-logo.png')));
|
||||
\Storage::disk('local_public')->put('snipe-logo-lg.png', file_get_contents(public_path('img/demo/snipe-logo-lg.png')));
|
||||
\Storage::disk('public')->put('snipe-logo.png', file_get_contents(public_path('img/demo/snipe-logo.png')));
|
||||
\Storage::disk('public')->put('snipe-logo-lg.png', file_get_contents(public_path('img/demo/snipe-logo-lg.png')));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ class RestoreFromBackup extends Command
|
|||
|
||||
$za = new ZipArchive();
|
||||
|
||||
$errcode = $za->open($filename, ZipArchive::RDONLY);
|
||||
$errcode = $za->open($filename/* , ZipArchive::RDONLY */); // that constant only exists in PHP 7.4 and higher
|
||||
if ($errcode !== true) {
|
||||
$errors = [
|
||||
ZipArchive::ER_EXISTS => 'File already exists.',
|
||||
|
@ -248,8 +248,13 @@ class RestoreFromBackup extends Command
|
|||
}
|
||||
fclose($pipes[0]);
|
||||
fclose($sql_contents);
|
||||
|
||||
$this->line(stream_get_contents($pipes[1]));
|
||||
fclose($pipes[1]);
|
||||
|
||||
$this->error(stream_get_contents($pipes[2]));
|
||||
fclose($pipes[2]);
|
||||
|
||||
//wait, have to do fclose() on all pipes first?
|
||||
$close_results = proc_close($proc_results);
|
||||
if ($close_results != 0) {
|
||||
|
|
|
@ -54,6 +54,7 @@ class Helper
|
|||
return $cost;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Static colors for pie charts.
|
||||
*
|
||||
|
@ -332,6 +333,8 @@ class Helper
|
|||
'#92896B',
|
||||
];
|
||||
|
||||
|
||||
|
||||
return $colors[$index];
|
||||
}
|
||||
|
||||
|
@ -389,6 +392,7 @@ class Helper
|
|||
return $colors;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Format currency using comma for thousands until local info is property used.
|
||||
*
|
||||
|
@ -398,6 +402,19 @@ class Helper
|
|||
*/
|
||||
public static function ParseFloat($floatString)
|
||||
{
|
||||
/*******
|
||||
*
|
||||
* WARNING: This does conversions based on *locale* - a Unix-ey-like thing.
|
||||
*
|
||||
* Everything else in the system tends to convert based on the Snipe-IT settings
|
||||
*
|
||||
* So it's very likely this is *not* what you want - instead look for the new
|
||||
*
|
||||
* ParseCurrency($currencyString)
|
||||
*
|
||||
* Which should be directly below here
|
||||
*
|
||||
*/
|
||||
$LocaleInfo = localeconv();
|
||||
$floatString = str_replace(',', '', $floatString);
|
||||
$floatString = str_replace($LocaleInfo['decimal_point'], '.', $floatString);
|
||||
|
@ -412,6 +429,26 @@ class Helper
|
|||
|
||||
return floatval($floatString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format currency using comma or period for thousands, and period or comma for decimal, based on settings.
|
||||
*
|
||||
* @author [B. Wetherington] [<bwetherington@grokability.com>]
|
||||
* @since [v5.2]
|
||||
* @return Float
|
||||
*/
|
||||
public static function ParseCurrency($currencyString) {
|
||||
$without_currency = str_replace(Setting::getSettings()->default_currency, '', $currencyString); //generally shouldn't come up, since we don't do this in fields, but just in case it does...
|
||||
if(Setting::getSettings()->digit_separator=='1.234,56') {
|
||||
//EU format
|
||||
$without_thousands = str_replace('.', '', $without_currency);
|
||||
$corrected_decimal = str_replace(',', '.', $without_thousands);
|
||||
} else {
|
||||
$without_thousands = str_replace(',', '', $without_currency);
|
||||
$corrected_decimal = $without_thousands; // decimal is already OK
|
||||
}
|
||||
return floatval($corrected_decimal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of status labels in an array to make a dropdown menu
|
||||
|
@ -780,12 +817,12 @@ class Helper
|
|||
} catch (DecryptException $e) {
|
||||
return 'Error Decrypting: '.$e->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
public static function formatStandardApiResponse($status, $payload = null, $messages = null)
|
||||
|
||||
{
|
||||
$array['status'] = $status;
|
||||
$array['messages'] = $messages;
|
||||
|
@ -869,7 +906,8 @@ class Helper
|
|||
// If upload_max_size is less, then reduce. Except if upload_max_size is
|
||||
// zero, which indicates no limit.
|
||||
$upload_max = self::parse_size(ini_get('upload_max_filesize'));
|
||||
if ($upload_max > 0 && $upload_max < $max_size) {
|
||||
|
||||
if ($upload_max > 0 && $upload_max < $post_max_size) {
|
||||
$max_size = ini_get('upload_max_filesize');
|
||||
}
|
||||
}
|
||||
|
@ -895,33 +933,33 @@ class Helper
|
|||
|
||||
$allowedExtensionMap = [
|
||||
// Images
|
||||
'jpg' => 'fa fa-file-image-o',
|
||||
'jpeg' => 'fa fa-file-image-o',
|
||||
'gif' => 'fa fa-file-image-o',
|
||||
'png' => 'fa fa-file-image-o',
|
||||
'jpg' => 'far fa-image',
|
||||
'jpeg' => 'far fa-image',
|
||||
'gif' => 'far fa-image',
|
||||
'png' => 'far fa-image',
|
||||
// word
|
||||
'doc' => 'fa fa-file-word-o',
|
||||
'docx' => 'fa fa-file-word-o',
|
||||
'doc' => 'far fa-file-word',
|
||||
'docx' => 'far fa-file-word',
|
||||
// Excel
|
||||
'xls' => 'fa fa-file-excel-o',
|
||||
'xlsx' => 'fa fa-file-excel-o',
|
||||
'xls' => 'far fa-file-excel',
|
||||
'xlsx' => 'far fa-file-excel',
|
||||
// archive
|
||||
'zip' => 'fa fa-file-archive-o',
|
||||
'rar' => 'fa fa-file-archive-o',
|
||||
'zip' => 'fas fa-file-archive',
|
||||
'rar' => 'fas fa-file-archive',
|
||||
//Text
|
||||
'txt' => 'fa fa-file-text-o',
|
||||
'rtf' => 'fa fa-file-text-o',
|
||||
'xml' => 'fa fa-file-text-o',
|
||||
'txt' => 'far fa-file-alt',
|
||||
'rtf' => 'far fa-file-alt',
|
||||
'xml' => 'far fa-file-alt',
|
||||
// Misc
|
||||
'pdf' => 'fa fa-file-pdf-o',
|
||||
'lic' => 'fa fa-file-floppy-o',
|
||||
'pdf' => 'far fa-file-pdf',
|
||||
'lic' => 'far fa-save',
|
||||
];
|
||||
|
||||
if ($extension && array_key_exists($extension, $allowedExtensionMap)) {
|
||||
return $allowedExtensionMap[$extension];
|
||||
}
|
||||
|
||||
return 'fa fa-file-o';
|
||||
return 'far fa-file';
|
||||
}
|
||||
|
||||
public static function show_file_inline($filename)
|
||||
|
|
|
@ -66,19 +66,19 @@ class AccessoriesController extends Controller
|
|||
$accessory = new Accessory();
|
||||
|
||||
// Update the accessory data
|
||||
$accessory->name = request('name');
|
||||
$accessory->category_id = request('category_id');
|
||||
$accessory->location_id = request('location_id');
|
||||
$accessory->min_amt = request('min_amt');
|
||||
$accessory->company_id = Company::getIdForCurrentUser(request('company_id'));
|
||||
$accessory->order_number = request('order_number');
|
||||
$accessory->manufacturer_id = request('manufacturer_id');
|
||||
$accessory->model_number = request('model_number');
|
||||
$accessory->purchase_date = request('purchase_date');
|
||||
$accessory->purchase_cost = Helper::ParseFloat(request('purchase_cost'));
|
||||
$accessory->qty = request('qty');
|
||||
$accessory->user_id = Auth::user()->id;
|
||||
$accessory->supplier_id = request('supplier_id');
|
||||
$accessory->name = request('name');
|
||||
$accessory->category_id = request('category_id');
|
||||
$accessory->location_id = request('location_id');
|
||||
$accessory->min_amt = request('min_amt');
|
||||
$accessory->company_id = Company::getIdForCurrentUser(request('company_id'));
|
||||
$accessory->order_number = request('order_number');
|
||||
$accessory->manufacturer_id = request('manufacturer_id');
|
||||
$accessory->model_number = request('model_number');
|
||||
$accessory->purchase_date = request('purchase_date');
|
||||
$accessory->purchase_cost = Helper::ParseCurrency(request('purchase_cost'));
|
||||
$accessory->qty = request('qty');
|
||||
$accessory->user_id = Auth::user()->id;
|
||||
$accessory->supplier_id = request('supplier_id');
|
||||
|
||||
$accessory = $request->handleImages($accessory);
|
||||
|
||||
|
@ -101,6 +101,7 @@ class AccessoriesController extends Controller
|
|||
*/
|
||||
public function edit($accessoryId = null)
|
||||
{
|
||||
|
||||
if ($item = Accessory::find($accessoryId)) {
|
||||
$this->authorize($item);
|
||||
|
||||
|
@ -108,8 +109,10 @@ class AccessoriesController extends Controller
|
|||
}
|
||||
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save edited Accessory from form post
|
||||
*
|
||||
|
@ -128,18 +131,18 @@ class AccessoriesController extends Controller
|
|||
$this->authorize($accessory);
|
||||
|
||||
// Update the accessory data
|
||||
$accessory->name = request('name');
|
||||
$accessory->location_id = request('location_id');
|
||||
$accessory->min_amt = request('min_amt');
|
||||
$accessory->category_id = request('category_id');
|
||||
$accessory->company_id = Company::getIdForCurrentUser(request('company_id'));
|
||||
$accessory->manufacturer_id = request('manufacturer_id');
|
||||
$accessory->order_number = request('order_number');
|
||||
$accessory->model_number = request('model_number');
|
||||
$accessory->purchase_date = request('purchase_date');
|
||||
$accessory->purchase_cost = request('purchase_cost');
|
||||
$accessory->qty = request('qty');
|
||||
$accessory->supplier_id = request('supplier_id');
|
||||
$accessory->name = request('name');
|
||||
$accessory->location_id = request('location_id');
|
||||
$accessory->min_amt = request('min_amt');
|
||||
$accessory->category_id = request('category_id');
|
||||
$accessory->company_id = Company::getIdForCurrentUser(request('company_id'));
|
||||
$accessory->manufacturer_id = request('manufacturer_id');
|
||||
$accessory->order_number = request('order_number');
|
||||
$accessory->model_number = request('model_number');
|
||||
$accessory->purchase_date = request('purchase_date');
|
||||
$accessory->purchase_cost = Helper::ParseCurrency(request('purchase_cost'));
|
||||
$accessory->qty = request('qty');
|
||||
$accessory->supplier_id = request('supplier_id');
|
||||
|
||||
$accessory = $request->handleImages($accessory);
|
||||
|
||||
|
@ -167,6 +170,7 @@ class AccessoriesController extends Controller
|
|||
|
||||
$this->authorize($accessory);
|
||||
|
||||
|
||||
if ($accessory->hasUsers() > 0) {
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.assoc_users', ['count'=> $accessory->hasUsers()]));
|
||||
}
|
||||
|
@ -184,6 +188,7 @@ class AccessoriesController extends Controller
|
|||
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.delete.success'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a view that invokes the ajax table which contains
|
||||
* the content for the accessory detail view, which is generated in getDataView.
|
||||
|
|
|
@ -28,8 +28,23 @@ class AccessoriesController extends Controller
|
|||
{
|
||||
$this->authorize('view', Accessory::class);
|
||||
$allowed_columns = ['id', 'name', 'model_number', 'eol', 'notes', 'created_at', 'min_amt', 'company_id'];
|
||||
|
||||
// This array is what determines which fields should be allowed to be sorted on ON the table itself, no relations
|
||||
// Relations will be handled in query scopes a little further down.
|
||||
$allowed_columns =
|
||||
[
|
||||
'id',
|
||||
'name',
|
||||
'model_number',
|
||||
'eol',
|
||||
'notes',
|
||||
'created_at',
|
||||
'min_amt',
|
||||
'company_id'
|
||||
];
|
||||
|
||||
$accessories = Accessory::with('category', 'company', 'manufacturer', 'users', 'location');
|
||||
|
||||
$accessories = Accessory::select('accessories.*')->with('category', 'company', 'manufacturer', 'users', 'location', 'supplier');
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$accessories = $accessories->TextSearch($request->input('search'));
|
||||
|
@ -51,6 +66,10 @@ class AccessoriesController extends Controller
|
|||
$accessories->where('supplier_id', '=', $request->input('supplier_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('location_id')) {
|
||||
$accessories->where('location_id','=',$request->input('location_id'));
|
||||
}
|
||||
|
||||
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
|
||||
// case we override with the actual count, so we should return 0 items.
|
||||
$offset = (($accessories) && ($request->get('offset') > $accessories->count())) ? $accessories->count() : $request->get('offset', 0);
|
||||
|
@ -59,28 +78,37 @@ class AccessoriesController extends Controller
|
|||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
$sort_override = $request->input('sort');
|
||||
$column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'created_at';
|
||||
|
||||
switch ($sort) {
|
||||
switch ($sort_override) {
|
||||
case 'category':
|
||||
$accessories = $accessories->OrderCategory($order);
|
||||
break;
|
||||
case 'company':
|
||||
$accessories = $accessories->OrderCompany($order);
|
||||
break;
|
||||
case 'location':
|
||||
$accessories = $accessories->OrderLocation($order);
|
||||
break;
|
||||
case 'manufacturer':
|
||||
$accessories = $accessories->OrderManufacturer($order);
|
||||
break;
|
||||
case 'supplier':
|
||||
$accessories = $accessories->OrderSupplier($order);
|
||||
break;
|
||||
default:
|
||||
$accessories = $accessories->orderBy($sort, $order);
|
||||
$accessories = $accessories->orderBy($column_sort, $order);
|
||||
break;
|
||||
}
|
||||
|
||||
$accessories->orderBy($sort, $order);
|
||||
|
||||
|
||||
$total = $accessories->count();
|
||||
$accessories = $accessories->skip($offset)->take($limit)->get();
|
||||
|
||||
return (new AccessoriesTransformer)->transformAccessories($accessories, $total);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
|
@ -94,12 +122,14 @@ class AccessoriesController extends Controller
|
|||
$this->authorize('create', Accessory::class);
|
||||
$accessory = new Accessory;
|
||||
$accessory->fill($request->all());
|
||||
$accessory = $request->handleImages($accessory);
|
||||
|
||||
if ($accessory->save()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $accessory, trans('admin/accessories/message.create.success')));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $accessory->getErrors()));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -118,6 +148,7 @@ class AccessoriesController extends Controller
|
|||
return (new AccessoriesTransformer)->transformAccessory($accessory);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
|
@ -134,6 +165,7 @@ class AccessoriesController extends Controller
|
|||
return (new AccessoriesTransformer)->transformAccessory($accessory);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
|
@ -165,15 +197,20 @@ class AccessoriesController extends Controller
|
|||
|
||||
if ($request->filled('search')) {
|
||||
$accessory_users = $accessory->users()
|
||||
->where('first_name', 'like', '%'.$request->input('search').'%')
|
||||
->orWhere('last_name', 'like', '%'.$request->input('search').'%')
|
||||
->get();
|
||||
->where(function ($query) use ($request) {
|
||||
$search_str = '%' . $request->input('search') . '%';
|
||||
$query->where('first_name', 'like', $search_str)
|
||||
->orWhere('last_name', 'like', $search_str)
|
||||
->orWhere('note', 'like', $search_str);
|
||||
})
|
||||
->get();
|
||||
$total = $accessory_users->count();
|
||||
}
|
||||
|
||||
return (new AccessoriesTransformer)->transformCheckedoutAccessory($accessory, $accessory_users, $total);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
|
@ -220,6 +257,7 @@ class AccessoriesController extends Controller
|
|||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/accessories/message.delete.success')));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save the Accessory checkout information.
|
||||
*
|
||||
|
@ -239,7 +277,9 @@ class AccessoriesController extends Controller
|
|||
|
||||
$this->authorize('checkout', $accessory);
|
||||
|
||||
|
||||
if ($accessory->numRemaining() > 0) {
|
||||
|
||||
if (! $user = User::find($request->input('assigned_to'))) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/accessories/message.checkout.user_does_not_exist')));
|
||||
}
|
||||
|
@ -261,6 +301,7 @@ class AccessoriesController extends Controller
|
|||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'No accessories remaining'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -299,19 +340,23 @@ class AccessoriesController extends Controller
|
|||
$data['item_tag'] = '';
|
||||
$data['note'] = $logaction->note;
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/accessories/message.checkin.success')));
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/accessories/message.checkin.success')));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/accessories/message.checkin.error')));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a paginated collection for the select2 menus
|
||||
*
|
||||
* @see \App\Http\Transformers\SelectlistTransformer
|
||||
*/
|
||||
* Gets a paginated collection for the select2 menus
|
||||
*
|
||||
* @see \App\Http\Transformers\SelectlistTransformer
|
||||
*
|
||||
*/
|
||||
public function selectlist(Request $request)
|
||||
{
|
||||
|
||||
$accessories = Accessory::select([
|
||||
'accessories.id',
|
||||
'accessories.name',
|
||||
|
@ -325,4 +370,5 @@ class AccessoriesController extends Controller
|
|||
|
||||
return (new SelectlistTransformer)->transformSelectlist($accessories);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ use Illuminate\Support\Facades\Input;
|
|||
*/
|
||||
class AssetMaintenancesController extends Controller
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Generates the JSON response for asset maintenances listing view.
|
||||
*
|
||||
|
@ -82,10 +84,12 @@ class AssetMaintenancesController extends Controller
|
|||
|
||||
$total = $maintenances->count();
|
||||
$maintenances = $maintenances->skip($offset)->take($limit)->get();
|
||||
|
||||
return (new AssetMaintenancesTransformer())->transformAssetMaintenances($maintenances, $total);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates and stores the new asset maintenance
|
||||
*
|
||||
|
@ -101,7 +105,7 @@ class AssetMaintenancesController extends Controller
|
|||
$assetMaintenance = new AssetMaintenance();
|
||||
$assetMaintenance->supplier_id = $request->input('supplier_id');
|
||||
$assetMaintenance->is_warranty = $request->input('is_warranty');
|
||||
$assetMaintenance->cost = e($request->input('cost'));
|
||||
$assetMaintenance->cost = Helper::ParseCurrency($request->input('cost'));
|
||||
$assetMaintenance->notes = e($request->input('notes'));
|
||||
$asset = Asset::find(e($request->input('asset_id')));
|
||||
|
||||
|
@ -129,9 +133,11 @@ class AssetMaintenancesController extends Controller
|
|||
// Was the asset maintenance created?
|
||||
if ($assetMaintenance->save()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $assetMaintenance, trans('admin/asset_maintenances/message.create.success')));
|
||||
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $assetMaintenance->getErrors()));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -155,7 +161,7 @@ class AssetMaintenancesController extends Controller
|
|||
|
||||
$assetMaintenance->supplier_id = e($request->input('supplier_id'));
|
||||
$assetMaintenance->is_warranty = e($request->input('is_warranty'));
|
||||
$assetMaintenance->cost = Helper::ParseFloat(e($request->input('cost')));
|
||||
$assetMaintenance->cost = Helper::ParseCurrency($request->input('cost'));
|
||||
$assetMaintenance->notes = e($request->input('notes'));
|
||||
|
||||
$asset = Asset::find(request('asset_id'));
|
||||
|
@ -192,6 +198,7 @@ class AssetMaintenancesController extends Controller
|
|||
// Was the asset maintenance created?
|
||||
if ($assetMaintenance->save()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $assetMaintenance, trans('admin/asset_maintenances/message.edit.success')));
|
||||
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $assetMaintenance->getErrors()));
|
||||
|
@ -218,6 +225,8 @@ class AssetMaintenancesController extends Controller
|
|||
$assetMaintenance->delete();
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $assetMaintenance, trans('admin/asset_maintenances/message.delete.success')));
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -237,5 +246,6 @@ class AssetMaintenancesController extends Controller
|
|||
}
|
||||
|
||||
return (new AssetMaintenancesTransformer())->transformAssetMaintenance($assetMaintenance);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ class AssetModelsController extends Controller
|
|||
->with('category', 'depreciation', 'manufacturer', 'fieldset')
|
||||
->withCount('assets as assets_count');
|
||||
|
||||
if ($request->filled('status')) {
|
||||
if ($request->input('status')=='deleted') {
|
||||
$assetmodels->onlyTrashed();
|
||||
}
|
||||
|
||||
|
@ -102,6 +102,7 @@ class AssetModelsController extends Controller
|
|||
return (new AssetModelsTransformer)->transformAssetModels($assetmodels, $total);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
|
@ -120,8 +121,9 @@ class AssetModelsController extends Controller
|
|||
if ($assetmodel->save()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $assetmodel, trans('admin/models/message.create.success')));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $assetmodel->getErrors()));
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -156,6 +158,7 @@ class AssetModelsController extends Controller
|
|||
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
|
@ -184,6 +187,7 @@ class AssetModelsController extends Controller
|
|||
$assetmodel->fieldset_id = $request->get('custom_fieldset_id');
|
||||
}
|
||||
|
||||
|
||||
if ($assetmodel->save()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $assetmodel, trans('admin/models/message.update.success')));
|
||||
}
|
||||
|
|
|
@ -2,12 +2,16 @@
|
|||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Events\CheckoutableCheckedIn;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\AssetCheckoutRequest;
|
||||
use App\Http\Transformers\AssetsTransformer;
|
||||
use App\Http\Transformers\DepreciationReportTransformer;
|
||||
use App\Http\Transformers\LicensesTransformer;
|
||||
use App\Http\Transformers\SelectlistTransformer;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Company;
|
||||
|
@ -20,7 +24,6 @@ use Auth;
|
|||
use Carbon\Carbon;
|
||||
use DB;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use Input;
|
||||
use Paginator;
|
||||
|
@ -28,6 +31,7 @@ use Slack;
|
|||
use Str;
|
||||
use TCPDF;
|
||||
use Validator;
|
||||
use Route;
|
||||
|
||||
/**
|
||||
* This class controls all actions related to assets for
|
||||
|
@ -46,9 +50,32 @@ class AssetsController extends Controller
|
|||
* @since [v4.0]
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function index(Request $request, $audit = null)
|
||||
public function index(Request $request, $audit = null)
|
||||
{
|
||||
$this->authorize('index', Asset::class);
|
||||
|
||||
\Log::debug(Route::currentRouteName());
|
||||
|
||||
|
||||
/**
|
||||
* This looks MAD janky (and it is), but the AssetsController@index does a LOT of heavy lifting throughout the
|
||||
* app. This bit here just makes sure that someone without permission to view assets doesn't
|
||||
* end up with priv escalations because they asked for a different endpoint.
|
||||
*
|
||||
* Since we never gave the specification for which transformer to use before, it should default
|
||||
* gracefully to just use the AssetTransformer by default, which shouldn't break anything.
|
||||
*
|
||||
* It was either this mess, or repeating ALL of the searching and sorting and filtering code,
|
||||
* which would have been far worse of a mess. *sad face* - snipe (Sept 1, 2021)
|
||||
*/
|
||||
if (Route::currentRouteName()=='api.depreciation-report.index') {
|
||||
$transformer = 'App\Http\Transformers\DepreciationReportTransformer';
|
||||
$this->authorize('reports.view');
|
||||
} else {
|
||||
$transformer = 'App\Http\Transformers\AssetsTransformer';
|
||||
$this->authorize('index', Asset::class);
|
||||
}
|
||||
|
||||
|
||||
$settings = Setting::getSettings();
|
||||
|
||||
$allowed_columns = [
|
||||
|
@ -161,6 +188,8 @@ class AssetsController extends Controller
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// This is used by the sidenav, mostly
|
||||
|
||||
// We switched from using query scopes here because of a Laravel bug
|
||||
|
@ -221,7 +250,7 @@ class AssetsController extends Controller
|
|||
->where('status_alias.archived', '=', 0);
|
||||
});
|
||||
|
||||
// If there is a status ID, don't take show_archived_in_list into consideration
|
||||
// If there is a status ID, don't take show_archived_in_list into consideration
|
||||
} else {
|
||||
$assets->join('status_labels AS status_alias', function ($join) {
|
||||
$join->on('status_alias.id', '=', 'assets.status_id');
|
||||
|
@ -230,12 +259,14 @@ class AssetsController extends Controller
|
|||
|
||||
}
|
||||
|
||||
|
||||
if ((! is_null($filter)) && (count($filter)) > 0) {
|
||||
$assets->ByFilter($filter);
|
||||
} elseif ($request->filled('search')) {
|
||||
$assets->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
|
||||
// This is kinda gross, but we need to do this because the Bootstrap Tables
|
||||
// API passes custom field ordering as custom_fields.fieldname, and we have to strip
|
||||
// that out to let the default sorter below order them correctly on the assets table.
|
||||
|
@ -245,6 +276,7 @@ class AssetsController extends Controller
|
|||
// in the allowed_columns array)
|
||||
$column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'assets.created_at';
|
||||
|
||||
|
||||
switch ($sort_override) {
|
||||
case 'model':
|
||||
$assets->OrderModels($order);
|
||||
|
@ -280,10 +312,28 @@ class AssetsController extends Controller
|
|||
break;
|
||||
}
|
||||
|
||||
|
||||
$total = $assets->count();
|
||||
$assets = $assets->skip($offset)->take($limit)->get();
|
||||
// dd($assets);
|
||||
return (new AssetsTransformer)->transformAssets($assets, $total);
|
||||
|
||||
|
||||
/**
|
||||
* Include additional associated relationships
|
||||
*/
|
||||
if ($request->input('components')) {
|
||||
$assets->loadMissing(['components' => function ($query) {
|
||||
$query->orderBy('created_at', 'desc');
|
||||
}]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Here we're just determining which Transformer (via $transformer) to use based on the
|
||||
* variables we set earlier on in this method - we default to AssetsTransformer.
|
||||
*/
|
||||
return (new $transformer)->transformAssets($assets, $total, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -294,15 +344,16 @@ class AssetsController extends Controller
|
|||
* @since [v4.2.1]
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function showByTag($tag)
|
||||
public function showByTag(Request $request, $tag)
|
||||
{
|
||||
if ($asset = Asset::with('assetstatus')->with('assignedTo')->where('asset_tag', $tag)->first()) {
|
||||
$this->authorize('view', $asset);
|
||||
|
||||
return (new AssetsTransformer)->transformAsset($asset);
|
||||
return (new AssetsTransformer)->transformAsset($asset, $request);
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 200);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -313,17 +364,19 @@ class AssetsController extends Controller
|
|||
* @since [v4.2.1]
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function showBySerial($serial)
|
||||
public function showBySerial(Request $request, $serial)
|
||||
{
|
||||
$this->authorize('index', Asset::class);
|
||||
if ($assets = Asset::with('assetstatus')->with('assignedTo')
|
||||
->withTrashed()->where('serial', $serial)->get()) {
|
||||
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
|
||||
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 200);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns JSON with information about an asset for detail view.
|
||||
*
|
||||
|
@ -332,17 +385,19 @@ class AssetsController extends Controller
|
|||
* @since [v4.0]
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function show($id)
|
||||
public function show(Request $request, $id)
|
||||
{
|
||||
if ($asset = Asset::with('assetstatus')->with('assignedTo')->withTrashed()
|
||||
->withCount('checkins as checkins_count', 'checkouts as checkouts_count', 'userRequests as user_requests_count')->findOrFail($id)) {
|
||||
$this->authorize('view', $asset);
|
||||
|
||||
return (new AssetsTransformer)->transformAsset($asset);
|
||||
return (new AssetsTransformer)->transformAsset($asset, $request->input('components') );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function licenses($id)
|
||||
public function licenses(Request $request, $id)
|
||||
{
|
||||
$this->authorize('view', Asset::class);
|
||||
$this->authorize('view', License::class);
|
||||
|
@ -350,7 +405,8 @@ class AssetsController extends Controller
|
|||
$licenses = $asset->licenses()->get();
|
||||
|
||||
return (new LicensesTransformer())->transformLicenses($licenses, $licenses->count());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a paginated collection for the select2 menus
|
||||
|
@ -358,9 +414,11 @@ class AssetsController extends Controller
|
|||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0.16]
|
||||
* @see \App\Http\Transformers\SelectlistTransformer
|
||||
*
|
||||
*/
|
||||
public function selectlist(Request $request)
|
||||
{
|
||||
|
||||
$assets = Company::scopeCompanyables(Asset::select([
|
||||
'assets.id',
|
||||
'assets.name',
|
||||
|
@ -379,18 +437,22 @@ class AssetsController extends Controller
|
|||
$assets = $assets->AssignedSearch($request->input('search'));
|
||||
}
|
||||
|
||||
|
||||
$assets = $assets->paginate(50);
|
||||
|
||||
// Loop through and set some custom properties for the transformer to use.
|
||||
// This lets us have more flexibility in special cases like assets, where
|
||||
// they may not have a ->name value but we want to display something anyway
|
||||
foreach ($assets as $asset) {
|
||||
|
||||
|
||||
$asset->use_text = $asset->present()->fullName;
|
||||
|
||||
if (($asset->checkedOutToUser()) && ($asset->assigned)) {
|
||||
$asset->use_text .= ' → '.$asset->assigned->getFullNameAttribute();
|
||||
}
|
||||
|
||||
|
||||
if ($asset->assetstatus->getStatuslabelType() == 'pending') {
|
||||
$asset->use_text .= '('.$asset->assetstatus->getStatuslabelType().')';
|
||||
}
|
||||
|
@ -401,6 +463,7 @@ class AssetsController extends Controller
|
|||
return (new SelectlistTransformer)->transformSelectlist($assets);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Accepts a POST request to create a new asset
|
||||
*
|
||||
|
@ -416,34 +479,34 @@ class AssetsController extends Controller
|
|||
$asset = new Asset();
|
||||
$asset->model()->associate(AssetModel::find((int) $request->get('model_id')));
|
||||
|
||||
$asset->name = $request->get('name');
|
||||
$asset->serial = $request->get('serial');
|
||||
$asset->company_id = Company::getIdForCurrentUser($request->get('company_id'));
|
||||
$asset->model_id = $request->get('model_id');
|
||||
$asset->order_number = $request->get('order_number');
|
||||
$asset->notes = $request->get('notes');
|
||||
$asset->asset_tag = $request->get('asset_tag', Asset::autoincrement_asset());
|
||||
$asset->user_id = Auth::id();
|
||||
$asset->archived = '0';
|
||||
$asset->physical = '1';
|
||||
$asset->depreciate = '0';
|
||||
$asset->status_id = $request->get('status_id', 0);
|
||||
$asset->warranty_months = $request->get('warranty_months', null);
|
||||
$asset->purchase_cost = Helper::ParseFloat($request->get('purchase_cost'));
|
||||
$asset->purchase_date = $request->get('purchase_date', null);
|
||||
$asset->assigned_to = $request->get('assigned_to', null);
|
||||
$asset->supplier_id = $request->get('supplier_id', 0);
|
||||
$asset->requestable = $request->get('requestable', 0);
|
||||
$asset->rtd_location_id = $request->get('rtd_location_id', null);
|
||||
$asset->location_id = $request->get('rtd_location_id', null);
|
||||
|
||||
$asset->name = $request->get('name');
|
||||
$asset->serial = $request->get('serial');
|
||||
$asset->company_id = Company::getIdForCurrentUser($request->get('company_id'));
|
||||
$asset->model_id = $request->get('model_id');
|
||||
$asset->order_number = $request->get('order_number');
|
||||
$asset->notes = $request->get('notes');
|
||||
$asset->asset_tag = $request->get('asset_tag', Asset::autoincrement_asset());
|
||||
$asset->user_id = Auth::id();
|
||||
$asset->archived = '0';
|
||||
$asset->physical = '1';
|
||||
$asset->depreciate = '0';
|
||||
$asset->status_id = $request->get('status_id', 0);
|
||||
$asset->warranty_months = $request->get('warranty_months', null);
|
||||
$asset->purchase_cost = Helper::ParseCurrency($request->get('purchase_cost')); // this is the API's store method, so I don't know that I want to do this? Confusing. FIXME (or not?!)
|
||||
$asset->purchase_date = $request->get('purchase_date', null);
|
||||
$asset->assigned_to = $request->get('assigned_to', null);
|
||||
$asset->supplier_id = $request->get('supplier_id', 0);
|
||||
$asset->requestable = $request->get('requestable', 0);
|
||||
$asset->rtd_location_id = $request->get('rtd_location_id', null);
|
||||
$asset->location_id = $request->get('rtd_location_id', null);
|
||||
|
||||
/**
|
||||
* this is here just legacy reasons. Api\AssetController
|
||||
* used image_source once to allow encoded image uploads.
|
||||
*/
|
||||
if ($request->has('image_source')) {
|
||||
$request->offsetSet('image', $request->offsetGet('image_source'));
|
||||
}
|
||||
}
|
||||
|
||||
$asset = $request->handleImages($asset);
|
||||
|
||||
|
@ -478,6 +541,7 @@ class AssetsController extends Controller
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
$asset->{$field->convertUnicodeDbSlug()} = $field_val;
|
||||
}
|
||||
}
|
||||
|
@ -504,6 +568,7 @@ class AssetsController extends Controller
|
|||
return response()->json(Helper::formatStandardApiResponse('error', null, $asset->getErrors()), 200);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Accepts a POST request to update an asset
|
||||
*
|
||||
|
@ -554,9 +619,10 @@ class AssetsController extends Controller
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if ($asset->save()) {
|
||||
if (($request->filled('assigned_user')) && ($target = User::find($request->get('assigned_user')))) {
|
||||
$location = $target->location_id;
|
||||
$location = $target->location_id;
|
||||
} elseif (($request->filled('assigned_asset')) && ($target = Asset::find($request->get('assigned_asset')))) {
|
||||
$location = $target->location_id;
|
||||
|
||||
|
@ -583,6 +649,7 @@ class AssetsController extends Controller
|
|||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete a given asset (mark as deleted).
|
||||
*
|
||||
|
@ -610,6 +677,39 @@ class AssetsController extends Controller
|
|||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore a soft-deleted asset.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
* @since [v5.1.18]
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function restore($assetId = null)
|
||||
{
|
||||
// Get asset information
|
||||
$asset = Asset::withTrashed()->find($assetId);
|
||||
$this->authorize('delete', $asset);
|
||||
if (isset($asset->id)) {
|
||||
// Restore the asset
|
||||
Asset::withTrashed()->where('id', $assetId)->restore();
|
||||
|
||||
$logaction = new Actionlog();
|
||||
$logaction->item_type = Asset::class;
|
||||
$logaction->item_id = $asset->id;
|
||||
$logaction->created_at = date("Y-m-d H:i:s");
|
||||
$logaction->user_id = Auth::user()->id;
|
||||
$logaction->logaction('restored');
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/hardware/message.restore.success')));
|
||||
|
||||
|
||||
}
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Checkout an asset
|
||||
*
|
||||
|
@ -635,12 +735,14 @@ class AssetsController extends Controller
|
|||
'asset_tag' => $asset->asset_tag,
|
||||
];
|
||||
|
||||
|
||||
// This item is checked out to a location
|
||||
if (request('checkout_to_type') == 'location') {
|
||||
$target = Location::find(request('assigned_location'));
|
||||
$asset->location_id = ($target) ? $target->id : '';
|
||||
$error_payload['target_id'] = $request->input('assigned_location');
|
||||
$error_payload['target_type'] = 'location';
|
||||
|
||||
} elseif (request('checkout_to_type') == 'asset') {
|
||||
$target = Asset::where('id', '!=', $asset_id)->find(request('assigned_asset'));
|
||||
$asset->location_id = $target->rtd_location_id;
|
||||
|
@ -648,6 +750,7 @@ class AssetsController extends Controller
|
|||
$asset->location_id = (($target) && (isset($target->location_id))) ? $target->location_id : '';
|
||||
$error_payload['target_id'] = $request->input('assigned_asset');
|
||||
$error_payload['target_type'] = 'asset';
|
||||
|
||||
} elseif (request('checkout_to_type') == 'user') {
|
||||
// Fetch the target and set the asset's new location_id
|
||||
$target = User::find(request('assigned_user'));
|
||||
|
@ -656,10 +759,14 @@ class AssetsController extends Controller
|
|||
$error_payload['target_type'] = 'user';
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (! isset($target)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', $error_payload, 'Checkout target for asset '.e($asset->asset_tag).' is invalid - '.$error_payload['target_type'].' does not exist.'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
$checkout_at = request('checkout_at', date('Y-m-d H:i:s'));
|
||||
$expected_checkin = request('expected_checkin', null);
|
||||
$note = request('note', null);
|
||||
|
@ -667,12 +774,15 @@ class AssetsController extends Controller
|
|||
|
||||
// Set the location ID to the RTD location id if there is one
|
||||
// Wait, why are we doing this? This overrides the stuff we set further up, which makes no sense.
|
||||
// TODO: Follow up here. WTF. Commented out for now.
|
||||
// TODO: Follow up here. WTF. Commented out for now.
|
||||
|
||||
|
||||
// if ((isset($target->rtd_location_id)) && ($asset->rtd_location_id!='')) {
|
||||
// $asset->location_id = $target->rtd_location_id;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
if ($asset->checkOut($target, Auth::user(), $checkout_at, $expected_checkin, $note, $asset_name, $asset->location_id)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkout.success')));
|
||||
}
|
||||
|
@ -680,6 +790,7 @@ class AssetsController extends Controller
|
|||
return response()->json(Helper::formatStandardApiResponse('error', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkout.error')));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checkin an asset
|
||||
*
|
||||
|
@ -694,6 +805,7 @@ class AssetsController extends Controller
|
|||
$asset = Asset::findOrFail($asset_id);
|
||||
$this->authorize('checkin', $asset);
|
||||
|
||||
|
||||
$user = $asset->assignedUser;
|
||||
if (is_null($target = $asset->assignedTo)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkin.already_checked_in')));
|
||||
|
@ -708,7 +820,7 @@ class AssetsController extends Controller
|
|||
if ($request->filled('name')) {
|
||||
$asset->name = $request->input('name');
|
||||
}
|
||||
|
||||
|
||||
$asset->location_id = $asset->rtd_location_id;
|
||||
|
||||
if ($request->filled('location_id')) {
|
||||
|
@ -720,7 +832,7 @@ class AssetsController extends Controller
|
|||
}
|
||||
|
||||
if ($asset->save()) {
|
||||
$asset->logCheckin($target, e($request->input('note')));
|
||||
event(new CheckoutableCheckedIn($asset, $target, Auth::user(), $request->input('note')));
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkin.success')));
|
||||
}
|
||||
|
@ -728,6 +840,7 @@ class AssetsController extends Controller
|
|||
return response()->json(Helper::formatStandardApiResponse('success', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkin.error')));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mark an asset as audited
|
||||
*
|
||||
|
@ -738,6 +851,8 @@ class AssetsController extends Controller
|
|||
*/
|
||||
public function audit(Request $request)
|
||||
{
|
||||
|
||||
|
||||
$this->authorize('audit', Asset::class);
|
||||
$rules = [
|
||||
'asset_tag' => 'required',
|
||||
|
@ -755,6 +870,7 @@ class AssetsController extends Controller
|
|||
|
||||
$asset = Asset::where('asset_tag', '=', $request->input('asset_tag'))->first();
|
||||
|
||||
|
||||
if ($asset) {
|
||||
// We don't want to log this as a normal update, so let's bypass that
|
||||
$asset->unsetEventDispatcher();
|
||||
|
@ -784,8 +900,15 @@ class AssetsController extends Controller
|
|||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', ['asset_tag'=> e($request->input('asset_tag'))], 'Asset with tag '.$request->input('asset_tag').' not found'));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns JSON listing of all requestable assets
|
||||
*
|
||||
|
|
|
@ -47,6 +47,7 @@ class CategoriesController extends Controller
|
|||
$categories = $categories->skip($offset)->take($limit)->get();
|
||||
|
||||
return (new CategoriesTransformer)->transformCategories($categories, $total);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -62,6 +63,7 @@ class CategoriesController extends Controller
|
|||
$this->authorize('create', Category::class);
|
||||
$category = new Category;
|
||||
$category->fill($request->all());
|
||||
$category->category_type = strtolower($request->input('category_type'));
|
||||
$category = $request->handleImages($category);
|
||||
|
||||
if ($category->save()) {
|
||||
|
@ -101,6 +103,7 @@ class CategoriesController extends Controller
|
|||
$this->authorize('update', Category::class);
|
||||
$category = Category::findOrFail($id);
|
||||
$category->fill($request->all());
|
||||
$category->category_type = strtolower($request->input('category_type'));
|
||||
$category = $request->handleImages($category);
|
||||
|
||||
if ($category->save()) {
|
||||
|
|
|
@ -9,6 +9,9 @@ use App\Models\Company;
|
|||
use App\Models\Component;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Events\CheckoutableCheckedIn;
|
||||
use App\Events\ComponentCheckedIn;
|
||||
use App\Models\Asset;
|
||||
|
||||
class ComponentsController extends Controller
|
||||
{
|
||||
|
@ -23,8 +26,25 @@ class ComponentsController extends Controller
|
|||
public function index(Request $request)
|
||||
{
|
||||
$this->authorize('view', Component::class);
|
||||
|
||||
// This array is what determines which fields should be allowed to be sorted on ON the table itself, no relations
|
||||
// Relations will be handled in query scopes a little further down.
|
||||
$allowed_columns =
|
||||
[
|
||||
'id',
|
||||
'name',
|
||||
'min_amt',
|
||||
'order_number',
|
||||
'serial',
|
||||
'purchase_date',
|
||||
'purchase_cost',
|
||||
'qty',
|
||||
'image',
|
||||
];
|
||||
|
||||
|
||||
$components = Company::scopeCompanyables(Component::select('components.*')
|
||||
->with('company', 'location', 'category'));
|
||||
->with('company', 'location', 'category', 'assets'));
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$components = $components->TextSearch($request->input('search'));
|
||||
|
@ -49,11 +69,12 @@ class ComponentsController extends Controller
|
|||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$allowed_columns = ['id', 'name', 'min_amt', 'order_number', 'serial', 'purchase_date', 'purchase_cost', 'company', 'category', 'qty', 'location', 'image'];
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
$sort_override = $request->input('sort');
|
||||
$column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'created_at';
|
||||
|
||||
switch ($sort) {
|
||||
switch ($sort_override) {
|
||||
case 'category':
|
||||
$components = $components->OrderCategory($order);
|
||||
break;
|
||||
|
@ -64,7 +85,7 @@ class ComponentsController extends Controller
|
|||
$components = $components->OrderCompany($order);
|
||||
break;
|
||||
default:
|
||||
$components = $components->orderBy($sort, $order);
|
||||
$components = $components->orderBy($column_sort, $order);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -74,6 +95,7 @@ class ComponentsController extends Controller
|
|||
return (new ComponentsTransformer)->transformComponents($components, $total);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
|
@ -163,11 +185,11 @@ class ComponentsController extends Controller
|
|||
* @param Request $request
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
*/
|
||||
public function getAssets(Request $request, $id)
|
||||
{
|
||||
$this->authorize('view', \App\Models\Asset::class);
|
||||
|
||||
|
||||
$component = Component::findOrFail($id);
|
||||
$assets = $component->assets();
|
||||
|
||||
|
@ -178,4 +200,119 @@ class ComponentsController extends Controller
|
|||
|
||||
return (new ComponentsTransformer)->transformCheckedoutComponents($assets, $total);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate and checkout the component.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* t
|
||||
* @since [v5.1.8]
|
||||
* @param Request $request
|
||||
* @param int $componentId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function checkout(Request $request, $componentId)
|
||||
{
|
||||
// Check if the component exists
|
||||
if (is_null($component = Component::find($componentId))) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/components/message.does_not_exist')));
|
||||
}
|
||||
|
||||
$this->authorize('checkout', $component);
|
||||
|
||||
|
||||
if ($component->numRemaining() >= $request->get('assigned_qty')) {
|
||||
|
||||
if (!$asset = Asset::find($request->input('assigned_to'))) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')));
|
||||
}
|
||||
|
||||
// Update the accessory data
|
||||
$component->assigned_to = $request->input('assigned_to');
|
||||
|
||||
$component->assets()->attach($component->id, [
|
||||
'component_id' => $component->id,
|
||||
'created_at' => \Carbon::now(),
|
||||
'assigned_qty' => $request->get('assigned_qty', 1),
|
||||
'user_id' => \Auth::id(),
|
||||
'asset_id' => $request->get('assigned_to')
|
||||
]);
|
||||
|
||||
$component->logCheckout($request->input('note'), $asset);
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/components/message.checkout.success')));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Not enough components remaining: '.$component->numRemaining().' remaining, '.$request->get('assigned_qty').' requested.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate and store checkin data.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v5.1.8]
|
||||
* @param Request $request
|
||||
* @param $component_asset_id
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function checkin(Request $request, $component_asset_id)
|
||||
{
|
||||
if ($component_assets = \DB::table('components_assets')->find($component_asset_id)) {
|
||||
|
||||
if (is_null($component = Component::find($component_assets->component_id))) {
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/components/message.not_found')));
|
||||
}
|
||||
|
||||
$this->authorize('checkin', $component);
|
||||
|
||||
$max_to_checkin = $component_assets->assigned_qty;
|
||||
|
||||
if ($max_to_checkin > 1) {
|
||||
|
||||
$validator = \Validator::make($request->all(), [
|
||||
"checkin_qty" => "required|numeric|between:1,$max_to_checkin"
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Checkin quantity must be between 1 and '.$max_to_checkin));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Validation passed, so let's figure out what we have to do here.
|
||||
$qty_remaining_in_checkout = ($component_assets->assigned_qty - (int)$request->input('checkin_qty', 1));
|
||||
|
||||
// We have to modify the record to reflect the new qty that's
|
||||
// actually checked out.
|
||||
$component_assets->assigned_qty = $qty_remaining_in_checkout;
|
||||
|
||||
\Log::debug($component_asset_id.' - '.$qty_remaining_in_checkout.' remaining in record '.$component_assets->id);
|
||||
|
||||
\DB::table('components_assets')->where('id',
|
||||
$component_asset_id)->update(['assigned_qty' => $qty_remaining_in_checkout]);
|
||||
|
||||
// If the checked-in qty is exactly the same as the assigned_qty,
|
||||
// we can simply delete the associated components_assets record
|
||||
if ($qty_remaining_in_checkout == 0) {
|
||||
\DB::table('components_assets')->where('id', '=', $component_asset_id)->delete();
|
||||
}
|
||||
|
||||
|
||||
$asset = Asset::find($component_assets->asset_id);
|
||||
|
||||
event(new CheckoutableCheckedIn($component, $asset, \Auth::user(), $request->input('note'), \Carbon::now()));
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/components/message.checkin.success')));
|
||||
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'No matching checkouts for that component join record'));
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,26 @@ class ConsumablesController extends Controller
|
|||
public function index(Request $request)
|
||||
{
|
||||
$this->authorize('index', Consumable::class);
|
||||
|
||||
// This array is what determines which fields should be allowed to be sorted on ON the table itself, no relations
|
||||
// Relations will be handled in query scopes a little further down.
|
||||
$allowed_columns =
|
||||
[
|
||||
'id',
|
||||
'name',
|
||||
'order_number',
|
||||
'min_amt',
|
||||
'purchase_date',
|
||||
'purchase_cost',
|
||||
'company',
|
||||
'category',
|
||||
'model_number',
|
||||
'item_no',
|
||||
'qty',
|
||||
'image',
|
||||
];
|
||||
|
||||
|
||||
$consumables = Company::scopeCompanyables(
|
||||
Consumable::select('consumables.*')
|
||||
->with('company', 'location', 'category', 'users', 'manufacturer')
|
||||
|
@ -42,10 +62,19 @@ class ConsumablesController extends Controller
|
|||
$consumables->where('category_id', '=', $request->input('category_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('model_number')) {
|
||||
$consumables->where('model_number','=',$request->input('model_number'));
|
||||
}
|
||||
|
||||
if ($request->filled('manufacturer_id')) {
|
||||
$consumables->where('manufacturer_id', '=', $request->input('manufacturer_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('location_id')) {
|
||||
$consumables->where('location_id','=',$request->input('location_id'));
|
||||
}
|
||||
|
||||
|
||||
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
|
||||
// case we override with the actual count, so we should return 0 items.
|
||||
$offset = (($consumables) && ($request->get('offset') > $consumables->count())) ? $consumables->count() : $request->get('offset', 0);
|
||||
|
@ -55,9 +84,12 @@ class ConsumablesController extends Controller
|
|||
|
||||
$allowed_columns = ['id', 'name', 'order_number', 'min_amt', 'purchase_date', 'purchase_cost', 'company', 'category', 'model_number', 'item_no', 'manufacturer', 'location', 'qty', 'image'];
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
|
||||
switch ($sort) {
|
||||
$sort_override = $request->input('sort');
|
||||
$column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'created_at';
|
||||
|
||||
|
||||
switch ($sort_override) {
|
||||
case 'category':
|
||||
$consumables = $consumables->OrderCategory($order);
|
||||
break;
|
||||
|
@ -71,7 +103,7 @@ class ConsumablesController extends Controller
|
|||
$consumables = $consumables->OrderCompany($order);
|
||||
break;
|
||||
default:
|
||||
$consumables = $consumables->orderBy($sort, $order);
|
||||
$consumables = $consumables->orderBy($column_sort, $order);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -160,13 +192,13 @@ class ConsumablesController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a JSON response containing details on the users associated with this consumable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see \App\Http\Controllers\Consumables\ConsumablesController::getView() method that returns the form.
|
||||
* @since [v1.0]
|
||||
* @param int $consumableId
|
||||
* @return array
|
||||
* Returns a JSON response containing details on the users associated with this consumable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see \App\Http\Controllers\Consumables\ConsumablesController::getView() method that returns the form.
|
||||
* @since [v1.0]
|
||||
* @param int $consumableId
|
||||
* @return array
|
||||
*/
|
||||
public function getDataView($consumableId)
|
||||
{
|
||||
|
@ -251,10 +283,10 @@ class ConsumablesController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets a paginated collection for the select2 menus
|
||||
*
|
||||
* @see \App\Http\Transformers\SelectlistTransformer
|
||||
*/
|
||||
* Gets a paginated collection for the select2 menus
|
||||
*
|
||||
* @see \App\Http\Transformers\SelectlistTransformer
|
||||
*/
|
||||
public function selectlist(Request $request)
|
||||
{
|
||||
$consumables = Consumable::select([
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Transformers\LocationsTransformer;
|
||||
use App\Http\Transformers\SelectlistTransformer;
|
||||
use App\Models\Location;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
|
@ -79,6 +79,7 @@ class LocationsController extends Controller
|
|||
return (new LocationsTransformer)->transformLocations($locations, $total);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
|
|
|
@ -47,6 +47,7 @@ class StatuslabelsController extends Controller
|
|||
return (new StatuslabelsTransformer)->transformStatuslabels($statuslabels, $total);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
|
@ -71,6 +72,10 @@ class StatuslabelsController extends Controller
|
|||
$statuslabel->deployable = $statusType['deployable'];
|
||||
$statuslabel->pending = $statusType['pending'];
|
||||
$statuslabel->archived = $statusType['archived'];
|
||||
$statuslabel->color = $request->input('color');
|
||||
$statuslabel->show_in_nav = $request->input('show_in_nav', 0);
|
||||
$statuslabel->default_label = $request->input('default_label', 0);
|
||||
|
||||
|
||||
if ($statuslabel->save()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $statuslabel, trans('admin/statuslabels/message.create.success')));
|
||||
|
@ -108,7 +113,7 @@ class StatuslabelsController extends Controller
|
|||
{
|
||||
$this->authorize('update', Statuslabel::class);
|
||||
$statuslabel = Statuslabel::findOrFail($id);
|
||||
|
||||
|
||||
$request->except('deployable', 'pending', 'archived');
|
||||
|
||||
if (! $request->filled('type')) {
|
||||
|
@ -121,6 +126,9 @@ class StatuslabelsController extends Controller
|
|||
$statuslabel->deployable = $statusType['deployable'];
|
||||
$statuslabel->pending = $statusType['pending'];
|
||||
$statuslabel->archived = $statusType['archived'];
|
||||
$statuslabel->color = $request->input('color');
|
||||
$statuslabel->show_in_nav = $request->input('show_in_nav', 0);
|
||||
$statuslabel->default_label = $request->input('default_label', 0);
|
||||
|
||||
if ($statuslabel->save()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $statuslabel, trans('admin/statuslabels/message.update.success')));
|
||||
|
@ -153,7 +161,7 @@ class StatuslabelsController extends Controller
|
|||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/statuslabels/message.assoc_assets')));
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Show a count of assets by status label for pie chart
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
|
@ -164,10 +172,7 @@ class StatuslabelsController extends Controller
|
|||
{
|
||||
$this->authorize('view', Statuslabel::class);
|
||||
|
||||
$statuslabels = Statuslabel::with('assets')
|
||||
->groupBy('id')
|
||||
->withCount('assets as assets_count')
|
||||
->get();
|
||||
$statuslabels = Statuslabel::withCount('assets')->get();
|
||||
|
||||
$labels = [];
|
||||
$points = [];
|
||||
|
@ -183,8 +188,8 @@ class StatuslabelsController extends Controller
|
|||
$colors_array[] = $statuslabel->color;
|
||||
} else {
|
||||
$colors_array[] = Helper::defaultChartColors($default_color_count);
|
||||
$default_color_count++;
|
||||
}
|
||||
$default_color_count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,9 +233,11 @@ class StatuslabelsController extends Controller
|
|||
$total = $assets->count();
|
||||
$assets = $assets->skip($offset)->take($limit)->get();
|
||||
|
||||
|
||||
return (new AssetsTransformer)->transformAssets($assets, $total);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a boolean response based on whether the status label
|
||||
* is one that is deployable.
|
||||
|
|
|
@ -8,7 +8,7 @@ use App\Http\Transformers\SelectlistTransformer;
|
|||
use App\Http\Transformers\SuppliersTransformer;
|
||||
use App\Models\Supplier;
|
||||
use Illuminate\Http\Request;
|
||||
use App\http\Requests\ImageUploadRequest;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class SuppliersController extends Controller
|
||||
|
@ -24,11 +24,12 @@ class SuppliersController extends Controller
|
|||
{
|
||||
$this->authorize('view', Supplier::class);
|
||||
$allowed_columns = ['id', 'name', 'address', 'phone', 'contact', 'fax', 'email', 'image', 'assets_count', 'licenses_count', 'accessories_count', 'url'];
|
||||
|
||||
|
||||
$suppliers = Supplier::select(
|
||||
['id', 'name', 'address', 'address2', 'city', 'state', 'country', 'fax', 'phone', 'email', 'contact', 'created_at', 'updated_at', 'deleted_at', 'image', 'notes']
|
||||
)->withCount('assets as assets_count')->withCount('licenses as licenses_count')->withCount('accessories as accessories_count');
|
||||
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$suppliers = $suppliers->TextSearch($request->input('search'));
|
||||
}
|
||||
|
@ -50,6 +51,7 @@ class SuppliersController extends Controller
|
|||
return (new SuppliersTransformer)->transformSuppliers($suppliers, $total);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
|
|
|
@ -68,12 +68,17 @@ class UsersController extends Controller
|
|||
->withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count');
|
||||
$users = Company::scopeCompanyables($users);
|
||||
|
||||
|
||||
if (($request->filled('deleted')) && ($request->input('deleted') == 'true')) {
|
||||
$users = $users->onlyTrashed();
|
||||
} elseif (($request->filled('all')) && ($request->input('all') == 'true')) {
|
||||
$users = $users->withTrashed();
|
||||
}
|
||||
|
||||
if ($request->filled('activated')) {
|
||||
$users = $users->where('users.activated', '=', $request->input('activated'));
|
||||
}
|
||||
|
||||
if ($request->filled('company_id')) {
|
||||
$users = $users->where('users.company_id', '=', $request->input('company_id'));
|
||||
}
|
||||
|
@ -90,6 +95,30 @@ class UsersController extends Controller
|
|||
$users = $users->where('users.username', '=', $request->input('username'));
|
||||
}
|
||||
|
||||
if ($request->filled('first_name')) {
|
||||
$users = $users->where('users.first_name', '=', $request->input('first_name'));
|
||||
}
|
||||
|
||||
if ($request->filled('last_name')) {
|
||||
$users = $users->where('users.last_name', '=', $request->input('last_name'));
|
||||
}
|
||||
|
||||
if ($request->filled('employee_num')) {
|
||||
$users = $users->where('users.employee_num', '=', $request->input('employee_num'));
|
||||
}
|
||||
|
||||
if ($request->filled('state')) {
|
||||
$users = $users->where('users.state', '=', $request->input('state'));
|
||||
}
|
||||
|
||||
if ($request->filled('country')) {
|
||||
$users = $users->where('users.country', '=', $request->input('country'));
|
||||
}
|
||||
|
||||
if ($request->filled('zip')) {
|
||||
$users = $users->where('users.zip', '=', $request->input('zip'));
|
||||
}
|
||||
|
||||
if ($request->filled('group_id')) {
|
||||
$users = $users->ByGroup($request->get('group_id'));
|
||||
}
|
||||
|
@ -98,6 +127,10 @@ class UsersController extends Controller
|
|||
$users = $users->where('users.department_id', '=', $request->input('department_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('manager_id')) {
|
||||
$users = $users->where('users.manager_id','=',$request->input('manager_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$users = $users->TextSearch($request->input('search'));
|
||||
}
|
||||
|
@ -112,6 +145,7 @@ class UsersController extends Controller
|
|||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
|
||||
switch ($request->input('sort')) {
|
||||
case 'manager':
|
||||
$users = $users->OrderManager($order);
|
||||
|
@ -201,6 +235,8 @@ class UsersController extends Controller
|
|||
return (new SelectlistTransformer)->transformSelectlist($users);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
|
@ -259,6 +295,7 @@ class UsersController extends Controller
|
|||
return (new UsersTransformer)->transformUser($user);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
|
@ -274,14 +311,21 @@ class UsersController extends Controller
|
|||
|
||||
$user = User::findOrFail($id);
|
||||
|
||||
// This is a janky hack to prevent people from changing admin demo user data on the public demo.
|
||||
// The $ids 1 and 2 are special since they are seeded as superadmins in the demo seeder.
|
||||
// Thanks, jerks. You are why we can't have nice things. - snipe
|
||||
/**
|
||||
* This is a janky hack to prevent people from changing admin demo user data on the public demo.
|
||||
*
|
||||
* The $ids 1 and 2 are special since they are seeded as superadmins in the demo seeder.
|
||||
*
|
||||
* Thanks, jerks. You are why we can't have nice things. - snipe
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
if ((($id == 1) || ($id == 2)) && (config('app.lock_passwords'))) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Permission denied. You cannot update user information via API on the demo.'));
|
||||
}
|
||||
|
||||
|
||||
$user->fill($request->all());
|
||||
|
||||
if ($user->id == $request->input('manager_id')) {
|
||||
|
@ -305,6 +349,8 @@ class UsersController extends Controller
|
|||
$user->permissions = $permissions_array;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Update the location of any assets checked out to this user
|
||||
Asset::where('assigned_type', User::class)
|
||||
->where('assigned_to', $user->id)->update(['location_id' => $request->input('location_id', null)]);
|
||||
|
@ -328,6 +374,7 @@ class UsersController extends Controller
|
|||
$user->groups()->sync([]);
|
||||
}
|
||||
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', (new UsersTransformer)->transformUser($user), trans('admin/users/message.success.update')));
|
||||
}
|
||||
|
||||
|
@ -389,13 +436,13 @@ class UsersController extends Controller
|
|||
* @param $userId
|
||||
* @return string JSON
|
||||
*/
|
||||
public function assets($id)
|
||||
public function assets(Request $request, $id)
|
||||
{
|
||||
$this->authorize('view', User::class);
|
||||
$this->authorize('view', Asset::class);
|
||||
$assets = Asset::where('assigned_to', '=', $id)->where('assigned_type', '=', User::class)->with('model')->get();
|
||||
|
||||
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
|
||||
return (new AssetsTransformer)->transformAssets($assets, $assets->count(), $request);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -458,8 +505,9 @@ class UsersController extends Controller
|
|||
return response()->json(['message' => trans('admin/settings/general.two_factor_reset_error')], 500);
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json(['message' => 'No ID provided'], 500);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -474,4 +522,28 @@ class UsersController extends Controller
|
|||
{
|
||||
return (new UsersTransformer)->transformUser($request->user());
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore a soft-deleted user.
|
||||
*
|
||||
* @author [E. Taylor] [<dev@evantaylor.name>]
|
||||
* @param int $userId
|
||||
* @since [v6.0.0]
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function restore($userId = null)
|
||||
{
|
||||
// Get asset information
|
||||
$user = User::withTrashed()->find($userId);
|
||||
$this->authorize('delete', $user);
|
||||
if (isset($user->id)) {
|
||||
// Restore the user
|
||||
User::withTrashed()->where('id', $userId)->restore();
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.success.restored')));
|
||||
}
|
||||
|
||||
$id = $userId;
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found', compact('id'))), 200);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,14 +23,14 @@ use View;
|
|||
class AssetMaintenancesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Checks for permissions for this action.
|
||||
*
|
||||
* @todo This should be replaced with middleware and/or policies
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
* @return View
|
||||
*/
|
||||
* Checks for permissions for this action.
|
||||
*
|
||||
* @todo This should be replaced with middleware and/or policies
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
* @return View
|
||||
*/
|
||||
private static function getInsufficientPermissionsRedirect()
|
||||
{
|
||||
return redirect()->route('maintenances.index')
|
||||
|
@ -38,16 +38,16 @@ class AssetMaintenancesController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a view that invokes the ajax tables which actually contains
|
||||
* the content for the asset maintenances listing, which is generated in getDatatable.
|
||||
*
|
||||
* @todo This should be replaced with middleware and/or policies
|
||||
* @see AssetMaintenancesController::getDatatable() method that generates the JSON response
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
* @return View
|
||||
*/
|
||||
* Returns a view that invokes the ajax tables which actually contains
|
||||
* the content for the asset maintenances listing, which is generated in getDatatable.
|
||||
*
|
||||
* @todo This should be replaced with middleware and/or policies
|
||||
* @see AssetMaintenancesController::getDatatable() method that generates the JSON response
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
* @return View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('asset_maintenances/index');
|
||||
|
@ -84,21 +84,21 @@ class AssetMaintenancesController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Validates and stores the new asset maintenance
|
||||
*
|
||||
* @see AssetMaintenancesController::getCreate() method for the form
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
* @return mixed
|
||||
*/
|
||||
* Validates and stores the new asset maintenance
|
||||
*
|
||||
* @see AssetMaintenancesController::getCreate() method for the form
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
* @return mixed
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
// create a new model instance
|
||||
$assetMaintenance = new AssetMaintenance();
|
||||
$assetMaintenance->supplier_id = $request->input('supplier_id');
|
||||
$assetMaintenance->is_warranty = $request->input('is_warranty');
|
||||
$assetMaintenance->cost = $request->input('cost');
|
||||
$assetMaintenance->cost = Helper::ParseCurrency($request->input('cost'));
|
||||
$assetMaintenance->notes = $request->input('notes');
|
||||
$asset = Asset::find($request->input('asset_id'));
|
||||
|
||||
|
@ -134,15 +134,15 @@ class AssetMaintenancesController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a form view to edit a selected asset maintenance.
|
||||
*
|
||||
* @see AssetMaintenancesController::postEdit() method that stores the data
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @param int $assetMaintenanceId
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
* @return mixed
|
||||
*/
|
||||
* Returns a form view to edit a selected asset maintenance.
|
||||
*
|
||||
* @see AssetMaintenancesController::postEdit() method that stores the data
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @param int $assetMaintenanceId
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
* @return mixed
|
||||
*/
|
||||
public function edit($assetMaintenanceId = null)
|
||||
{
|
||||
// Check if the asset maintenance exists
|
||||
|
@ -204,10 +204,10 @@ class AssetMaintenancesController extends Controller
|
|||
return static::getInsufficientPermissionsRedirect();
|
||||
}
|
||||
|
||||
$assetMaintenance->supplier_id = e($request->input('supplier_id'));
|
||||
$assetMaintenance->is_warranty = e($request->input('is_warranty'));
|
||||
$assetMaintenance->cost = Helper::ParseFloat(e($request->input('cost')));
|
||||
$assetMaintenance->notes = e($request->input('notes'));
|
||||
$assetMaintenance->supplier_id = $request->input('supplier_id');
|
||||
$assetMaintenance->is_warranty = $request->input('is_warranty');
|
||||
$assetMaintenance->cost = Helper::ParseCurrency($request->input('cost'));
|
||||
$assetMaintenance->notes = $request->input('notes');
|
||||
|
||||
$asset = Asset::find(request('asset_id'));
|
||||
|
||||
|
@ -240,7 +240,7 @@ class AssetMaintenancesController extends Controller
|
|||
$assetMaintenance->asset_maintenance_time = $completionDate->diffInDays($startDate);
|
||||
}
|
||||
|
||||
// Was the asset maintenance created?
|
||||
// Was the asset maintenance created?
|
||||
if ($assetMaintenance->save()) {
|
||||
|
||||
// Redirect to the new asset maintenance page
|
||||
|
@ -252,14 +252,14 @@ class AssetMaintenancesController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Delete an asset maintenance
|
||||
*
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @param int $assetMaintenanceId
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
* @return mixed
|
||||
*/
|
||||
* Delete an asset maintenance
|
||||
*
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @param int $assetMaintenanceId
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
* @return mixed
|
||||
*/
|
||||
public function destroy($assetMaintenanceId)
|
||||
{
|
||||
// Check if the asset maintenance exists
|
||||
|
@ -280,14 +280,14 @@ class AssetMaintenancesController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* View an asset maintenance
|
||||
*
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @param int $assetMaintenanceId
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
* @return View
|
||||
*/
|
||||
* View an asset maintenance
|
||||
*
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @param int $assetMaintenanceId
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
* @return View
|
||||
*/
|
||||
public function show($assetMaintenanceId)
|
||||
{
|
||||
// Check if the asset maintenance exists
|
||||
|
|
|
@ -7,6 +7,8 @@ use App\Helpers\Helper;
|
|||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\AssetCheckinRequest;
|
||||
use App\Models\Asset;
|
||||
use App\Models\CheckoutAcceptance;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
use Illuminate\Support\Facades\View;
|
||||
|
@ -109,6 +111,16 @@ class AssetCheckinController extends Controller
|
|||
$checkin_at = $request->input('checkin_at');
|
||||
}
|
||||
|
||||
// Get all pending Acceptances for this asset and delete them
|
||||
$acceptances = CheckoutAcceptance::pending()->whereHasMorph('checkoutable',
|
||||
[Asset::class],
|
||||
function (Builder $query) use ($asset) {
|
||||
$query->where('id', $asset->id);
|
||||
})->get();
|
||||
$acceptances->map(function($acceptance) {
|
||||
$acceptance->delete();
|
||||
});
|
||||
|
||||
// Was the asset updated?
|
||||
if ($asset->save()) {
|
||||
event(new CheckoutableCheckedIn($asset, $target, Auth::user(), $request->input('note'), $checkin_at));
|
||||
|
|
|
@ -9,6 +9,7 @@ use App\Models\Actionlog;
|
|||
use App\Models\Asset;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use enshrined\svgSanitize\Sanitizer;
|
||||
|
||||
class AssetFilesController extends Controller
|
||||
{
|
||||
|
@ -36,9 +37,29 @@ class AssetFilesController extends Controller
|
|||
}
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$file_name = 'hardware-'.$asset->id.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
|
||||
|
||||
// Check for SVG and sanitize it
|
||||
if ($extension=='svg') {
|
||||
\Log::debug('This is an SVG');
|
||||
|
||||
$sanitizer = new Sanitizer();
|
||||
$dirtySVG = file_get_contents($file->getRealPath());
|
||||
$cleanSVG = $sanitizer->sanitize($dirtySVG);
|
||||
|
||||
try {
|
||||
Storage::put('private_uploads/assets/'.$file_name, $cleanSVG);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Upload no workie :( ');
|
||||
\Log::debug($e);
|
||||
}
|
||||
} else {
|
||||
Storage::put('private_uploads/assets/'.$file_name, file_get_contents($file));
|
||||
}
|
||||
|
||||
|
||||
$asset->logUpload($file_name, e($request->get('notes')));
|
||||
}
|
||||
|
||||
|
@ -127,7 +148,6 @@ class AssetFilesController extends Controller
|
|||
|
||||
return redirect()->back()->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
}
|
||||
$log->delete();
|
||||
|
||||
return redirect()->back()
|
||||
->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
|
|
|
@ -129,22 +129,22 @@ class AssetsController extends Controller
|
|||
$asset->asset_tag = $asset_tags[$a];
|
||||
}
|
||||
|
||||
$asset->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$asset->model_id = $request->input('model_id');
|
||||
$asset->order_number = $request->input('order_number');
|
||||
$asset->notes = $request->input('notes');
|
||||
$asset->user_id = Auth::id();
|
||||
$asset->archived = '0';
|
||||
$asset->physical = '1';
|
||||
$asset->depreciate = '0';
|
||||
$asset->status_id = request('status_id', 0);
|
||||
$asset->warranty_months = request('warranty_months', null);
|
||||
$asset->purchase_cost = Helper::ParseFloat($request->get('purchase_cost'));
|
||||
$asset->purchase_date = request('purchase_date', null);
|
||||
$asset->assigned_to = request('assigned_to', null);
|
||||
$asset->supplier_id = request('supplier_id', 0);
|
||||
$asset->requestable = request('requestable', 0);
|
||||
$asset->rtd_location_id = request('rtd_location_id', null);
|
||||
$asset->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$asset->model_id = $request->input('model_id');
|
||||
$asset->order_number = $request->input('order_number');
|
||||
$asset->notes = $request->input('notes');
|
||||
$asset->user_id = Auth::id();
|
||||
$asset->archived = '0';
|
||||
$asset->physical = '1';
|
||||
$asset->depreciate = '0';
|
||||
$asset->status_id = request('status_id', 0);
|
||||
$asset->warranty_months = request('warranty_months', null);
|
||||
$asset->purchase_cost = Helper::ParseCurrency($request->get('purchase_cost'));
|
||||
$asset->purchase_date = request('purchase_date', null);
|
||||
$asset->assigned_to = request('assigned_to', null);
|
||||
$asset->supplier_id = request('supplier_id', 0);
|
||||
$asset->requestable = request('requestable', 0);
|
||||
$asset->rtd_location_id = request('rtd_location_id', null);
|
||||
|
||||
if (! empty($settings->audit_interval)) {
|
||||
$asset->next_audit_date = Carbon::now()->addMonths($settings->audit_interval)->toDateString();
|
||||
|
@ -296,7 +296,7 @@ class AssetsController extends Controller
|
|||
|
||||
$asset->status_id = $request->input('status_id', null);
|
||||
$asset->warranty_months = $request->input('warranty_months', null);
|
||||
$asset->purchase_cost = Helper::ParseFloat($request->input('purchase_cost', null));
|
||||
$asset->purchase_cost = Helper::ParseCurrency($request->input('purchase_cost', null));
|
||||
$asset->purchase_date = $request->input('purchase_date', null);
|
||||
$asset->supplier_id = $request->input('supplier_id', null);
|
||||
$asset->expected_checkin = $request->input('expected_checkin', null);
|
||||
|
@ -357,6 +357,7 @@ class AssetsController extends Controller
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if ($asset->save()) {
|
||||
return redirect()->route('hardware.show', $assetId)
|
||||
->with('success', trans('admin/hardware/message.update.success'));
|
||||
|
@ -828,8 +829,8 @@ class AssetsController extends Controller
|
|||
Storage::putFileAs($path, $upload, $file_name);
|
||||
}
|
||||
|
||||
$asset->logAudit($request->input('note'), $request->input('location_id'), $file_name);
|
||||
|
||||
$asset->logAudit($request->input('note'), $request->input('location_id'), $file_name);
|
||||
return redirect()->to('hardware')->with('success', trans('admin/hardware/message.audit.success'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,8 @@ class BulkAssetsController extends Controller
|
|||
return redirect()->back()->with('error', 'No assets selected');
|
||||
}
|
||||
|
||||
$asset_ids = array_keys($request->input('ids'));
|
||||
|
||||
$asset_ids = array_values(array_unique($request->input('ids')));
|
||||
|
||||
if ($request->filled('bulk_actions')) {
|
||||
switch ($request->input('bulk_actions')) {
|
||||
|
@ -51,7 +52,7 @@ class BulkAssetsController extends Controller
|
|||
return view('hardware/bulk-delete')->with('assets', $assets);
|
||||
case 'edit':
|
||||
return view('hardware/bulk')
|
||||
->with('assets', request('ids'))
|
||||
->with('assets', $asset_ids)
|
||||
->with('statuslabel_list', Helper::statusLabelList());
|
||||
}
|
||||
}
|
||||
|
@ -92,6 +93,7 @@ class BulkAssetsController extends Controller
|
|||
|| ($request->filled('model_id'))
|
||||
) {
|
||||
foreach ($assets as $assetId) {
|
||||
|
||||
$this->update_array = [];
|
||||
|
||||
$this->conditionallyAddItem('purchase_date')
|
||||
|
@ -104,7 +106,7 @@ class BulkAssetsController extends Controller
|
|||
->conditionallyAddItem('warranty_months');
|
||||
|
||||
if ($request->filled('purchase_cost')) {
|
||||
$this->update_array['purchase_cost'] = Helper::ParseFloat($request->input('purchase_cost'));
|
||||
$this->update_array['purchase_cost'] = Helper::ParseCurrency($request->input('purchase_cost'));
|
||||
}
|
||||
|
||||
if ($request->filled('company_id')) {
|
||||
|
|
|
@ -29,6 +29,7 @@ class ForgotPasswordController extends Controller
|
|||
public function __construct()
|
||||
{
|
||||
$this->middleware('guest');
|
||||
$this->middleware('throttle:5,1', ['except' => 'showLinkRequestForm']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -66,13 +67,21 @@ class ForgotPasswordController extends Controller
|
|||
* Once we have attempted to send the link, we will examine the response
|
||||
* then see the message we need to show to the user. Finally, we'll send out a proper response.
|
||||
*/
|
||||
$response = $this->broker()->sendResetLink(
|
||||
array_merge(
|
||||
$request->only('username'),
|
||||
['activated' => '1'],
|
||||
['ldap_import' => '0']
|
||||
)
|
||||
);
|
||||
|
||||
$response = null;
|
||||
|
||||
try {
|
||||
$response = $this->broker()->sendResetLink(
|
||||
array_merge(
|
||||
$request->only('username'),
|
||||
['activated' => '1'],
|
||||
['ldap_import' => '0']
|
||||
)
|
||||
);
|
||||
} catch(\Exception $e) {
|
||||
\Log::info('Password reset attempt: User '.$request->input('username').'failed with exception: '.$e );
|
||||
}
|
||||
|
||||
|
||||
if ($response === \Password::RESET_LINK_SENT) {
|
||||
\Log::info('Password reset attempt: User '.$request->input('username').' WAS found, password reset sent');
|
||||
|
@ -91,10 +100,10 @@ class ForgotPasswordController extends Controller
|
|||
*
|
||||
* Instead we tell the user we've sent an email even though we haven't.
|
||||
* It's bad UX, but better security. The compromises we sometimes have to make.
|
||||
*/
|
||||
*/
|
||||
|
||||
// Regardless of response, we do not want to disclose the status of a user account,
|
||||
// so we give them a generic "If this exists, we're TOTALLY gonna email you" response
|
||||
return redirect()->route('login')->with('success', trans('passwords.sent'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,6 +154,9 @@ class LoginController extends Controller
|
|||
{
|
||||
$header_name = Setting::getSettings()->login_remote_user_header_name ?: 'REMOTE_USER';
|
||||
$remote_user = $request->server($header_name);
|
||||
if (!isset($remote_user)) {
|
||||
$remote_user = $request->server('REDIRECT_'.$header_name);
|
||||
}
|
||||
if (Setting::getSettings()->login_remote_user_enabled == '1' && isset($remote_user) && ! empty($remote_user)) {
|
||||
Log::debug("Authenticating via HTTP header $header_name.");
|
||||
|
||||
|
|
|
@ -80,6 +80,11 @@ class BulkAssetModelsController extends Controller
|
|||
$update_array['depreciation_id'] = $request->input('depreciation_id');
|
||||
}
|
||||
|
||||
if ($request->filled('requestable') != '') {
|
||||
$update_array['requestable'] = $request->input('requestable');
|
||||
}
|
||||
|
||||
|
||||
if (count($update_array) > 0) {
|
||||
AssetModel::whereIn('id', $models_raw_array)->update($update_array);
|
||||
|
||||
|
|
|
@ -39,6 +39,8 @@ trait CheckInOutRequest
|
|||
switch (request('checkout_to_type')) {
|
||||
case 'location':
|
||||
$asset->location_id = $target->id;
|
||||
Asset::where('assigned_type', 'App\Models\Asset')->where('assigned_to', $asset->id)
|
||||
->update(['location_id' => $asset->location_id]);
|
||||
break;
|
||||
case 'asset':
|
||||
$asset->location_id = $target->rtd_location_id;
|
||||
|
|
|
@ -6,6 +6,7 @@ use App\Http\Controllers\Controller;
|
|||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Models\Company;
|
||||
use App\Models\Component;
|
||||
use App\Helpers\Helper;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
@ -36,6 +37,7 @@ class ComponentsController extends Controller
|
|||
return view('components/index');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a form to create a new component.
|
||||
*
|
||||
|
@ -67,17 +69,17 @@ class ComponentsController extends Controller
|
|||
{
|
||||
$this->authorize('create', Component::class);
|
||||
$component = new Component();
|
||||
$component->name = $request->input('name');
|
||||
$component->category_id = $request->input('category_id');
|
||||
$component->location_id = $request->input('location_id');
|
||||
$component->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$component->order_number = $request->input('order_number', null);
|
||||
$component->min_amt = $request->input('min_amt', null);
|
||||
$component->serial = $request->input('serial', null);
|
||||
$component->purchase_date = $request->input('purchase_date', null);
|
||||
$component->purchase_cost = $request->input('purchase_cost', null);
|
||||
$component->qty = $request->input('qty');
|
||||
$component->user_id = Auth::id();
|
||||
$component->name = $request->input('name');
|
||||
$component->category_id = $request->input('category_id');
|
||||
$component->location_id = $request->input('location_id');
|
||||
$component->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$component->order_number = $request->input('order_number', null);
|
||||
$component->min_amt = $request->input('min_amt', null);
|
||||
$component->serial = $request->input('serial', null);
|
||||
$component->purchase_date = $request->input('purchase_date', null);
|
||||
$component->purchase_cost = Helper::ParseCurrency($request->input('purchase_cost', null));
|
||||
$component->qty = $request->input('qty');
|
||||
$component->user_id = Auth::id();
|
||||
|
||||
$component = $request->handleImages($component);
|
||||
|
||||
|
@ -109,6 +111,7 @@ class ComponentsController extends Controller
|
|||
return redirect()->route('components.index')->with('error', trans('admin/components/message.does_not_exist'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a view to edit a component.
|
||||
*
|
||||
|
@ -139,16 +142,16 @@ class ComponentsController extends Controller
|
|||
$this->authorize('update', $component);
|
||||
|
||||
// Update the component data
|
||||
$component->name = $request->input('name');
|
||||
$component->category_id = $request->input('category_id');
|
||||
$component->location_id = $request->input('location_id');
|
||||
$component->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$component->order_number = $request->input('order_number');
|
||||
$component->min_amt = $request->input('min_amt');
|
||||
$component->serial = $request->input('serial');
|
||||
$component->purchase_date = $request->input('purchase_date');
|
||||
$component->purchase_cost = request('purchase_cost');
|
||||
$component->qty = $request->input('qty');
|
||||
$component->name = $request->input('name');
|
||||
$component->category_id = $request->input('category_id');
|
||||
$component->location_id = $request->input('location_id');
|
||||
$component->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$component->order_number = $request->input('order_number');
|
||||
$component->min_amt = $request->input('min_amt');
|
||||
$component->serial = $request->input('serial');
|
||||
$component->purchase_date = $request->input('purchase_date');
|
||||
$component->purchase_cost = Helper::ParseCurrency(request('purchase_cost'));
|
||||
$component->qty = $request->input('qty');
|
||||
|
||||
$component = $request->handleImages($component);
|
||||
|
||||
|
|
|
@ -65,19 +65,19 @@ class ConsumablesController extends Controller
|
|||
{
|
||||
$this->authorize('create', Consumable::class);
|
||||
$consumable = new Consumable();
|
||||
$consumable->name = $request->input('name');
|
||||
$consumable->category_id = $request->input('category_id');
|
||||
$consumable->location_id = $request->input('location_id');
|
||||
$consumable->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$consumable->order_number = $request->input('order_number');
|
||||
$consumable->min_amt = $request->input('min_amt');
|
||||
$consumable->manufacturer_id = $request->input('manufacturer_id');
|
||||
$consumable->model_number = $request->input('model_number');
|
||||
$consumable->item_no = $request->input('item_no');
|
||||
$consumable->purchase_date = $request->input('purchase_date');
|
||||
$consumable->purchase_cost = Helper::ParseFloat($request->input('purchase_cost'));
|
||||
$consumable->qty = $request->input('qty');
|
||||
$consumable->user_id = Auth::id();
|
||||
$consumable->name = $request->input('name');
|
||||
$consumable->category_id = $request->input('category_id');
|
||||
$consumable->location_id = $request->input('location_id');
|
||||
$consumable->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$consumable->order_number = $request->input('order_number');
|
||||
$consumable->min_amt = $request->input('min_amt');
|
||||
$consumable->manufacturer_id = $request->input('manufacturer_id');
|
||||
$consumable->model_number = $request->input('model_number');
|
||||
$consumable->item_no = $request->input('item_no');
|
||||
$consumable->purchase_date = $request->input('purchase_date');
|
||||
$consumable->purchase_cost = Helper::ParseCurrency($request->input('purchase_cost'));
|
||||
$consumable->qty = $request->input('qty');
|
||||
$consumable->user_id = Auth::id();
|
||||
|
||||
$consumable = $request->handleImages($consumable);
|
||||
|
||||
|
@ -128,18 +128,18 @@ class ConsumablesController extends Controller
|
|||
|
||||
$this->authorize($consumable);
|
||||
|
||||
$consumable->name = $request->input('name');
|
||||
$consumable->category_id = $request->input('category_id');
|
||||
$consumable->location_id = $request->input('location_id');
|
||||
$consumable->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$consumable->order_number = $request->input('order_number');
|
||||
$consumable->min_amt = $request->input('min_amt');
|
||||
$consumable->manufacturer_id = $request->input('manufacturer_id');
|
||||
$consumable->model_number = $request->input('model_number');
|
||||
$consumable->item_no = $request->input('item_no');
|
||||
$consumable->purchase_date = $request->input('purchase_date');
|
||||
$consumable->purchase_cost = Helper::ParseFloat($request->input('purchase_cost'));
|
||||
$consumable->qty = Helper::ParseFloat($request->input('qty'));
|
||||
$consumable->name = $request->input('name');
|
||||
$consumable->category_id = $request->input('category_id');
|
||||
$consumable->location_id = $request->input('location_id');
|
||||
$consumable->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$consumable->order_number = $request->input('order_number');
|
||||
$consumable->min_amt = $request->input('min_amt');
|
||||
$consumable->manufacturer_id = $request->input('manufacturer_id');
|
||||
$consumable->model_number = $request->input('model_number');
|
||||
$consumable->item_no = $request->input('item_no');
|
||||
$consumable->purchase_date = $request->input('purchase_date');
|
||||
$consumable->purchase_cost = Helper::ParseCurrency($request->input('purchase_cost'));
|
||||
$consumable->qty = Helper::ParseFloat($request->input('qty'));
|
||||
|
||||
$consumable = $request->handleImages($consumable);
|
||||
|
||||
|
|
|
@ -125,8 +125,8 @@ class DepreciationsController extends Controller
|
|||
$this->authorize('update', $depreciation);
|
||||
|
||||
// Depreciation data
|
||||
$depreciation->name = $request->input('name');
|
||||
$depreciation->months = $request->input('months');
|
||||
$depreciation->name = $request->input('name');
|
||||
$depreciation->months = $request->input('months');
|
||||
$depreciation->depreciation_min = $request->input('depreciation_min');
|
||||
|
||||
// Was the asset created?
|
||||
|
|
|
@ -7,6 +7,7 @@ use App\Http\Controllers\Controller;
|
|||
use App\Models\License;
|
||||
use App\Models\LicenseSeat;
|
||||
use App\Models\User;
|
||||
use App\Models\Asset;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
|
@ -80,7 +81,12 @@ class LicenseCheckinController extends Controller
|
|||
// Ooops.. something went wrong
|
||||
return redirect()->back()->withInput()->withErrors($validator);
|
||||
}
|
||||
$return_to = User::find($licenseSeat->assigned_to);
|
||||
|
||||
if($licenseSeat->assigned_to != null){
|
||||
$return_to = User::find($licenseSeat->assigned_to);
|
||||
} else {
|
||||
$return_to = Asset::find($licenseSeat->asset_id);
|
||||
}
|
||||
|
||||
// Update the asset data
|
||||
$licenseSeat->assigned_to = null;
|
||||
|
|
|
@ -7,10 +7,10 @@ use App\Http\Controllers\Controller;
|
|||
use App\Http\Requests\AssetFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\License;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use enshrined\svgSanitize\Sanitizer;
|
||||
|
||||
class LicenseFilesController extends Controller
|
||||
{
|
||||
|
@ -37,26 +37,39 @@ class LicenseFilesController extends Controller
|
|||
Storage::makeDirectory('private_uploads/licenses', 775);
|
||||
}
|
||||
|
||||
$upload_success = false;
|
||||
foreach ($request->file('file') as $file) {
|
||||
$file_name = 'license-'.$license->id.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$file->getClientOriginalExtension())).'.'.$file->getClientOriginalExtension();
|
||||
|
||||
$upload_success = $file->storeAs('private_uploads/licenses', $file_name);
|
||||
// $upload_success = $file->storeAs('private_uploads/licenses/'.$file_name, $file);
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$file_name = 'license-'.$license->id.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
|
||||
|
||||
|
||||
// Check for SVG and sanitize it
|
||||
if ($extension == 'svg') {
|
||||
\Log::debug('This is an SVG');
|
||||
\Log::debug($file_name);
|
||||
|
||||
$sanitizer = new Sanitizer();
|
||||
$dirtySVG = file_get_contents($file->getRealPath());
|
||||
$cleanSVG = $sanitizer->sanitize($dirtySVG);
|
||||
|
||||
try {
|
||||
Storage::put('private_uploads/licenses/'.$file_name, $cleanSVG);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Upload no workie :( ');
|
||||
\Log::debug($e);
|
||||
}
|
||||
|
||||
} else {
|
||||
Storage::put('private_uploads/licenses/'.$file_name, file_get_contents($file));
|
||||
}
|
||||
|
||||
//Log the upload to the log
|
||||
$license->logUpload($file_name, e($request->input('notes')));
|
||||
}
|
||||
|
||||
// This being called from a modal seems to confuse redirect()->back()
|
||||
// It thinks we should go to the dashboard. As this is only used
|
||||
// from the modal at present, hardcode the redirect. Longterm
|
||||
// maybe we evaluate something else.
|
||||
if ($upload_success) {
|
||||
return redirect()->route('licenses.show', $license->id)->with('success', trans('admin/licenses/message.upload.success'));
|
||||
}
|
||||
|
||||
return redirect()->route('licenses.show', $license->id)->with('error', trans('admin/licenses/message.upload.error'));
|
||||
return redirect()->route('licenses.show', $license->id)->with('success', trans('admin/licenses/message.upload.success'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('licenses.show', $license->id)->with('error', trans('admin/licenses/message.upload.nofiles'));
|
||||
|
@ -153,6 +166,7 @@ class LicenseFilesController extends Controller
|
|||
}
|
||||
|
||||
return StorageHelper::downloader($file);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,27 +76,27 @@ class LicensesController extends Controller
|
|||
// create a new model instance
|
||||
$license = new License();
|
||||
// Save the license data
|
||||
$license->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$license->depreciation_id = $request->input('depreciation_id');
|
||||
$license->expiration_date = $request->input('expiration_date');
|
||||
$license->license_email = $request->input('license_email');
|
||||
$license->license_name = $request->input('license_name');
|
||||
$license->maintained = $request->input('maintained', 0);
|
||||
$license->manufacturer_id = $request->input('manufacturer_id');
|
||||
$license->name = $request->input('name');
|
||||
$license->notes = $request->input('notes');
|
||||
$license->order_number = $request->input('order_number');
|
||||
$license->purchase_cost = $request->input('purchase_cost');
|
||||
$license->purchase_date = $request->input('purchase_date');
|
||||
$license->purchase_order = $request->input('purchase_order');
|
||||
$license->purchase_order = $request->input('purchase_order');
|
||||
$license->reassignable = $request->input('reassignable', 0);
|
||||
$license->seats = $request->input('seats');
|
||||
$license->serial = $request->input('serial');
|
||||
$license->supplier_id = $request->input('supplier_id');
|
||||
$license->category_id = $request->input('category_id');
|
||||
$license->termination_date = $request->input('termination_date');
|
||||
$license->user_id = Auth::id();
|
||||
$license->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$license->depreciation_id = $request->input('depreciation_id');
|
||||
$license->expiration_date = $request->input('expiration_date');
|
||||
$license->license_email = $request->input('license_email');
|
||||
$license->license_name = $request->input('license_name');
|
||||
$license->maintained = $request->input('maintained', 0);
|
||||
$license->manufacturer_id = $request->input('manufacturer_id');
|
||||
$license->name = $request->input('name');
|
||||
$license->notes = $request->input('notes');
|
||||
$license->order_number = $request->input('order_number');
|
||||
$license->purchase_cost = Helper::ParseCurrency($request->input('purchase_cost'));
|
||||
$license->purchase_date = $request->input('purchase_date');
|
||||
$license->purchase_order = $request->input('purchase_order');
|
||||
$license->purchase_order = $request->input('purchase_order');
|
||||
$license->reassignable = $request->input('reassignable', 0);
|
||||
$license->seats = $request->input('seats');
|
||||
$license->serial = $request->input('serial');
|
||||
$license->supplier_id = $request->input('supplier_id');
|
||||
$license->category_id = $request->input('category_id');
|
||||
$license->termination_date = $request->input('termination_date');
|
||||
$license->user_id = Auth::id();
|
||||
|
||||
if ($license->save()) {
|
||||
return redirect()->route('licenses.index')->with('success', trans('admin/licenses/message.create.success'));
|
||||
|
@ -154,25 +154,25 @@ class LicensesController extends Controller
|
|||
|
||||
$this->authorize('update', $license);
|
||||
|
||||
$license->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$license->depreciation_id = $request->input('depreciation_id');
|
||||
$license->expiration_date = $request->input('expiration_date');
|
||||
$license->license_email = $request->input('license_email');
|
||||
$license->license_name = $request->input('license_name');
|
||||
$license->maintained = $request->input('maintained', 0);
|
||||
$license->name = $request->input('name');
|
||||
$license->notes = $request->input('notes');
|
||||
$license->order_number = $request->input('order_number');
|
||||
$license->purchase_cost = $request->input('purchase_cost');
|
||||
$license->purchase_date = $request->input('purchase_date');
|
||||
$license->purchase_order = $request->input('purchase_order');
|
||||
$license->reassignable = $request->input('reassignable', 0);
|
||||
$license->serial = $request->input('serial');
|
||||
$license->termination_date = $request->input('termination_date');
|
||||
$license->seats = e($request->input('seats'));
|
||||
$license->manufacturer_id = $request->input('manufacturer_id');
|
||||
$license->supplier_id = $request->input('supplier_id');
|
||||
$license->category_id = $request->input('category_id');
|
||||
$license->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$license->depreciation_id = $request->input('depreciation_id');
|
||||
$license->expiration_date = $request->input('expiration_date');
|
||||
$license->license_email = $request->input('license_email');
|
||||
$license->license_name = $request->input('license_name');
|
||||
$license->maintained = $request->input('maintained',0);
|
||||
$license->name = $request->input('name');
|
||||
$license->notes = $request->input('notes');
|
||||
$license->order_number = $request->input('order_number');
|
||||
$license->purchase_cost = Helper::ParseCurrency($request->input('purchase_cost'));
|
||||
$license->purchase_date = $request->input('purchase_date');
|
||||
$license->purchase_order = $request->input('purchase_order');
|
||||
$license->reassignable = $request->input('reassignable', 0);
|
||||
$license->serial = $request->input('serial');
|
||||
$license->termination_date = $request->input('termination_date');
|
||||
$license->seats = e($request->input('seats'));
|
||||
$license->manufacturer_id = $request->input('manufacturer_id');
|
||||
$license->supplier_id = $request->input('supplier_id');
|
||||
$license->category_id = $request->input('category_id');
|
||||
|
||||
if ($license->save()) {
|
||||
return redirect()->route('licenses.show', ['license' => $licenseId])->with('success', trans('admin/licenses/message.update.success'));
|
||||
|
|
|
@ -12,8 +12,10 @@ use App\Models\CustomField;
|
|||
use App\Models\Depreciation;
|
||||
use App\Models\License;
|
||||
use App\Models\Setting;
|
||||
use App\Notifications\CheckoutAssetNotification;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Input;
|
||||
|
@ -37,12 +39,12 @@ class ReportsController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a view that displays the accessories report.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @return View
|
||||
*/
|
||||
* Returns a view that displays the accessories report.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @return View
|
||||
*/
|
||||
public function getAccessoryReport()
|
||||
{
|
||||
$this->authorize('reports.view');
|
||||
|
@ -52,14 +54,14 @@ class ReportsController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Exports the accessories to CSV
|
||||
*
|
||||
* @deprecated Server-side exports have been replaced by datatables export since v2.
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ManufacturersController::getDatatable() method that generates the JSON response
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
* Exports the accessories to CSV
|
||||
*
|
||||
* @deprecated Server-side exports have been replaced by datatables export since v2.
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ManufacturersController::getDatatable() method that generates the JSON response
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function exportAccessoryReport()
|
||||
{
|
||||
$this->authorize('reports.view');
|
||||
|
@ -73,7 +75,7 @@ class ReportsController extends Controller
|
|||
trans('admin/accessories/general.remaining'),
|
||||
];
|
||||
$header = array_map('trim', $header);
|
||||
$rows[] = implode($header, ', ');
|
||||
$rows[] = implode(', ', $header);
|
||||
|
||||
// Row per accessory
|
||||
foreach ($accessories as $accessory) {
|
||||
|
@ -83,10 +85,10 @@ class ReportsController extends Controller
|
|||
$row[] = e($accessory->total);
|
||||
$row[] = e($accessory->remaining);
|
||||
|
||||
$rows[] = implode($row, ',');
|
||||
$rows[] = implode(',', $row);
|
||||
}
|
||||
|
||||
$csv = implode($rows, "\n");
|
||||
$csv = implode("\n", $rows);
|
||||
$response = Response::make($csv, 200);
|
||||
$response->header('Content-Type', 'text/csv');
|
||||
$response->header('Content-disposition', 'attachment;filename=report.csv');
|
||||
|
@ -95,31 +97,27 @@ class ReportsController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Show depreciation report for assets.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @return View
|
||||
*/
|
||||
* Show depreciation report for assets.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @return View
|
||||
*/
|
||||
public function getDeprecationReport()
|
||||
{
|
||||
$this->authorize('reports.view');
|
||||
$depreciations = Depreciation::get();
|
||||
// Grab all the assets
|
||||
$assets = Asset::with('assignedTo', 'assetstatus', 'defaultLoc', 'location', 'company', 'model.category', 'model.depreciation')
|
||||
->orderBy('created_at', 'DESC')->get();
|
||||
|
||||
return view('reports/depreciation', compact('assets'))->with('depreciations', $depreciations);
|
||||
return view('reports/depreciation')->with('depreciations',$depreciations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports the depreciations to CSV
|
||||
*
|
||||
* @deprecated Server-side exports have been replaced by datatables export since v2.
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
* Exports the depreciations to CSV
|
||||
*
|
||||
* @deprecated Server-side exports have been replaced by datatables export since v2.
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function exportDeprecationReport()
|
||||
{
|
||||
$this->authorize('reports.view');
|
||||
|
@ -190,6 +188,7 @@ class ReportsController extends Controller
|
|||
die;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Displays audit report.
|
||||
*
|
||||
|
@ -204,13 +203,14 @@ class ReportsController extends Controller
|
|||
return view('reports/audit');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Displays activity report.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @return View
|
||||
*/
|
||||
* Displays activity report.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @return View
|
||||
*/
|
||||
public function getActivityReport()
|
||||
{
|
||||
$this->authorize('reports.view');
|
||||
|
@ -259,22 +259,23 @@ class ReportsController extends Controller
|
|||
->orderBy('created_at', 'DESC')
|
||||
->chunk(20, function ($actionlogs) use ($handle) {
|
||||
$executionTime = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
|
||||
\Log::debug('Walking results: '.$executionTime);
|
||||
$count = 0;
|
||||
\Log::debug('Walking results: '.$executionTime);
|
||||
$count = 0;
|
||||
|
||||
foreach ($actionlogs as $actionlog) {
|
||||
$count++;
|
||||
$target_name = '';
|
||||
foreach ($actionlogs as $actionlog) {
|
||||
$count++;
|
||||
$target_name = '';
|
||||
|
||||
if ($actionlog->target) {
|
||||
if ($actionlog->target) {
|
||||
if ($actionlog->targetType() == 'user') {
|
||||
$target_name = $actionlog->target->getFullNameAttribute();
|
||||
} else {
|
||||
$target_name = $actionlog->target->getDisplayNameAttribute();
|
||||
}
|
||||
} else {
|
||||
$target_name = $actionlog->target->getDisplayNameAttribute();
|
||||
}
|
||||
}
|
||||
|
||||
$row = [
|
||||
|
||||
$row = [
|
||||
$actionlog->created_at,
|
||||
($actionlog->user) ? e($actionlog->user->getFullNameAttribute()) : '',
|
||||
$actionlog->present()->actionType(),
|
||||
|
@ -284,9 +285,9 @@ class ReportsController extends Controller
|
|||
($actionlog->note) ? e($actionlog->note) : '',
|
||||
$actionlog->log_meta,
|
||||
];
|
||||
fputcsv($handle, $row);
|
||||
}
|
||||
});
|
||||
fputcsv($handle, $row);
|
||||
}
|
||||
});
|
||||
|
||||
// Close the output stream
|
||||
fclose($handle);
|
||||
|
@ -297,9 +298,11 @@ class ReportsController extends Controller
|
|||
'Content-Disposition' => 'attachment; filename="activity-report-'.date('Y-m-d-his').'.csv"',
|
||||
]);
|
||||
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Displays license report
|
||||
*
|
||||
|
@ -318,13 +321,13 @@ class ReportsController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Exports the licenses to CSV
|
||||
*
|
||||
* @deprecated Server-side exports have been replaced by datatables export since v2.
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
* Exports the licenses to CSV
|
||||
*
|
||||
* @deprecated Server-side exports have been replaced by datatables export since v2.
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function exportLicenseReport()
|
||||
{
|
||||
$this->authorize('reports.view');
|
||||
|
@ -343,7 +346,7 @@ class ReportsController extends Controller
|
|||
];
|
||||
|
||||
$header = array_map('trim', $header);
|
||||
$rows[] = implode($header, ', ');
|
||||
$rows[] = implode(', ', $header);
|
||||
|
||||
// Row per license
|
||||
foreach ($licenses as $license) {
|
||||
|
@ -357,10 +360,11 @@ class ReportsController extends Controller
|
|||
$row[] = ($license->depreciation != '') ? '' : e($license->depreciation->name);
|
||||
$row[] = '"'.Helper::formatCurrencyOutput($license->purchase_cost).'"';
|
||||
|
||||
$rows[] = implode($row, ',');
|
||||
$rows[] = implode(',', $row);
|
||||
}
|
||||
|
||||
$csv = implode($rows, "\n");
|
||||
|
||||
$csv = implode("\n", $rows);
|
||||
$response = Response::make($csv, 200);
|
||||
$response->header('Content-Type', 'text/csv');
|
||||
$response->header('Content-disposition', 'attachment;filename=report.csv');
|
||||
|
@ -369,13 +373,13 @@ class ReportsController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a form that allows the user to generate a custom CSV report.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ReportsController::postCustomReport() method that generates the CSV
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
* Returns a form that allows the user to generate a custom CSV report.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ReportsController::postCustomReport() method that generates the CSV
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function getCustomReport()
|
||||
{
|
||||
$this->authorize('reports.view');
|
||||
|
@ -405,13 +409,14 @@ class ReportsController extends Controller
|
|||
// Open output stream
|
||||
$handle = fopen('php://output', 'w');
|
||||
stream_set_timeout($handle, 2000);
|
||||
|
||||
|
||||
if ($request->filled('use_bom')) {
|
||||
fprintf($handle, chr(0xEF).chr(0xBB).chr(0xBF));
|
||||
}
|
||||
|
||||
$header = [];
|
||||
|
||||
|
||||
if ($request->filled('company')) {
|
||||
$header[] = trans('general.company');
|
||||
}
|
||||
|
@ -475,7 +480,7 @@ class ReportsController extends Controller
|
|||
if ($request->filled('rtd_location')) {
|
||||
$header[] = trans('admin/hardware/form.default_location');
|
||||
}
|
||||
|
||||
|
||||
if ($request->filled('rtd_location_address')) {
|
||||
$header[] = trans('general.address');
|
||||
$header[] = trans('general.address');
|
||||
|
@ -485,6 +490,7 @@ class ReportsController extends Controller
|
|||
$header[] = trans('general.zip');
|
||||
}
|
||||
|
||||
|
||||
if ($request->filled('assigned_to')) {
|
||||
$header[] = trans('admin/hardware/table.checkoutto');
|
||||
$header[] = trans('general.type');
|
||||
|
@ -548,8 +554,9 @@ class ReportsController extends Controller
|
|||
$header[] = trans('general.notes');
|
||||
}
|
||||
|
||||
|
||||
foreach ($customfields as $customfield) {
|
||||
if (e($request->input($customfield->db_column_name())) == '1') {
|
||||
if ($request->input($customfield->db_column_name()) == '1') {
|
||||
$header[] = $customfield->name;
|
||||
}
|
||||
}
|
||||
|
@ -563,7 +570,7 @@ class ReportsController extends Controller
|
|||
$assets = \App\Models\Company::scopeCompanyables(Asset::select('assets.*'))->with(
|
||||
'location', 'assetstatus', 'assetlog', 'company', 'defaultLoc', 'assignedTo',
|
||||
'model.category', 'model.manufacturer', 'supplier');
|
||||
|
||||
|
||||
if ($request->filled('by_location_id')) {
|
||||
$assets->where('assets.location_id', $request->input('by_location_id'));
|
||||
}
|
||||
|
@ -625,15 +632,15 @@ class ReportsController extends Controller
|
|||
if (($request->filled('next_audit_start')) && ($request->filled('next_audit_end'))) {
|
||||
$assets->whereBetween('assets.next_audit_date', [$request->input('next_audit_start'), $request->input('next_audit_end')]);
|
||||
}
|
||||
|
||||
$assets->orderBy('assets.id', 'ASC')->chunk(20, function ($assets) use ($handle, $customfields, $request) {
|
||||
|
||||
$executionTime = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
|
||||
\Log::debug('Walking results: '.$executionTime);
|
||||
$count = 0;
|
||||
foreach ($assets as $asset) {
|
||||
$count++;
|
||||
$row = [];
|
||||
|
||||
|
||||
if ($request->filled('company')) {
|
||||
$row[] = ($asset->company) ? $asset->company->name : '';
|
||||
}
|
||||
|
@ -682,7 +689,7 @@ class ReportsController extends Controller
|
|||
if ($request->filled('supplier')) {
|
||||
$row[] = ($asset->supplier) ? $asset->supplier->name : '';
|
||||
}
|
||||
|
||||
|
||||
if ($request->filled('location')) {
|
||||
$row[] = ($asset->location) ? $asset->location->present()->name() : '';
|
||||
}
|
||||
|
@ -758,8 +765,8 @@ class ReportsController extends Controller
|
|||
}
|
||||
|
||||
if ($request->filled('depreciation')) {
|
||||
$depreciation = $asset->getDepreciatedValue();
|
||||
$diff = ($asset->purchase_cost - $depreciation);
|
||||
$depreciation = $asset->getDepreciatedValue();
|
||||
$diff = ($asset->purchase_cost - $depreciation);
|
||||
$row[] = Helper::formatCurrencyOutput($depreciation);
|
||||
$row[] = Helper::formatCurrencyOutput($diff);
|
||||
$row[] = ($asset->depreciation) ? $asset->depreciated_date()->format('Y-m-d') : '';
|
||||
|
@ -865,7 +872,7 @@ class ReportsController extends Controller
|
|||
];
|
||||
|
||||
$header = array_map('trim', $header);
|
||||
$rows[] = implode($header, ',');
|
||||
$rows[] = implode(',', $header);
|
||||
|
||||
foreach ($assetMaintenances as $assetMaintenance) {
|
||||
$row = [];
|
||||
|
@ -882,13 +889,13 @@ class ReportsController extends Controller
|
|||
} else {
|
||||
$improvementTime = intval($assetMaintenance->asset_maintenance_time);
|
||||
}
|
||||
$row[] = $improvementTime;
|
||||
$row[] = trans('general.currency').Helper::formatCurrencyOutput($assetMaintenance->cost);
|
||||
$rows[] = implode($row, ',');
|
||||
$row[] = $improvementTime;
|
||||
$row[] = trans('general.currency') . Helper::formatCurrencyOutput($assetMaintenance->cost);
|
||||
$rows[] = implode(',', $row);
|
||||
}
|
||||
|
||||
// spit out a csv
|
||||
$csv = implode($rows, "\n");
|
||||
$csv = implode("\n", $rows);
|
||||
$response = Response::make($csv, 200);
|
||||
$response->header('Content-Type', 'text/csv');
|
||||
$response->header('Content-disposition', 'attachment;filename=report.csv');
|
||||
|
@ -900,42 +907,124 @@ class ReportsController extends Controller
|
|||
* getAssetAcceptanceReport
|
||||
*
|
||||
* @return mixed
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @version v1.0
|
||||
*/
|
||||
public function getAssetAcceptanceReport()
|
||||
public function getAssetAcceptanceReport($deleted = false)
|
||||
{
|
||||
$this->authorize('reports.view');
|
||||
$showDeleted = $deleted == 'deleted';
|
||||
|
||||
/**
|
||||
* Get all assets with pending checkout acceptances
|
||||
*/
|
||||
$acceptances = CheckoutAcceptance::pending()->get();
|
||||
if($showDeleted) {
|
||||
$acceptances = CheckoutAcceptance::pending()->withTrashed()->with(['assignedTo' , 'checkoutable.assignedTo', 'checkoutable.model'])->get();
|
||||
} else {
|
||||
$acceptances = CheckoutAcceptance::pending()->with(['assignedTo' => function ($query) {
|
||||
$query->withTrashed();
|
||||
}, 'checkoutable.assignedTo', 'checkoutable.model'])->get();
|
||||
}
|
||||
|
||||
$assetsForReport = $acceptances
|
||||
->filter(function ($acceptance) {
|
||||
return $acceptance->checkoutable_type == \App\Models\Asset::class;
|
||||
})
|
||||
->map(function ($acceptance) {
|
||||
return $acceptance->checkoutable;
|
||||
->map(function($acceptance) {
|
||||
return ['assetItem' => $acceptance->checkoutable, 'acceptance' => $acceptance];
|
||||
});
|
||||
|
||||
return view('reports/unaccepted_assets', compact('assetsForReport'));
|
||||
return view('reports/unaccepted_assets', compact('assetsForReport','showDeleted' ));
|
||||
}
|
||||
|
||||
/**
|
||||
* exportAssetAcceptanceReport
|
||||
* sentAssetAcceptanceReminder
|
||||
*
|
||||
* @param integer|null $acceptanceId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @version v1.0
|
||||
*/
|
||||
public function sentAssetAcceptanceReminder($acceptanceId = null)
|
||||
{
|
||||
$this->authorize('reports.view');
|
||||
|
||||
if (!$acceptance = CheckoutAcceptance::pending()->find($acceptanceId)) {
|
||||
// Redirect to the unaccepted assets report page with error
|
||||
return redirect()->route('reports/unaccepted_assets')->with('error', trans('general.bad_data'));
|
||||
}
|
||||
$assetItem = $acceptance->checkoutable;
|
||||
|
||||
$logItem = $assetItem->checkouts()->where('created_at', '=', $acceptance->created_at)->get()[0];
|
||||
|
||||
if(!$assetItem->assignedTo->locale){
|
||||
Notification::locale(Setting::getSettings()->locale)->send(
|
||||
$assetItem->assignedTo,
|
||||
new CheckoutAssetNotification($assetItem, $assetItem->assignedTo, $logItem->user, $acceptance, $logItem->note)
|
||||
);
|
||||
} else {
|
||||
Notification::send(
|
||||
$assetItem->assignedTo,
|
||||
new CheckoutAssetNotification($assetItem, $assetItem->assignedTo, $logItem->user, $acceptance, $logItem->note)
|
||||
);
|
||||
}
|
||||
|
||||
return redirect()->route('reports/unaccepted_assets')->with('success', trans('admin/reports/general.reminder_sent'));
|
||||
}
|
||||
|
||||
/**
|
||||
* sentAssetAcceptanceReminder
|
||||
*
|
||||
* @param integer|null $acceptanceId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @version v1.0
|
||||
*/
|
||||
public function deleteAssetAcceptance($acceptanceId = null)
|
||||
{
|
||||
$this->authorize('reports.view');
|
||||
|
||||
if (!$acceptance = CheckoutAcceptance::pending()->find($acceptanceId)) {
|
||||
// Redirect to the unaccepted assets report page with error
|
||||
return redirect()->route('reports/unaccepted_assets')->with('error', trans('general.bad_data'));
|
||||
}
|
||||
|
||||
if($acceptance->delete()) {
|
||||
return redirect()->route('reports/unaccepted_assets')->with('success', trans('admin/reports/general.acceptance_deleted'));
|
||||
} else {
|
||||
return redirect()->route('reports/unaccepted_assets')->with('error', trans('general.deletion_failed'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports the AssetAcceptance report to CSV
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @version v1.0
|
||||
*/
|
||||
public function exportAssetAcceptanceReport()
|
||||
public function postAssetAcceptanceReport($deleted = false)
|
||||
{
|
||||
$this->authorize('reports.view');
|
||||
// Grab all the improvements
|
||||
$assetsForReport = Actionlog::whereIn('id', $this->getAssetsNotAcceptedYet())
|
||||
->get();
|
||||
$showDeleted = $deleted == 'deleted';
|
||||
|
||||
/**
|
||||
* Get all assets with pending checkout acceptances
|
||||
*/
|
||||
if($showDeleted) {
|
||||
$acceptances = CheckoutAcceptance::pending()->withTrashed()->with(['assignedTo', 'checkoutable.assignedTo', 'checkoutable.model'])->get();
|
||||
} else {
|
||||
$acceptances = CheckoutAcceptance::pending()->with(['assignedTo', 'checkoutable.assignedTo', 'checkoutable.model'])->get();
|
||||
}
|
||||
|
||||
$assetsForReport = $acceptances
|
||||
->filter(function($acceptance) {
|
||||
return $acceptance->checkoutable_type == 'App\Models\Asset';
|
||||
})
|
||||
->map(function($acceptance) {
|
||||
return ['assetItem' => $acceptance->checkoutable, 'acceptance' => $acceptance];
|
||||
});
|
||||
|
||||
$rows = [];
|
||||
|
||||
|
@ -948,20 +1037,20 @@ class ReportsController extends Controller
|
|||
];
|
||||
|
||||
$header = array_map('trim', $header);
|
||||
$rows[] = implode($header, ',');
|
||||
$rows[] = implode(',', $header);
|
||||
|
||||
foreach ($assetsForReport as $assetItem) {
|
||||
$row = [];
|
||||
$row[] = str_replace(',', '', e($assetItem->assetlog->model->category->name));
|
||||
$row[] = str_replace(',', '', e($assetItem->assetlog->model->name));
|
||||
$row[] = str_replace(',', '', e($assetItem->assetlog->present()->name()));
|
||||
$row[] = str_replace(',', '', e($assetItem->assetlog->asset_tag));
|
||||
$row[] = str_replace(',', '', e($assetItem->assetlog->assignedTo->present()->name()));
|
||||
$rows[] = implode($row, ',');
|
||||
foreach ($assetsForReport as $item) {
|
||||
$row = [ ];
|
||||
$row[] = str_replace(',', '', e($item['assetItem']->model->category->name));
|
||||
$row[] = str_replace(',', '', e($item['assetItem']->model->name));
|
||||
$row[] = str_replace(',', '', e($item['assetItem']->name));
|
||||
$row[] = str_replace(',', '', e($item['assetItem']->asset_tag));
|
||||
$row[] = str_replace(',', '', e(($item['acceptance']->assignedTo) ? $item['acceptance']->assignedTo->present()->name() : trans('admin/reports/general.deleted_user')));
|
||||
$rows[] = implode(',', $row);
|
||||
}
|
||||
|
||||
// spit out a csv
|
||||
$csv = implode($rows, "\n");
|
||||
$csv = implode("\n", $rows);
|
||||
$response = Response::make($csv, 200);
|
||||
$response->header('Content-Type', 'text/csv');
|
||||
$response->header('Content-disposition', 'attachment;filename=report.csv');
|
||||
|
|
|
@ -360,6 +360,7 @@ class SettingsController extends Controller
|
|||
return redirect()->back()->withInput()->withErrors($setting->getErrors());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a form to allow a super admin to update settings.
|
||||
*
|
||||
|
@ -411,14 +412,15 @@ class SettingsController extends Controller
|
|||
$setting = $request->handleImages($setting, 600, 'logo', '', 'logo');
|
||||
|
||||
if ('1' == $request->input('clear_logo')) {
|
||||
Storage::disk('public')->delete($setting->logo);
|
||||
Storage::disk('public')->delete($setting->logo);
|
||||
$setting->logo = null;
|
||||
$setting->brand = 1;
|
||||
$setting->brand = 1;
|
||||
}
|
||||
|
||||
$setting = $request->handleImages($setting, 600, 'email_logo', '', 'email_logo');
|
||||
|
||||
if ('1' == $request->input('clear_email_logo')) {
|
||||
|
||||
if ('1' == $request->input('clear_email_logo')) {
|
||||
Storage::disk('public')->delete($setting->email_logo);
|
||||
$setting->email_logo = null;
|
||||
// If they are uploading an image, validate it and upload it
|
||||
|
@ -431,8 +433,9 @@ class SettingsController extends Controller
|
|||
$setting->label_logo = null;
|
||||
}
|
||||
|
||||
|
||||
// If the user wants to clear the favicon...
|
||||
if ($request->hasFile('favicon')) {
|
||||
if ($request->hasFile('favicon')) {
|
||||
$favicon_image = $favicon_upload = $request->file('favicon');
|
||||
$favicon_ext = $favicon_image->getClientOriginalExtension();
|
||||
$setting->favicon = $favicon_file_name = 'favicon-uploaded.'.$favicon_ext;
|
||||
|
@ -449,16 +452,17 @@ class SettingsController extends Controller
|
|||
Storage::disk('public')->put($favicon_file_name, file_get_contents($request->file('favicon')));
|
||||
}
|
||||
|
||||
|
||||
// Remove Current image if exists
|
||||
if (($setting->favicon) && (file_exists($favicon_file_name))) {
|
||||
Storage::disk('public')->delete($favicon_file_name);
|
||||
}
|
||||
} elseif ('1' == $request->input('clear_favicon')) {
|
||||
Storage::disk('public')->delete($setting->clear_favicon);
|
||||
Storage::disk('public')->delete($setting->clear_favicon);
|
||||
$setting->favicon = null;
|
||||
|
||||
// If they are uploading an image, validate it and upload it
|
||||
}
|
||||
// If they are uploading an image, validate it and upload it
|
||||
}
|
||||
|
||||
if ($setting->save()) {
|
||||
return redirect()->route('settings.index')
|
||||
|
@ -516,6 +520,7 @@ class SettingsController extends Controller
|
|||
$setting->pwd_secure_min = (int) $request->input('pwd_secure_min');
|
||||
$setting->pwd_secure_complexity = '';
|
||||
|
||||
|
||||
if ($request->filled('pwd_secure_complexity')) {
|
||||
$setting->pwd_secure_complexity = implode('|', $request->input('pwd_secure_complexity'));
|
||||
}
|
||||
|
@ -928,9 +933,14 @@ class SettingsController extends Controller
|
|||
$setting->ldap_jobtitle = $request->input('ldap_jobtitle');
|
||||
$setting->ldap_country = $request->input('ldap_country');
|
||||
$setting->ldap_dept = $request->input('ldap_dept');
|
||||
$setting->ldap_client_tls_cert = $request->input('ldap_client_tls_cert');
|
||||
$setting->ldap_client_tls_key = $request->input('ldap_client_tls_key');
|
||||
|
||||
|
||||
}
|
||||
|
||||
if ($setting->save()) {
|
||||
$setting->update_client_side_cert_files();
|
||||
return redirect()->route('settings.ldap.index')
|
||||
->with('success', trans('admin/settings/message.update.success'));
|
||||
}
|
||||
|
|
|
@ -33,7 +33,8 @@ class BulkUsersController extends Controller
|
|||
// Make sure there were users selected
|
||||
if (($request->filled('ids')) && (count($request->input('ids')) > 0)) {
|
||||
// Get the list of affected users
|
||||
$users = User::whereIn('id', array_keys(request('ids')))
|
||||
$user_raw_array = request('ids');
|
||||
$users = User::whereIn('id', $user_raw_array)
|
||||
->with('groups', 'assets', 'licenses', 'accessories')->get();
|
||||
|
||||
if ($request->input('bulk_actions') == 'edit') {
|
||||
|
|
|
@ -10,6 +10,8 @@ use Illuminate\Support\Facades\Auth;
|
|||
use Illuminate\Support\Facades\Input;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use enshrined\svgSanitize\Sanitizer;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class UserFilesController extends Controller
|
||||
{
|
||||
|
@ -38,12 +40,32 @@ class UserFilesController extends Controller
|
|||
return redirect()->back()->with('error', trans('admin/users/message.upload.nofiles'));
|
||||
}
|
||||
foreach ($files as $file) {
|
||||
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$filename = 'user-'.$user->id.'-'.str_random(8);
|
||||
$filename .= '-'.str_slug($file->getClientOriginalName()).'.'.$extension;
|
||||
if (! $file->move($destinationPath, $filename)) {
|
||||
return redirect()->back()->with('error', trans('admin/users/message.upload.invalidfiles'));
|
||||
$file_name = 'user-'.$user->id.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
|
||||
|
||||
|
||||
// Check for SVG and sanitize it
|
||||
if ($extension == 'svg') {
|
||||
\Log::debug('This is an SVG');
|
||||
\Log::debug($file_name);
|
||||
|
||||
$sanitizer = new Sanitizer();
|
||||
|
||||
$dirtySVG = file_get_contents($file->getRealPath());
|
||||
$cleanSVG = $sanitizer->sanitize($dirtySVG);
|
||||
|
||||
try {
|
||||
Storage::put('private_uploads/users/'.$file_name, $cleanSVG);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Upload no workie :( ');
|
||||
\Log::debug($e);
|
||||
}
|
||||
|
||||
} else {
|
||||
Storage::put('private_uploads/users/'.$file_name, file_get_contents($file));
|
||||
}
|
||||
|
||||
//Log the uploaded file to the log
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_id = $user->id;
|
||||
|
@ -51,8 +73,8 @@ class UserFilesController extends Controller
|
|||
$logAction->user_id = Auth::id();
|
||||
$logAction->note = $request->input('notes');
|
||||
$logAction->target_id = null;
|
||||
$logAction->created_at = date('Y-m-d H:i:s');
|
||||
$logAction->filename = $filename;
|
||||
$logAction->created_at = date("Y-m-d H:i:s");
|
||||
$logAction->filename = $file_name;
|
||||
$logAction->action_type = 'uploaded';
|
||||
|
||||
if (! $logAction->save()) {
|
||||
|
@ -63,8 +85,9 @@ class UserFilesController extends Controller
|
|||
// dd($logActions);
|
||||
return redirect()->back()->with('success', trans('admin/users/message.upload.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->with('error', trans('admin/users/message.upload.nofiles'));
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -97,6 +120,7 @@ class UserFilesController extends Controller
|
|||
$error = trans('admin/users/message.user_not_found', ['id' => $userId]);
|
||||
// Redirect to the licence management page
|
||||
return redirect()->route('users.index')->with('error', $error);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -128,4 +152,5 @@ class UserFilesController extends Controller
|
|||
// Redirect to the licence management page
|
||||
return redirect()->route('users.index')->with('error', $error);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ class Kernel extends HttpKernel
|
|||
\App\Http\Middleware\CheckForDebug::class,
|
||||
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
|
||||
\App\Http\Middleware\SecurityHeaders::class,
|
||||
\App\Http\Middleware\PreventBackHistory::class,
|
||||
|
||||
];
|
||||
|
||||
|
|
|
@ -15,27 +15,21 @@ class CustomFieldSetDefaultValuesForModel extends Component
|
|||
public $fields;
|
||||
public $model_id;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
\Log::info("INSTANTIATING A THING!!!"); // WORKS!
|
||||
}
|
||||
|
||||
public function foo()
|
||||
{
|
||||
\Log::info("Uh, foo?");
|
||||
}
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->fieldset_id = AssetModel::find($this->model_id)->fieldset_id;
|
||||
\Log::error("Mount at least fired, that's got to count for something, yeah?"); //WORKS! YAY!
|
||||
$this->model = AssetModel::find($this->model_id); // It's possible to do some clever route-model binding here, but let's keep it simple, shall we?
|
||||
$this->fieldset_id = $this->model->fieldset_id;
|
||||
$this->fields = CustomFieldset::find($this->fieldset_id)->fields;
|
||||
$this->add_default_values = ( $this->model->defaultValues->count() > 0);
|
||||
}
|
||||
|
||||
public function updatedFieldsetId()
|
||||
{
|
||||
$this->fields = CustomFieldset::find($this->fieldset_id)->fields;
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
// return 'fart<div>Hi: {{ $this->add_default_values }} yeah?</div>';
|
||||
return view('livewire.custom-field-set-default-values-for-model');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Livewire;
|
||||
|
||||
use Livewire\Component;
|
||||
|
||||
use App\Models\CustomFieldset;
|
||||
|
||||
class CustomFieldsForFieldset extends Component
|
||||
{
|
||||
public $fieldset_id;
|
||||
public $fields;
|
||||
|
||||
public function render()
|
||||
{
|
||||
if($this->fieldset_id) {
|
||||
$this->fields = CustomFieldset::find($this->fieldset_id)->fields()->get();
|
||||
}
|
||||
return view('livewire.custom-fields-for-fieldset');
|
||||
}
|
||||
}
|
30
app/Http/Middleware/PreventBackHistory.php
Normal file
30
app/Http/Middleware/PreventBackHistory.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
|
||||
class PreventBackHistory
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
$headers = [
|
||||
'Cache-Control' => 'no-cache, no-store, max-age=0, must-revalidate',
|
||||
'Pragma' => 'no-cache',
|
||||
'Expires' => 'Sun, 02 Jan 1990 00:00:00 GMT'
|
||||
];
|
||||
$response = $next($request);
|
||||
foreach($headers as $key => $value) {
|
||||
$response->headers->set($key, $value);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@ class AssetFileRequest extends Request
|
|||
*/
|
||||
public function rules()
|
||||
{
|
||||
$max_file_size = \App\Helpers\Helper::file_upload_max_size();
|
||||
$max_file_size = Helper::file_upload_max_size();
|
||||
|
||||
return [
|
||||
'file.*' => 'required|mimes:png,gif,jpg,svg,jpeg,doc,docx,pdf,txt,zip,rar,xls,xlsx,lic,xml,rtf,webp|max:'.$max_file_size,
|
||||
|
|
|
@ -123,7 +123,7 @@ class ImageUploadRequest extends Request
|
|||
$upload = Image::make($image->getRealPath())->resize(null, $w, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
});
|
||||
});
|
||||
|
||||
// This requires a string instead of an object, so we use ($string)
|
||||
Storage::disk('public')->put($path.'/'.$file_name, (string) $upload->encode());
|
||||
|
@ -150,12 +150,12 @@ class ImageUploadRequest extends Request
|
|||
}
|
||||
}
|
||||
|
||||
// Remove Current image if exists
|
||||
// Remove Current image if exists
|
||||
if (Storage::disk('public')->exists($path.'/'.$item->{$use_db_field})) {
|
||||
\Log::debug('A file already exists that we are replacing - we should delete the old one.');
|
||||
try {
|
||||
Storage::disk('public')->delete($path.'/'.$item->{$use_db_field});
|
||||
\Log::debug('Old file '.$path.'/'.$file_name.' has been deleted.');
|
||||
Storage::disk('public')->delete($path.'/'.$item->{$use_db_field});
|
||||
\Log::debug('Old file '.$path.'/'.$file_name.' has been deleted.');
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Could not delete old file. '.$path.'/'.$file_name.' does not exist?');
|
||||
}
|
||||
|
@ -164,14 +164,14 @@ class ImageUploadRequest extends Request
|
|||
$item->{$use_db_field} = $file_name;
|
||||
}
|
||||
|
||||
// If the user isn't uploading anything new but wants to delete their old image, do so
|
||||
// If the user isn't uploading anything new but wants to delete their old image, do so
|
||||
} else {
|
||||
\Log::debug('No file passed for '.$form_fieldname);
|
||||
if ($this->input('image_delete') == '1') {
|
||||
\Log::debug('Deleting image');
|
||||
try {
|
||||
Storage::disk('public')->delete($path.'/'.$item->{$use_db_field});
|
||||
$item->{$use_db_field} = null;
|
||||
$item->{$use_db_field} = null;
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
|
|
25
app/Http/Traits/TwoColumnUniqueUndeletedTrait.php
Normal file
25
app/Http/Traits/TwoColumnUniqueUndeletedTrait.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Traits;
|
||||
|
||||
trait TwoColumnUniqueUndeletedTrait
|
||||
{
|
||||
/**
|
||||
* Prepare a unique_ids rule, adding a model identifier if required.
|
||||
*
|
||||
* @param array $parameters
|
||||
* @param string $field
|
||||
* @return string
|
||||
*/
|
||||
protected function prepareTwoColumnUniqueUndeletedRule($parameters, $field)
|
||||
{
|
||||
$column = $parameters[0];
|
||||
$value = $this->{$parameters[0]};
|
||||
|
||||
if ($this->exists) {
|
||||
return 'two_column_unique_undeleted:'.$this->table.','.$this->getKey().','.$column.','.$value;
|
||||
}
|
||||
|
||||
return 'two_column_unique_undeleted:'.$this->table.',0,'.$column.','.$value;
|
||||
}
|
||||
}
|
|
@ -24,7 +24,7 @@ class ActionlogsTransformer
|
|||
{
|
||||
$icon = $actionlog->present()->icon();
|
||||
if ($actionlog->filename != '') {
|
||||
$icon = e(\App\Helpers\Helper::filetype_icon($actionlog->filename));
|
||||
$icon = e(Helper::filetype_icon($actionlog->filename));
|
||||
}
|
||||
|
||||
// This is necessary since we can't escape special characters within a JSON object
|
||||
|
@ -68,14 +68,14 @@ class ActionlogsTransformer
|
|||
}
|
||||
}
|
||||
|
||||
$array = [
|
||||
$array = [
|
||||
'id' => (int) $actionlog->id,
|
||||
'icon' => $icon,
|
||||
'file' => ($actionlog->filename != '') ?
|
||||
[
|
||||
'url' => route('show/assetfile', ['assetId' => $actionlog->item->id, 'fileId' => $actionlog->id]),
|
||||
'filename' => $actionlog->filename,
|
||||
'inlineable' => (bool) \App\Helpers\Helper::show_file_inline($actionlog->filename),
|
||||
'inlineable' => (bool) Helper::show_file_inline($actionlog->filename),
|
||||
] : null,
|
||||
|
||||
'item' => ($actionlog->item) ? [
|
||||
|
@ -104,10 +104,10 @@ class ActionlogsTransformer
|
|||
'type' => e($actionlog->targetType()),
|
||||
] : null,
|
||||
|
||||
'note' => ($actionlog->note) ? e($actionlog->note) : null,
|
||||
'signature_file' => ($actionlog->accept_signature) ? route('log.signature.view', ['filename' => $actionlog->accept_signature]) : null,
|
||||
'log_meta' => ((isset($clean_meta)) && (is_array($clean_meta))) ? $clean_meta : null,
|
||||
'action_date' => ($actionlog->action_date) ? Helper::getFormattedDateObject($actionlog->action_date, 'datetime') : null,
|
||||
'note' => ($actionlog->note) ? e($actionlog->note): null,
|
||||
'signature_file' => ($actionlog->accept_signature) ? route('log.signature.view', ['filename' => $actionlog->accept_signature ]) : null,
|
||||
'log_meta' => ((isset($clean_meta)) && (is_array($clean_meta))) ? $clean_meta: null,
|
||||
'action_date' => ($actionlog->action_date) ? Helper::getFormattedDateObject($actionlog->action_date, 'datetime'): Helper::getFormattedDateObject($actionlog->created_at, 'datetime'),
|
||||
|
||||
];
|
||||
|
||||
|
|
|
@ -83,12 +83,13 @@ class AssetsTransformer
|
|||
'user_can_checkout' => (bool) $asset->availableForCheckout(),
|
||||
];
|
||||
|
||||
|
||||
if (($asset->model) && ($asset->model->fieldset) && ($asset->model->fieldset->fields->count() > 0)) {
|
||||
$fields_array = [];
|
||||
|
||||
foreach ($asset->model->fieldset->fields as $field) {
|
||||
if ($field->isFieldDecryptable($asset->{$field->convertUnicodeDbSlug()})) {
|
||||
$decrypted = \App\Helpers\Helper::gracefulDecrypt($field, $asset->{$field->convertUnicodeDbSlug()});
|
||||
$decrypted = Helper::gracefulDecrypt($field, $asset->{$field->convertUnicodeDbSlug()});
|
||||
$value = (Gate::allows('superadmin')) ? $decrypted : strtoupper(trans('admin/custom_fields/general.encrypted'));
|
||||
|
||||
$fields_array[$field->name] = [
|
||||
|
@ -96,12 +97,15 @@ class AssetsTransformer
|
|||
'value' => $value,
|
||||
'field_format' => $field->format,
|
||||
];
|
||||
|
||||
} else {
|
||||
$fields_array[$field->name] = [
|
||||
'field' => $field->convertUnicodeDbSlug(),
|
||||
'value' => $asset->{$field->convertUnicodeDbSlug()},
|
||||
'field_format' => $field->format,
|
||||
];
|
||||
|
||||
|
||||
}
|
||||
$array['custom_fields'] = $fields_array;
|
||||
}
|
||||
|
@ -112,7 +116,7 @@ class AssetsTransformer
|
|||
$permissions_array['available_actions'] = [
|
||||
'checkout' => Gate::allows('checkout', Asset::class),
|
||||
'checkin' => Gate::allows('checkin', Asset::class),
|
||||
'clone' => Gate::allows('create', Asset::class),
|
||||
'clone' => false,
|
||||
'restore' => false,
|
||||
'update' => (bool) Gate::allows('update', Asset::class),
|
||||
'delete' => ($asset->assigned_to == '' && Gate::allows('delete', Asset::class)),
|
||||
|
@ -129,6 +133,29 @@ class AssetsTransformer
|
|||
];
|
||||
}
|
||||
|
||||
|
||||
if (request('components')=='true') {
|
||||
|
||||
if ($asset->components) {
|
||||
$array['components'] = [];
|
||||
|
||||
foreach ($asset->components as $component) {
|
||||
$array['components'][] = [
|
||||
|
||||
'id' => $component->id,
|
||||
'pivot_id' => $component->pivot->id,
|
||||
'name' => $component->name,
|
||||
'qty' => $component->pivot->assigned_qty,
|
||||
'price_cost' => $component->purchase_cost,
|
||||
'purchase_total' => $component->purchase_cost * $component->pivot->assigned_qty,
|
||||
'checkout_date' => Helper::getFormattedDateObject($component->pivot->created_at, 'datetime') ,
|
||||
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$array += $permissions_array;
|
||||
|
||||
return $array;
|
||||
|
@ -160,6 +187,7 @@ class AssetsTransformer
|
|||
] : null;
|
||||
}
|
||||
|
||||
|
||||
public function transformRequestedAssets(Collection $assets, $total)
|
||||
{
|
||||
$array = [];
|
||||
|
@ -192,7 +220,8 @@ class AssetsTransformer
|
|||
];
|
||||
|
||||
$array += $permissions_array;
|
||||
|
||||
return $array;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ class CategoriesTransformer
|
|||
'image' => ($category->image) ? Storage::disk('public')->url('categories/'.e($category->image)) : null,
|
||||
'category_type' => ucwords(e($category->category_type)),
|
||||
'has_eula' => ($category->getEula() ? true : false),
|
||||
'use_default_eula' => ($category->use_default_eula=='1' ? true : false),
|
||||
'eula' => ($category->getEula()),
|
||||
'checkin_email' => ($category->checkin_email == '1'),
|
||||
'require_acceptance' => ($category->require_acceptance == '1'),
|
||||
|
|
120
app/Http/Transformers/DepreciationReportTransformer.php
Normal file
120
app/Http/Transformers/DepreciationReportTransformer.php
Normal file
|
@ -0,0 +1,120 @@
|
|||
<?php
|
||||
namespace App\Http\Transformers;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Asset;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
/**
|
||||
* This tranformer looks like it's extraneous, since we return as much or more
|
||||
* info in the AssetsTransformer, but we want to flatten these results out so that they
|
||||
* don't dislose more information than we want. Folks with depreciation powers don't necessaily
|
||||
* have the right to see additional info, and inspecting the API call here could disclose
|
||||
* info they're not supposed to see.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v5.2.0]
|
||||
*/
|
||||
class DepreciationReportTransformer
|
||||
{
|
||||
public function transformAssets(Collection $assets, $total)
|
||||
{
|
||||
$array = array();
|
||||
foreach ($assets as $asset) {
|
||||
$array[] = self::transformAsset($asset);
|
||||
}
|
||||
return (new DatatablesTransformer)->transformDatatables($array, $total);
|
||||
}
|
||||
|
||||
|
||||
public function transformAsset(Asset $asset)
|
||||
{
|
||||
|
||||
/**
|
||||
* Set some default values here
|
||||
*/
|
||||
$purchase_cost = null;
|
||||
$depreciated_value = null;
|
||||
$monthly_depreciation = null;
|
||||
$diff = null;
|
||||
$checkout_target = null;
|
||||
|
||||
/**
|
||||
* If there is a location set and a currency set, use that for display
|
||||
*/
|
||||
if ($asset->location && $asset->location->currency) {
|
||||
$purchase_cost_currency = $asset->location->currency;
|
||||
} else {
|
||||
$purchase_cost_currency = \App\Models\Setting::getSettings()->default_currency;
|
||||
}
|
||||
|
||||
/**
|
||||
* If there is a NOT an empty purchase cost (meaning not null or '' but it *could* be zero),
|
||||
* format the purchase cost. We coould do this inline in the transformer, but we need that value
|
||||
* for the other calculations that come after, like diff, etc.
|
||||
*/
|
||||
if ($asset->purchase_cost!='') {
|
||||
$purchase_cost = $asset->purchase_cost;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Override the previously set null values if there is a valid model and associated depreciation
|
||||
*/
|
||||
if (($asset->model) && ($asset->model->depreciation)) {
|
||||
$depreciated_value = Helper::formatCurrencyOutput($asset->getDepreciatedValue());
|
||||
$monthly_depreciation = Helper::formatCurrencyOutput(($asset->model->eol > 0 ? ($asset->purchase_cost / $asset->model->eol) : 0));
|
||||
$diff = Helper::formatCurrencyOutput(($asset->purchase_cost - $asset->getDepreciatedValue()));
|
||||
}
|
||||
|
||||
if ($asset->assigned) {
|
||||
$checkout_target = $asset->assigned->name;
|
||||
if ($asset->checkedOutToUser()) {
|
||||
$checkout_target = $asset->assigned->getFullNameAttribute();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$array = [
|
||||
|
||||
'company' => ($asset->company) ? e($asset->company->name) : null,
|
||||
'name' => e($asset->name),
|
||||
'asset_tag' => e($asset->asset_tag),
|
||||
'serial' => e($asset->serial),
|
||||
'model' => ($asset->model) ? e($asset->model->name) : null,
|
||||
'model_number' => (($asset->model) && ($asset->model->model_number)) ? e($asset->model->model_number) : null,
|
||||
'eol' => ($asset->purchase_date!='') ? Helper::getFormattedDateObject($asset->present()->eol_date(), 'date') : null ,
|
||||
'status_label' => ($asset->assetstatus) ? e($asset->assetstatus->name) : null,
|
||||
'status' => ($asset->assetstatus) ? e($asset->present()->statusMeta) : null,
|
||||
'category' => (($asset->model) && ($asset->model->category)) ? e($asset->model->category->name) : null,
|
||||
'manufacturer' => (($asset->model) && ($asset->model->manufacturer)) ? e($asset->model->manufacturer->name) : null,
|
||||
'supplier' => ($asset->supplier) ? e($asset->supplier->name) : null,
|
||||
'notes' => ($asset->notes) ? e($asset->notes) : null,
|
||||
'order_number' => ($asset->order_number) ? e($asset->order_number) : null,
|
||||
'location' => ($asset->location) ? e($asset->location->name) : null,
|
||||
'warranty_expires' => ($asset->warranty_months > 0) ? Helper::getFormattedDateObject($asset->warranty_expires, 'date') : null,
|
||||
'currency' => $purchase_cost_currency,
|
||||
'purchase_date' => Helper::getFormattedDateObject($asset->purchase_date, 'date'),
|
||||
'purchase_cost' => Helper::formatCurrencyOutput($asset->purchase_cost),
|
||||
'book_value' => Helper::formatCurrencyOutput($depreciated_value),
|
||||
'monthly_depreciation' => $monthly_depreciation,
|
||||
'checked_out_to' => $checkout_target,
|
||||
'diff' => Helper::formatCurrencyOutput($diff),
|
||||
'number_of_months' => ($asset->model && $asset->model->depreciation) ? e($asset->model->depreciation->months) : null,
|
||||
'depreciation' => (($asset->model) && ($asset->model->depreciation)) ? e($asset->model->depreciation->name) : null,
|
||||
|
||||
|
||||
|
||||
];
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
public function transformAssetsDatatable($assets)
|
||||
{
|
||||
return (new DatatablesTransformer)->transformDatatables($assets);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -25,6 +25,7 @@ class DepreciationsTransformer
|
|||
'id' => (int) $depreciation->id,
|
||||
'name' => e($depreciation->name),
|
||||
'months' => $depreciation->months.' '.trans('general.months'),
|
||||
'depreciation_min' => $depreciation->depreciation_min,
|
||||
'created_at' => Helper::getFormattedDateObject($depreciation->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($depreciation->updated_at, 'datetime'),
|
||||
'depreciation_min' =>($depreciation->depreciation_min),
|
||||
|
|
|
@ -31,8 +31,9 @@ class LicensesTransformer
|
|||
'purchase_order' => e($license->purchase_order),
|
||||
'purchase_date' => Helper::getFormattedDateObject($license->purchase_date, 'date'),
|
||||
'termination_date' => Helper::getFormattedDateObject($license->termination_date, 'date'),
|
||||
'depreciation' => ($license->depreciation) ? ['id' => (int) $license->depreciation->id, 'name'=> e($license->depreciation->name)] : null,
|
||||
'purchase_cost' => e($license->purchase_cost),
|
||||
'depreciation' => ($license->depreciation) ? ['id' => (int) $license->depreciation->id,'name'=> e($license->depreciation->name)] : null,
|
||||
'purchase_cost' => Helper::formatCurrencyOutput($license->purchase_cost),
|
||||
'purchase_cost_numeric' => $license->purchase_cost,
|
||||
'notes' => e($license->notes),
|
||||
'expiration_date' => Helper::getFormattedDateObject($license->expiration_date, 'date'),
|
||||
'seats' => (int) $license->seats,
|
||||
|
@ -65,4 +66,7 @@ class LicensesTransformer
|
|||
{
|
||||
return (new DatatablesTransformer)->transformDatatables($licenses);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ class AccessoryImporter extends ItemImporter
|
|||
protected function handle($row)
|
||||
{
|
||||
parent::handle($row); // TODO: Change the autogenerated stub
|
||||
$this->createAccessoryIfNotExists();
|
||||
$this->createAccessoryIfNotExists($row);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -23,7 +23,7 @@ class AccessoryImporter extends ItemImporter
|
|||
* @author Daniel Melzter
|
||||
* @since 3.0
|
||||
*/
|
||||
public function createAccessoryIfNotExists()
|
||||
public function createAccessoryIfNotExists($row)
|
||||
{
|
||||
$accessory = Accessory::where('name', $this->item['name'])->first();
|
||||
if ($accessory) {
|
||||
|
@ -34,6 +34,7 @@ class AccessoryImporter extends ItemImporter
|
|||
}
|
||||
|
||||
$this->log('Updating Accessory');
|
||||
$this->item['model_number'] = $this->findCsvMatch($row, "model_number");
|
||||
$accessory->update($this->sanitizeItemForUpdating($accessory));
|
||||
$accessory->save();
|
||||
|
||||
|
@ -41,6 +42,7 @@ class AccessoryImporter extends ItemImporter
|
|||
}
|
||||
$this->log('No Matching Accessory, Creating a new one');
|
||||
$accessory = new Accessory();
|
||||
$this->item['model_number'] = $this->findCsvMatch($row, "model_number");
|
||||
$accessory->fill($this->sanitizeItemForStoring($accessory));
|
||||
|
||||
//FIXME: this disables model validation. Need to find a way to avoid double-logs without breaking everything.
|
||||
|
|
|
@ -101,7 +101,7 @@ class ItemImporter extends Importer
|
|||
return $this->createOrFetchUser($row);
|
||||
}
|
||||
|
||||
if ($this->item['checkout_class'] === 'location') {
|
||||
if (strtolower($this->item['checkout_class']) === 'location') {
|
||||
return Location::findOrFail($this->createOrFetchLocation($this->findCsvMatch($row, 'checkout_location')));
|
||||
}
|
||||
|
||||
|
|
|
@ -74,6 +74,7 @@ class UserImporter extends ItemImporter
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
// This needs to be applied after the update logic, otherwise we'll overwrite user passwords
|
||||
// Issue #5408
|
||||
$this->item['password'] = bcrypt($this->tempPassword);
|
||||
|
@ -106,6 +107,7 @@ class UserImporter extends ItemImporter
|
|||
}
|
||||
|
||||
$this->logError($user, 'User');
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -118,13 +120,15 @@ class UserImporter extends ItemImporter
|
|||
*/
|
||||
public function createOrFetchDepartment($department_name)
|
||||
{
|
||||
if (is_null($department_name) || $department_name == ''){
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
$department = Department::where(['name' => $department_name])->first();
|
||||
if ($department) {
|
||||
$this->log('A matching department '.$department_name.' already exists');
|
||||
|
||||
$this->log('A matching department ' . $department_name . ' already exists');
|
||||
return $department->id;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
$department = new department();
|
||||
|
@ -132,15 +136,14 @@ class UserImporter extends ItemImporter
|
|||
$department->user_id = $this->user_id;
|
||||
|
||||
if ($department->save()) {
|
||||
$this->log('department '.$department_name.' was created');
|
||||
|
||||
$this->log('department ' . $department_name . ' was created');
|
||||
return $department->id;
|
||||
}
|
||||
|
||||
$this->logError($department, 'Department');
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public function sendWelcome($send = true)
|
||||
{
|
||||
|
|
|
@ -38,16 +38,16 @@ class CheckoutableListener
|
|||
/**
|
||||
* Make a checkout acceptance and attach it in the notification
|
||||
*/
|
||||
$acceptance = $this->getCheckoutAcceptance($event);
|
||||
$acceptance = $this->getCheckoutAcceptance($event);
|
||||
|
||||
if (! $event->checkedOutTo->locale) {
|
||||
Notification::locale(Setting::getSettings()->locale)->send(
|
||||
$this->getNotifiables($event),
|
||||
$this->getNotifiables($event),
|
||||
$this->getCheckoutNotification($event, $acceptance)
|
||||
);
|
||||
} else {
|
||||
Notification::send(
|
||||
$this->getNotifiables($event),
|
||||
$this->getNotifiables($event),
|
||||
$this->getCheckoutNotification($event, $acceptance)
|
||||
);
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ class CheckoutableListener
|
|||
|
||||
/**
|
||||
* Notify the user about the checked in checkoutable
|
||||
*/
|
||||
*/
|
||||
public function onCheckedIn($event)
|
||||
{
|
||||
\Log::debug('checkin fired');
|
||||
|
@ -72,6 +72,15 @@ class CheckoutableListener
|
|||
/**
|
||||
* Send the appropriate notification
|
||||
*/
|
||||
$acceptances = CheckoutAcceptance::where('checkoutable_id', $event->checkoutable->id)
|
||||
->where('assigned_to_id', $event->checkedOutTo->id)
|
||||
->get();
|
||||
|
||||
foreach($acceptances as $acceptance){
|
||||
if($acceptance->isPending()){
|
||||
$acceptance->delete();
|
||||
}
|
||||
}
|
||||
\Log::debug('checked out to a user');
|
||||
if (! $event->checkedOutTo->locale) {
|
||||
\Log::debug('Use default settings locale');
|
||||
|
@ -87,7 +96,7 @@ class CheckoutableListener
|
|||
$this->getCheckinNotification($event)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a checkout acceptance
|
||||
|
@ -105,12 +114,12 @@ class CheckoutableListener
|
|||
$acceptance->assignedTo()->associate($event->checkedOutTo);
|
||||
$acceptance->save();
|
||||
|
||||
return $acceptance;
|
||||
return $acceptance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the entities to be notified of the passed event
|
||||
*
|
||||
*
|
||||
* @param Event $event
|
||||
* @return Collection
|
||||
*/
|
||||
|
@ -130,13 +139,13 @@ class CheckoutableListener
|
|||
$notifiables->push(new AdminRecipient());
|
||||
}
|
||||
|
||||
return $notifiables;
|
||||
return $notifiables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the appropriate notification for the event
|
||||
*
|
||||
* @param CheckoutableCheckedIn $event
|
||||
*
|
||||
* @param CheckoutableCheckedIn $event
|
||||
* @return Notification
|
||||
*/
|
||||
private function getCheckinNotification($event)
|
||||
|
@ -144,6 +153,8 @@ class CheckoutableListener
|
|||
|
||||
// $model = get_class($event->checkoutable);
|
||||
|
||||
|
||||
|
||||
$notificationClass = null;
|
||||
|
||||
switch (get_class($event->checkoutable)) {
|
||||
|
@ -152,7 +163,7 @@ class CheckoutableListener
|
|||
break;
|
||||
case Asset::class:
|
||||
$notificationClass = CheckinAssetNotification::class;
|
||||
break;
|
||||
break;
|
||||
case LicenseSeat::class:
|
||||
$notificationClass = CheckinLicenseSeatNotification::class;
|
||||
break;
|
||||
|
@ -160,14 +171,14 @@ class CheckoutableListener
|
|||
|
||||
\Log::debug('Notification class: '.$notificationClass);
|
||||
|
||||
return new $notificationClass($event->checkoutable, $event->checkedOutTo, $event->checkedInBy, $event->note);
|
||||
return new $notificationClass($event->checkoutable, $event->checkedOutTo, $event->checkedInBy, $event->note);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the appropriate notification for the event
|
||||
*
|
||||
* @param CheckoutableCheckedIn $event
|
||||
* @param CheckoutAcceptance $acceptance
|
||||
*
|
||||
* @param CheckoutableCheckedIn $event
|
||||
* @param CheckoutAcceptance $acceptance
|
||||
* @return Notification
|
||||
*/
|
||||
private function getCheckoutNotification($event, $acceptance)
|
||||
|
@ -183,10 +194,10 @@ class CheckoutableListener
|
|||
break;
|
||||
case Consumable::class:
|
||||
$notificationClass = CheckoutConsumableNotification::class;
|
||||
break;
|
||||
break;
|
||||
case LicenseSeat::class:
|
||||
$notificationClass = CheckoutLicenseSeatNotification::class;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
return new $notificationClass($event->checkoutable, $event->checkedOutTo, $event->checkedOutBy, $acceptance, $event->note);
|
||||
|
@ -202,11 +213,11 @@ class CheckoutableListener
|
|||
$events->listen(
|
||||
\App\Events\CheckoutableCheckedIn::class,
|
||||
'App\Listeners\CheckoutableListener@onCheckedIn'
|
||||
);
|
||||
);
|
||||
|
||||
$events->listen(
|
||||
\App\Events\CheckoutableCheckedOut::class,
|
||||
'App\Listeners\CheckoutableListener@onCheckedOut'
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,17 +31,17 @@ class Accessory extends SnipeModel
|
|||
|
||||
use Searchable;
|
||||
use Acceptable;
|
||||
|
||||
|
||||
/**
|
||||
* The attributes that should be included when searching the model.
|
||||
*
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = ['name', 'model_number', 'order_number', 'purchase_date'];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
*
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableRelations = [
|
||||
|
@ -53,8 +53,8 @@ class Accessory extends SnipeModel
|
|||
];
|
||||
|
||||
/**
|
||||
* Accessory validation rules
|
||||
*/
|
||||
* Accessory validation rules
|
||||
*/
|
||||
public $rules = [
|
||||
'name' => 'required|min:3|max:255',
|
||||
'qty' => 'required|integer|min:1',
|
||||
|
@ -65,12 +65,12 @@ class Accessory extends SnipeModel
|
|||
];
|
||||
|
||||
/**
|
||||
* Whether the model should inject it's identifier to the unique
|
||||
* validation rules before attempting validation. If this property
|
||||
* is not set in the model it will default to true.
|
||||
*
|
||||
* Whether the model should inject it's identifier to the unique
|
||||
* validation rules before attempting validation. If this property
|
||||
* is not set in the model it will default to true.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
*/
|
||||
protected $injectUniqueIdentifier = true;
|
||||
use ValidatingTrait;
|
||||
|
||||
|
@ -92,9 +92,12 @@ class Accessory extends SnipeModel
|
|||
'supplier_id',
|
||||
'image',
|
||||
'qty',
|
||||
'min_amt',
|
||||
'requestable',
|
||||
];
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Establishes the accessory -> supplier relationship
|
||||
*
|
||||
|
@ -172,7 +175,7 @@ class Accessory extends SnipeModel
|
|||
|
||||
/**
|
||||
* Get the LAST checkout for this accessory.
|
||||
*
|
||||
*
|
||||
* This is kinda gross, but is necessary for how the accessory
|
||||
* pivot stuff works for now.
|
||||
*
|
||||
|
@ -201,6 +204,7 @@ class Accessory extends SnipeModel
|
|||
return $this->assetlog()->where('action_type', '=', 'checkout')->take(1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the full image url
|
||||
*
|
||||
|
@ -300,7 +304,7 @@ class Accessory extends SnipeModel
|
|||
return $Parsedown->text(e(Setting::getSettings()->default_eula_text));
|
||||
}
|
||||
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -320,13 +324,13 @@ class Accessory extends SnipeModel
|
|||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to order on company
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
* Query builder scope to order on company
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeOrderCompany($query, $order)
|
||||
{
|
||||
return $query->leftJoin('companies', 'accessories.company_id', '=', 'companies.id')
|
||||
|
@ -334,13 +338,13 @@ class Accessory extends SnipeModel
|
|||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to order on category
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
* Query builder scope to order on category
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeOrderCategory($query, $order)
|
||||
{
|
||||
return $query->leftJoin('categories', 'accessories.category_id', '=', 'categories.id')
|
||||
|
@ -348,13 +352,13 @@ class Accessory extends SnipeModel
|
|||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to order on location
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
* Query builder scope to order on location
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeOrderLocation($query, $order)
|
||||
{
|
||||
return $query->leftJoin('locations', 'accessories.location_id', '=', 'locations.id')
|
||||
|
@ -362,15 +366,28 @@ class Accessory extends SnipeModel
|
|||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to order on manufacturer
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
* Query builder scope to order on manufacturer
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeOrderManufacturer($query, $order)
|
||||
{
|
||||
return $query->leftJoin('manufacturers', 'accessories.manufacturer_id', '=', 'manufacturers.id')->orderBy('manufacturers.name', $order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to order on supplier
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeOrderSupplier($query, $order)
|
||||
{
|
||||
return $query->leftJoin('suppliers', 'accessories.supplier_id', '=', 'suppliers.id')->orderBy('suppliers.name', $order);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,8 @@ class Asset extends Depreciable
|
|||
{
|
||||
|
||||
protected $presenter = \App\Presenters\AssetPresenter::class;
|
||||
|
||||
use CompanyableTrait;
|
||||
use HasFactory, Loggable, Requestable, Presentable, SoftDeletes, ValidatingTrait, UniqueUndeletedTrait, UniqueSerialTrait;
|
||||
|
||||
const LOCATION = 'location';
|
||||
|
@ -39,35 +41,46 @@ class Asset extends Depreciable
|
|||
|
||||
/**
|
||||
* Run after the checkout acceptance was declined by the user
|
||||
*
|
||||
*
|
||||
* @param User $acceptedBy
|
||||
* @param string $signature
|
||||
*/
|
||||
*/
|
||||
public function declinedCheckout(User $declinedBy, $signature)
|
||||
{
|
||||
$this->assigned_to = null;
|
||||
$this->assigned_type = null;
|
||||
$this->accepted = null;
|
||||
$this->save();
|
||||
$this->assigned_to = null;
|
||||
$this->assigned_type = null;
|
||||
$this->accepted = null;
|
||||
$this->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* The database table used by the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
* The database table used by the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'assets';
|
||||
|
||||
/**
|
||||
* Whether the model should inject it's identifier to the unique
|
||||
* validation rules before attempting validation. If this property
|
||||
* is not set in the model it will default to true.
|
||||
*
|
||||
* Whether the model should inject it's identifier to the unique
|
||||
* validation rules before attempting validation. If this property
|
||||
* is not set in the model it will default to true.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
*/
|
||||
protected $injectUniqueIdentifier = true;
|
||||
|
||||
// We set these as protected dates so that they will be easily accessible via Carbon
|
||||
protected $dates = [
|
||||
'created_at',
|
||||
'updated_at',
|
||||
'deleted_at',
|
||||
'purchase_date',
|
||||
'last_checkout',
|
||||
'expected_checkin',
|
||||
'last_audit_date',
|
||||
'next_audit_date'
|
||||
];
|
||||
|
||||
|
||||
protected $casts = [
|
||||
'purchase_date' => 'datetime',
|
||||
|
@ -103,11 +116,11 @@ class Asset extends Depreciable
|
|||
'last_audit_date' => 'date|nullable',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'asset_tag',
|
||||
'assigned_to',
|
||||
|
@ -135,27 +148,27 @@ class Asset extends Depreciable
|
|||
|
||||
/**
|
||||
* The attributes that should be included when searching the model.
|
||||
*
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = [
|
||||
'name',
|
||||
'asset_tag',
|
||||
'serial',
|
||||
'order_number',
|
||||
'purchase_cost',
|
||||
'notes',
|
||||
'name',
|
||||
'asset_tag',
|
||||
'serial',
|
||||
'order_number',
|
||||
'purchase_cost',
|
||||
'notes',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
'purchase_date',
|
||||
'expected_checkin',
|
||||
'next_audit_date',
|
||||
'updated_at',
|
||||
'purchase_date',
|
||||
'expected_checkin',
|
||||
'next_audit_date',
|
||||
'last_audit_date',
|
||||
];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
*
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableRelations = [
|
||||
|
@ -169,6 +182,7 @@ class Asset extends Depreciable
|
|||
'model.manufacturer' => ['name'],
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* This handles the custom field validation for assets
|
||||
*
|
||||
|
@ -187,6 +201,7 @@ class Asset extends Depreciable
|
|||
return parent::save($params);
|
||||
}
|
||||
|
||||
|
||||
public function getDisplayNameAttribute()
|
||||
{
|
||||
return $this->present()->name();
|
||||
|
@ -212,6 +227,7 @@ class Asset extends Depreciable
|
|||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Establishes the asset -> company relationship
|
||||
*
|
||||
|
@ -242,7 +258,8 @@ class Asset extends Depreciable
|
|||
|
||||
// The asset status is not archived and is deployable
|
||||
if (($this->assetstatus) && ($this->assetstatus->archived == '0')
|
||||
&& ($this->assetstatus->deployable == '1')) {
|
||||
&& ($this->assetstatus->deployable == '1'))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -346,6 +363,7 @@ class Asset extends Depreciable
|
|||
return $this->rules;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Establishes the asset -> depreciation relationship
|
||||
*
|
||||
|
@ -358,6 +376,7 @@ class Asset extends Depreciable
|
|||
return $this->model->belongsTo(\App\Models\Depreciation::class, 'depreciation_id');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get components assigned to this asset
|
||||
*
|
||||
|
@ -367,9 +386,10 @@ class Asset extends Depreciable
|
|||
*/
|
||||
public function components()
|
||||
{
|
||||
return $this->belongsToMany(\App\Models\Component::class, 'components_assets', 'asset_id', 'component_id')->withPivot('id', 'assigned_qty')->withTrashed();
|
||||
return $this->belongsToMany('\App\Models\Component', 'components_assets', 'asset_id', 'component_id')->withPivot('id', 'assigned_qty', 'created_at')->withTrashed();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get depreciation attribute from associated asset model
|
||||
*
|
||||
|
@ -386,6 +406,7 @@ class Asset extends Depreciable
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get uploads for this asset
|
||||
*
|
||||
|
@ -395,8 +416,8 @@ class Asset extends Depreciable
|
|||
*/
|
||||
public function uploads()
|
||||
{
|
||||
return $this->hasMany(\App\Models\Actionlog::class, 'item_id')
|
||||
->where('item_type', '=', self::class)
|
||||
return $this->hasMany('\App\Models\Actionlog', 'item_id')
|
||||
->where('item_type', '=', Asset::class)
|
||||
->where('action_type', '=', 'uploaded')
|
||||
->whereNotNull('filename')
|
||||
->orderBy('created_at', 'desc');
|
||||
|
@ -414,7 +435,7 @@ class Asset extends Depreciable
|
|||
*/
|
||||
public function checkedOutToUser()
|
||||
{
|
||||
return $this->assignedType() === self::USER;
|
||||
return $this->assignedType() === self::USER;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -443,6 +464,7 @@ class Asset extends Depreciable
|
|||
return $this->morphMany(self::class, 'assigned', 'assigned_type', 'assigned_to')->withTrashed();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the asset's location based on the assigned user
|
||||
*
|
||||
|
@ -471,6 +493,7 @@ class Asset extends Depreciable
|
|||
if ($this->assignedTo) {
|
||||
return $this->assignedTo;
|
||||
}
|
||||
|
||||
}
|
||||
if ($this->assignedType() == self::USER) {
|
||||
if (($this->assignedTo) && $this->assignedTo->userLoc) {
|
||||
|
@ -479,7 +502,7 @@ class Asset extends Depreciable
|
|||
//this makes no sense
|
||||
return $this->defaultLoc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->defaultLoc;
|
||||
}
|
||||
|
@ -529,6 +552,7 @@ class Asset extends Depreciable
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the asset's logs
|
||||
*
|
||||
|
@ -588,6 +612,7 @@ class Asset extends Depreciable
|
|||
->withTrashed();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get maintenances for this asset
|
||||
*
|
||||
|
@ -613,6 +638,8 @@ class Asset extends Depreciable
|
|||
return $this->belongsTo(\App\Models\User::class, 'user_id');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Establishes the asset -> status relationship
|
||||
*
|
||||
|
@ -658,6 +685,7 @@ class Asset extends Depreciable
|
|||
->get();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Establishes the asset -> assigned licenses relationship
|
||||
*
|
||||
|
@ -706,6 +734,8 @@ class Asset extends Depreciable
|
|||
return $this->belongsTo(\App\Models\Location::class, 'location_id');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the next autoincremented asset tag
|
||||
*
|
||||
|
@ -717,6 +747,7 @@ class Asset extends Depreciable
|
|||
{
|
||||
$settings = \App\Models\Setting::getSettings();
|
||||
|
||||
|
||||
if ($settings->auto_increment_assets == '1') {
|
||||
$temp_asset_tag = \DB::table('assets')
|
||||
->where('physical', '=', '1')
|
||||
|
@ -735,6 +766,7 @@ class Asset extends Depreciable
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next base number for the auto-incrementer.
|
||||
*
|
||||
|
@ -746,23 +778,28 @@ class Asset extends Depreciable
|
|||
*/
|
||||
public static function nextAutoIncrement($assets)
|
||||
{
|
||||
|
||||
$max = 1;
|
||||
|
||||
foreach ($assets as $asset) {
|
||||
$results = preg_match("/\d+$/", $asset['asset_tag'], $matches);
|
||||
|
||||
if ($results) {
|
||||
if ($results)
|
||||
{
|
||||
$number = $matches[0];
|
||||
|
||||
if ($number > $max) {
|
||||
if ($number > $max)
|
||||
{
|
||||
$max = $number;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $max + 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add zerofilling based on Settings
|
||||
*
|
||||
|
@ -802,6 +839,7 @@ class Asset extends Depreciable
|
|||
if (($this->model) && ($this->model->category)) {
|
||||
return $this->model->category->require_acceptance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -815,7 +853,7 @@ class Asset extends Depreciable
|
|||
public function getEula()
|
||||
{
|
||||
$Parsedown = new \Parsedown();
|
||||
|
||||
|
||||
if (($this->model) && ($this->model->category)) {
|
||||
if ($this->model->category->eula_text) {
|
||||
return $Parsedown->text(e($this->model->category->eula_text));
|
||||
|
@ -829,11 +867,12 @@ class Asset extends Depreciable
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* -----------------------------------------------
|
||||
* BEGIN QUERY SCOPES
|
||||
* -----------------------------------------------
|
||||
**/
|
||||
* -----------------------------------------------
|
||||
* BEGIN QUERY SCOPES
|
||||
* -----------------------------------------------
|
||||
**/
|
||||
|
||||
/**
|
||||
* Run additional, advanced searches.
|
||||
|
@ -854,11 +893,13 @@ class Asset extends Depreciable
|
|||
});
|
||||
|
||||
foreach ($terms as $term) {
|
||||
|
||||
$query = $query
|
||||
->orWhere('assets_users.first_name', 'LIKE', '%'.$term.'%')
|
||||
->orWhere('assets_users.last_name', 'LIKE', '%'.$term.'%')
|
||||
->orWhere('assets_users.username', 'LIKE', '%'.$term.'%')
|
||||
->orWhereRaw('CONCAT('.DB::getTablePrefix().'assets_users.first_name," ",'.DB::getTablePrefix().'assets_users.last_name) LIKE ?', ["%$term%", "%$term%"]);
|
||||
->orWhereRaw('CONCAT('.DB::getTablePrefix().'assets_users.first_name," ",'.DB::getTablePrefix().'assets_users.last_name) LIKE ?', ["%$term%"]);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -870,6 +911,7 @@ class Asset extends Depreciable
|
|||
});
|
||||
|
||||
foreach ($terms as $term) {
|
||||
|
||||
$query = $query->orWhere('assets_locations.name', 'LIKE', '%'.$term.'%');
|
||||
}
|
||||
|
||||
|
@ -883,30 +925,34 @@ class Asset extends Depreciable
|
|||
|
||||
foreach ($terms as $term) {
|
||||
$query = $query->orWhere('assigned_assets.name', 'LIKE', '%'.$term.'%');
|
||||
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope for hardware
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
* Query builder scope for hardware
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
|
||||
public function scopeHardware($query)
|
||||
{
|
||||
return $query->where('physical', '=', '1');
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope for pending assets
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
* Query builder scope for pending assets
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
|
||||
public function scopePending($query)
|
||||
{
|
||||
return $query->whereHas('assetstatus', function ($query) {
|
||||
|
@ -916,13 +962,15 @@ class Asset extends Depreciable
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope for searching location
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
* Query builder scope for searching location
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
|
||||
public function scopeAssetsByLocation($query, $location)
|
||||
{
|
||||
return $query->where(function ($query) use ($location) {
|
||||
|
@ -944,13 +992,15 @@ class Asset extends Depreciable
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope for RTD assets
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
* Query builder scope for RTD assets
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
|
||||
public function scopeRTD($query)
|
||||
{
|
||||
return $query->whereNull('assets.assigned_to')
|
||||
|
@ -961,13 +1011,14 @@ class Asset extends Depreciable
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope for Undeployable assets
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
/**
|
||||
* Query builder scope for Undeployable assets
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
|
||||
public function scopeUndeployable($query)
|
||||
{
|
||||
return $query->whereHas('assetstatus', function ($query) {
|
||||
|
@ -984,6 +1035,7 @@ class Asset extends Depreciable
|
|||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
|
||||
public function scopeNotArchived($query)
|
||||
{
|
||||
return $query->whereHas('assetstatus', function ($query) {
|
||||
|
@ -1013,6 +1065,7 @@ class Asset extends Depreciable
|
|||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
|
||||
public function scopeDueForAudit($query, $settings)
|
||||
{
|
||||
$interval = $settings->audit_warning_days ?? 0;
|
||||
|
@ -1037,6 +1090,7 @@ class Asset extends Depreciable
|
|||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
|
||||
public function scopeOverdueForAudit($query)
|
||||
{
|
||||
return $query->whereNotNull('assets.next_audit_date')
|
||||
|
@ -1058,6 +1112,7 @@ class Asset extends Depreciable
|
|||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
|
||||
public function scopeDueOrOverdueForAudit($query, $settings)
|
||||
{
|
||||
$interval = $settings->audit_warning_days ?? 0;
|
||||
|
@ -1068,13 +1123,15 @@ class Asset extends Depreciable
|
|||
->NotArchived();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope for Archived assets
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
|
||||
/**
|
||||
* Query builder scope for Archived assets
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
|
||||
public function scopeArchived($query)
|
||||
{
|
||||
return $query->whereHas('assetstatus', function ($query) {
|
||||
|
@ -1084,25 +1141,27 @@ class Asset extends Depreciable
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope for Deployed assets
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
/**
|
||||
* Query builder scope for Deployed assets
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
|
||||
public function scopeDeployed($query)
|
||||
{
|
||||
return $query->where('assigned_to', '>', '0');
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope for Requestable assets
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
/**
|
||||
* Query builder scope for Requestable assets
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
|
||||
public function scopeRequestableAssets($query)
|
||||
{
|
||||
return Company::scopeCompanyables($query->where('requestable', '=', 1))
|
||||
|
@ -1113,53 +1172,55 @@ class Asset extends Depreciable
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* scopeInModelList
|
||||
* Get all assets in the provided listing of model ids
|
||||
*
|
||||
* @param $query
|
||||
* @param array $modelIdListing
|
||||
*
|
||||
* @return mixed
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @version v1.0
|
||||
*/
|
||||
* scopeInModelList
|
||||
* Get all assets in the provided listing of model ids
|
||||
*
|
||||
* @param $query
|
||||
* @param array $modelIdListing
|
||||
*
|
||||
* @return mixed
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @version v1.0
|
||||
*/
|
||||
public function scopeInModelList($query, array $modelIdListing)
|
||||
{
|
||||
return $query->whereIn('assets.model_id', $modelIdListing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to get not-yet-accepted assets
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
/**
|
||||
* Query builder scope to get not-yet-accepted assets
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeNotYetAccepted($query)
|
||||
{
|
||||
return $query->where('accepted', '=', 'pending');
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to get rejected assets
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
/**
|
||||
* Query builder scope to get rejected assets
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeRejected($query)
|
||||
{
|
||||
return $query->where('accepted', '=', 'rejected');
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to get accepted assets
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
|
||||
/**
|
||||
* Query builder scope to get accepted assets
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeAccepted($query)
|
||||
{
|
||||
return $query->where('accepted', '=', 'accepted');
|
||||
|
@ -1205,7 +1266,7 @@ class Asset extends Depreciable
|
|||
})->orWhere(function ($query) use ($search) {
|
||||
$query->where('assets_users.first_name', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('assets_users.last_name', 'LIKE', '%'.$search.'%')
|
||||
->orWhereRaw('CONCAT('.DB::getTablePrefix().'assets_users.first_name," ",'.DB::getTablePrefix().'assets_users.last_name) LIKE ?', ["%$search%", "%$search%"])
|
||||
->orWhereRaw('CONCAT('.DB::getTablePrefix().'assets_users.first_name," ",'.DB::getTablePrefix().'assets_users.last_name) LIKE ?', ["%$search%"])
|
||||
->orWhere('assets_users.username', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('assets_locations.name', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('assigned_assets.name', 'LIKE', '%'.$search.'%');
|
||||
|
@ -1215,6 +1276,7 @@ class Asset extends Depreciable
|
|||
->orWhere('assets.order_number', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('assets.notes', 'LIKE', '%'.$search.'%');
|
||||
}
|
||||
|
||||
})->withTrashed()->whereNull('assets.deleted_at'); //workaround for laravel bug
|
||||
}
|
||||
|
||||
|
@ -1233,10 +1295,13 @@ class Asset extends Depreciable
|
|||
$leftJoin->on('assets_dept_users.id', '=', 'assets.assigned_to')
|
||||
->where('assets.assigned_type', '=', User::class);
|
||||
})->where(function ($query) use ($search) {
|
||||
$query->where('assets_dept_users.department_id', '=', $search);
|
||||
$query->where('assets_dept_users.department_id', '=', $search);
|
||||
|
||||
})->withTrashed()->whereNull('assets.deleted_at'); //workaround for laravel bug
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope to search on text filters for complex Bootstrap Tables API
|
||||
*
|
||||
|
@ -1259,7 +1324,8 @@ class Asset extends Depreciable
|
|||
$query->where('assets.name', 'LIKE', '%'.$search_val.'%');
|
||||
}
|
||||
|
||||
if ($fieldname == 'product_key') {
|
||||
|
||||
if ($fieldname =='serial') {
|
||||
$query->where('assets.serial', 'LIKE', '%'.$search_val.'%');
|
||||
}
|
||||
|
||||
|
@ -1300,6 +1366,7 @@ class Asset extends Depreciable
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
if ($fieldname == 'manufacturer') {
|
||||
$query->whereHas('model', function ($query) use ($search_val) {
|
||||
$query->whereHas('manufacturer', function ($query) use ($search_val) {
|
||||
|
@ -1338,6 +1405,7 @@ class Asset extends Depreciable
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
if ($fieldname == 'company') {
|
||||
$query->where(function ($query) use ($search_val) {
|
||||
$query->whereHas('company', function ($query) use ($search_val) {
|
||||
|
@ -1374,80 +1442,90 @@ class Asset extends Depreciable
|
|||
* assets.location would fail, as that field doesn't exist -- plus we're already searching
|
||||
* against those relationships earlier in this method.
|
||||
*
|
||||
* - snipe
|
||||
* - snipe
|
||||
*
|
||||
*/
|
||||
if (($fieldname != 'category') && ($fieldname != 'model_number') && ($fieldname != 'rtd_location') && ($fieldname != 'location') && ($fieldname != 'supplier')
|
||||
&& ($fieldname != 'status_label') && ($fieldname != 'model') && ($fieldname != 'company') && ($fieldname != 'manufacturer')) {
|
||||
$query->orWhere('assets.'.$fieldname, 'LIKE', '%'.$search_val.'%');
|
||||
|
||||
if (($fieldname!='category') && ($fieldname!='model_number') && ($fieldname!='rtd_location') && ($fieldname!='location') && ($fieldname!='supplier')
|
||||
&& ($fieldname!='status_label') && ($fieldname!='model') && ($fieldname!='company') && ($fieldname!='manufacturer')) {
|
||||
$query->where('assets.'.$fieldname, 'LIKE', '%' . $search_val . '%');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope to order on model
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
* Query builder scope to order on model
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeOrderModels($query, $order)
|
||||
{
|
||||
return $query->join('models as asset_models', 'assets.model_id', '=', 'asset_models.id')->orderBy('asset_models.name', $order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to order on model number
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
* Query builder scope to order on model number
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeOrderModelNumber($query, $order)
|
||||
{
|
||||
return $query->join('models', 'assets.model_id', '=', 'models.id')->orderBy('models.model_number', $order);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope to order on assigned user
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
* Query builder scope to order on assigned user
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeOrderAssigned($query, $order)
|
||||
{
|
||||
return $query->leftJoin('users as users_sort', 'assets.assigned_to', '=', 'users_sort.id')->select('assets.*')->orderBy('users_sort.first_name', $order)->orderBy('users_sort.last_name', $order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to order on status
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
* Query builder scope to order on status
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeOrderStatus($query, $order)
|
||||
{
|
||||
return $query->join('status_labels as status_sort', 'assets.status_id', '=', 'status_sort.id')->orderBy('status_sort.name', $order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to order on company
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
* Query builder scope to order on company
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeOrderCompany($query, $order)
|
||||
{
|
||||
return $query->leftJoin('companies as company_sort', 'assets.company_id', '=', 'company_sort.id')->orderBy('company_sort.name', $order);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope to return results of a category
|
||||
*
|
||||
|
@ -1476,14 +1554,16 @@ class Asset extends Depreciable
|
|||
->join('manufacturers', 'models.manufacturer_id', '=', 'manufacturers.id')->where('models.manufacturer_id', '=', $manufacturer_id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope to order on category
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
* Query builder scope to order on category
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeOrderCategory($query, $order)
|
||||
{
|
||||
return $query->join('models as order_model_category', 'assets.model_id', '=', 'order_model_category.id')
|
||||
|
@ -1491,6 +1571,7 @@ class Asset extends Depreciable
|
|||
->orderBy('category_order.name', $order);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope to order on manufacturer
|
||||
*
|
||||
|
@ -1506,14 +1587,14 @@ class Asset extends Depreciable
|
|||
->orderBy('manufacturers.name', $order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to order on location
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
/**
|
||||
* Query builder scope to order on location
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeOrderLocation($query, $order)
|
||||
{
|
||||
return $query->leftJoin('locations as asset_locations', 'asset_locations.id', '=', 'assets.location_id')->orderBy('asset_locations.name', $order);
|
||||
|
@ -1531,6 +1612,7 @@ class Asset extends Depreciable
|
|||
return $query->leftJoin('locations as rtd_asset_locations', 'rtd_asset_locations.id', '=', 'assets.rtd_location_id')->orderBy('rtd_asset_locations.name', $order);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope to order on supplier name
|
||||
*
|
||||
|
@ -1559,8 +1641,10 @@ class Asset extends Depreciable
|
|||
$query->where('locations.id', '=', $search);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope to search on depreciation name
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
|
@ -1572,5 +1656,8 @@ class Asset extends Depreciable
|
|||
{
|
||||
return $query->join('models', 'assets.model_id', '=', 'models.id')
|
||||
->join('depreciations', 'models.depreciation_id', '=', 'depreciations.id')->where('models.depreciation_id', '=', $search);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Http\Traits\UniqueUndeletedTrait;
|
||||
use App\Http\Traits\TwoColumnUniqueUndeletedTrait;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
@ -38,7 +38,7 @@ class Category extends SnipeModel
|
|||
*/
|
||||
public $rules = [
|
||||
'user_id' => 'numeric|nullable',
|
||||
'name' => 'required|min:1|max:255|unique_undeleted',
|
||||
'name' => 'required|min:1|max:255|two_column_unique_undeleted:category_type',
|
||||
'require_acceptance' => 'boolean',
|
||||
'use_default_eula' => 'boolean',
|
||||
'category_type' => 'required|in:asset,accessory,consumable,component,license',
|
||||
|
@ -53,7 +53,8 @@ class Category extends SnipeModel
|
|||
*/
|
||||
protected $injectUniqueIdentifier = true;
|
||||
use ValidatingTrait;
|
||||
use UniqueUndeletedTrait;
|
||||
use TwoColumnUniqueUndeletedTrait;
|
||||
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
|
|
|
@ -30,29 +30,29 @@ final class Company extends SnipeModel
|
|||
use Presentable;
|
||||
|
||||
/**
|
||||
* Whether the model should inject it's identifier to the unique
|
||||
* validation rules before attempting validation. If this property
|
||||
* is not set in the model it will default to true.
|
||||
*
|
||||
* Whether the model should inject it's identifier to the unique
|
||||
* validation rules before attempting validation. If this property
|
||||
* is not set in the model it will default to true.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
*/
|
||||
protected $injectUniqueIdentifier = true;
|
||||
use ValidatingTrait;
|
||||
use Searchable;
|
||||
|
||||
|
||||
/**
|
||||
* The attributes that should be included when searching the model.
|
||||
*
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = ['name', 'created_at', 'updated_at'];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
*
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableRelations = [];
|
||||
protected $searchableRelations = [];
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
|
@ -81,10 +81,10 @@ final class Company extends SnipeModel
|
|||
$company_id = null;
|
||||
}
|
||||
|
||||
$table = ($table_name) ? $table_name.'.' : '';
|
||||
$table = ($table_name) ? $table_name."." : $query->getModel()->getTable().".";
|
||||
|
||||
if (\Schema::hasColumn($query->getModel()->getTable(), $column)) {
|
||||
return $query->where($table.$column, '=', $company_id);
|
||||
return $query->where($table.$column, '=', $company_id);
|
||||
} else {
|
||||
return $query->join('users as users_comp', 'users_comp.id', 'user_id')->where('users_comp.company_id', '=', $company_id);
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ class Consumable extends SnipeModel
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = ['name', 'order_number', 'purchase_cost', 'purchase_date', 'item_no'];
|
||||
protected $searchableAttributes = ['name', 'order_number', 'purchase_cost', 'purchase_date', 'item_no', 'model_number'];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
|
|
|
@ -47,13 +47,20 @@ class Ldap extends Model
|
|||
ldap_set_option($connection, LDAP_OPT_PROTOCOL_VERSION, $ldap_version);
|
||||
ldap_set_option($connection, LDAP_OPT_NETWORK_TIMEOUT, 20);
|
||||
|
||||
if ($ldap_use_tls == '1') {
|
||||
if (Setting::getSettings()->ldap_client_tls_cert && Setting::getSettings()->ldap_client_tls_key) {
|
||||
ldap_set_option($connection, LDAP_OPT_X_TLS_CERTFILE, Setting::get_client_side_cert_path());
|
||||
ldap_set_option($connection, LDAP_OPT_X_TLS_KEYFILE, Setting::get_client_side_key_path());
|
||||
}
|
||||
|
||||
if ($ldap_use_tls=='1') {
|
||||
ldap_start_tls($connection);
|
||||
}
|
||||
|
||||
|
||||
return $connection;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Binds/authenticates the user to LDAP, and returns their attributes.
|
||||
*
|
||||
|
@ -95,7 +102,7 @@ class Ldap extends Model
|
|||
|
||||
if (! $ldapbind = @ldap_bind($connection, $userDn, $password)) {
|
||||
if (! $ldapbind = self::bindAdminToLdap($connection)) {
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,6 +135,8 @@ class Ldap extends Model
|
|||
{
|
||||
$ldap_username = Setting::getSettings()->ldap_uname;
|
||||
|
||||
$ldap_username = Setting::getSettings()->ldap_uname;
|
||||
|
||||
// Lets return some nicer messages for users who donked their app key, and disable LDAP
|
||||
try {
|
||||
$ldap_pass = \Crypt::decrypt(Setting::getSettings()->ldap_pword);
|
||||
|
@ -140,6 +149,7 @@ class Ldap extends Model
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse and map LDAP attributes based on settings
|
||||
*
|
||||
|
|
|
@ -341,8 +341,60 @@ class Setting extends Model
|
|||
'is_ad',
|
||||
'ad_domain',
|
||||
'ad_append_domain',
|
||||
'ldap_client_tls_key',
|
||||
'ldap_client_tls_cert'
|
||||
])->first()->getAttributes();
|
||||
|
||||
return collect($ldapSettings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the filename for the client-side SSL cert
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static function get_client_side_cert_path()
|
||||
{
|
||||
return storage_path().'/ldap_client_tls.cert';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the filename for the client-side SSL key
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static function get_client_side_key_path()
|
||||
{
|
||||
return storage_path().'/ldap_client_tls.key';
|
||||
}
|
||||
|
||||
public function update_client_side_cert_files()
|
||||
{
|
||||
/**
|
||||
* I'm not sure if it makes sense to have a cert but no key
|
||||
* nor vice versa, but for now I'm just leaving it like this.
|
||||
*
|
||||
* Also, we could easily set this up with an event handler and
|
||||
* self::saved() or something like that but there's literally only
|
||||
* one place where we will do that, so I'll just explicitly call
|
||||
* this method at that spot instead. It'll be easier to debug and understand.
|
||||
*/
|
||||
if ($this->ldap_client_tls_cert) {
|
||||
file_put_contents(self::get_client_side_cert_path(), $this->ldap_client_tls_cert);
|
||||
} else {
|
||||
if (file_exists(self::get_client_side_cert_path())) {
|
||||
unlink(self::get_client_side_cert_path());
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->ldap_client_tls_key) {
|
||||
file_put_contents(self::get_client_side_key_path(), $this->ldap_client_tls_key);
|
||||
} else {
|
||||
if (file_exists(self::get_client_side_key_path())) {
|
||||
unlink(self::get_client_side_key_path());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
|||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
*
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableRelations = [
|
||||
|
@ -122,8 +122,8 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
|||
protected function checkPermissionSection($section)
|
||||
{
|
||||
$user_groups = $this->groups;
|
||||
|
||||
if (($this->permissions == '') && (count($user_groups) == 0)) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -181,6 +181,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
|||
return $this->checkPermissionSection('superuser');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Establishes the user -> company relationship
|
||||
*
|
||||
|
@ -439,6 +440,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
|||
return $this->belongsToMany(Asset::class, 'checkout_requests', 'user_id', 'requestable_id')->whereNull('canceled_at');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope to return NOT-deleted users
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
|
@ -472,7 +474,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
|||
|
||||
/**
|
||||
* Generate email from full name
|
||||
*
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v2.0]
|
||||
*
|
||||
|
@ -518,7 +520,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
|||
$username = str_slug($first_name).str_slug($last_name);
|
||||
} elseif ($format == 'firstnamelastinitial') {
|
||||
$username = str_slug(($first_name.substr($last_name, 0, 1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$user['first_name'] = $first_name;
|
||||
|
@ -583,6 +585,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function decodePermissions()
|
||||
{
|
||||
return json_decode($this->permissions, true);
|
||||
|
@ -599,13 +602,14 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
|||
*/
|
||||
public function scopeSimpleNameSearch($query, $search)
|
||||
{
|
||||
$query = $query->where('first_name', 'LIKE', '%'.$search.'%')
|
||||
$query = $query->where('first_name', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('last_name', 'LIKE', '%'.$search.'%')
|
||||
->orWhereRaw('CONCAT('.DB::getTablePrefix().'users.first_name," ",'.DB::getTablePrefix().'users.last_name) LIKE ?', ["%$search%", "%$search%"]);
|
||||
->orWhereRaw('CONCAT('.DB::getTablePrefix().'users.first_name," ",'.DB::getTablePrefix().'users.last_name) LIKE ?', ["%$search%"]);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Run additional, advanced searches.
|
||||
*
|
||||
|
@ -613,10 +617,10 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
|||
* @param array $terms The search terms
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function advancedTextSearch(Builder $query, array $terms)
|
||||
{
|
||||
foreach ($terms as $term) {
|
||||
$query = $query->orWhereRaw('CONCAT('.DB::getTablePrefix().'users.first_name," ",'.DB::getTablePrefix().'users.last_name) LIKE ?', ["%$term%", "%$term%"]);
|
||||
public function advancedTextSearch(Builder $query, array $terms) {
|
||||
|
||||
foreach($terms as $term) {
|
||||
$query = $query->orWhereRaw('CONCAT('.DB::getTablePrefix().'users.first_name," ",'.DB::getTablePrefix().'users.last_name) LIKE ?', ["%$term%"]);
|
||||
}
|
||||
|
||||
return $query;
|
||||
|
|
|
@ -30,7 +30,7 @@ class CheckinAssetNotification extends Notification
|
|||
$this->expected_checkin = '';
|
||||
|
||||
if ($this->item->expected_checkin) {
|
||||
$this->expected_checkin = \App\Helpers\Helper::getFormattedDateObject($this->item->expected_checkin, 'date',
|
||||
$this->expected_checkin = Helper::getFormattedDateObject($this->item->expected_checkin, 'date',
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Notifications;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
|
@ -33,12 +34,12 @@ class CheckoutAssetNotification extends Notification
|
|||
$this->expected_checkin = '';
|
||||
|
||||
if ($this->item->last_checkout) {
|
||||
$this->last_checkout = \App\Helpers\Helper::getFormattedDateObject($this->item->last_checkout, 'date',
|
||||
$this->last_checkout = Helper::getFormattedDateObject($this->item->last_checkout, 'date',
|
||||
false);
|
||||
}
|
||||
|
||||
if ($this->item->expected_checkin) {
|
||||
$this->expected_checkin = \App\Helpers\Helper::getFormattedDateObject($this->item->expected_checkin, 'date',
|
||||
$this->expected_checkin = Helper::getFormattedDateObject($this->item->expected_checkin, 'date',
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,21 +38,20 @@ class ActionlogPresenter extends Presenter
|
|||
|
||||
public function icon()
|
||||
{
|
||||
$itemicon = 'fa fa-paperclip';
|
||||
$itemicon = 'fas fa-paperclip';
|
||||
|
||||
if ($this->itemType() == 'asset') {
|
||||
$itemicon = 'fa fa-barcode';
|
||||
return 'fas fa-barcode';
|
||||
} elseif ($this->itemType() == 'accessory') {
|
||||
$itemicon = 'fa fa-keyboard-o';
|
||||
return 'far fa-keyboard';
|
||||
} elseif ($this->itemType() == 'consumable') {
|
||||
$itemicon = 'fa fa-tint';
|
||||
return 'fas fa-tint';
|
||||
} elseif ($this->itemType() == 'license') {
|
||||
$itemicon = 'fa fa-floppy-o';
|
||||
return 'far fa-save';
|
||||
} elseif ($this->itemType() == 'component') {
|
||||
$itemicon = 'fa fa-hdd-o';
|
||||
return 'far fa-hdd';
|
||||
}
|
||||
|
||||
return $itemicon;
|
||||
}
|
||||
|
||||
public function actionType()
|
||||
|
|
|
@ -248,7 +248,7 @@ class AssetAuditPresenter extends Presenter
|
|||
'sortable' => true,
|
||||
'visible' => false,
|
||||
'switchable' => true,
|
||||
'title' => ($field->field_encrypted == '1') ? '<i class="fa fa-lock"></i> '.e($field->name) : e($field->name),
|
||||
'title' => ($field->field_encrypted == '1') ? '<i class="fas fa-lock"></i> '.e($field->name) : e($field->name),
|
||||
'formatter' => 'customFieldsFormatter',
|
||||
];
|
||||
}
|
||||
|
|
|
@ -106,6 +106,14 @@ class AssetModelPresenter extends Presenter
|
|||
'visible' => true,
|
||||
'formatter' => 'fieldsetsLinkObjFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'requestable',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'visible' => false,
|
||||
'title' => trans('admin/hardware/general.requestable'),
|
||||
'formatter' => 'trueFalseFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'notes',
|
||||
'searchable' => true,
|
||||
|
|
|
@ -523,6 +523,6 @@ class AssetPresenter extends Presenter
|
|||
|
||||
public function glyph()
|
||||
{
|
||||
return '<i class="fa fa-barcode" aria-hidden="true"></i>';
|
||||
return '<i class="fas fa-barcode" aria-hidden="true"></i>';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,7 +75,25 @@ class CategoryPresenter extends Presenter
|
|||
'sortable' => false,
|
||||
'switchable' => false,
|
||||
'title' => trans('table.actions'),
|
||||
],[
|
||||
"field" => "use_default_eula",
|
||||
"searchable" => false,
|
||||
"sortable" => true,
|
||||
"title" => trans('admin/categories/general.use_default_eula_column'),
|
||||
'visible' => true,
|
||||
"formatter" => 'trueFalseFormatter',
|
||||
],[
|
||||
"field" => "checkin_email",
|
||||
"searchable" => false,
|
||||
"sortable" => true,
|
||||
"class" => 'css-envelope',
|
||||
"title" => 'Send Email',
|
||||
"visible" => true,
|
||||
"formatter" => 'trueFalseFormatter',
|
||||
],[
|
||||
"field" => "require_acceptance",
|
||||
"searchable" => false,
|
||||
"sortable" => true,
|
||||
'formatter' => 'categoriesActionsFormatter',
|
||||
],
|
||||
[
|
||||
|
|
|
@ -41,14 +41,14 @@ class CompanyPresenter extends Presenter
|
|||
'field' => 'users_count',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'title' => '<span class="hidden-xs"><i class="fa fa-users"></i></span><span class="hidden-md hidden-lg">'.trans('general.users').'</span></th>',
|
||||
'title' => '<span class="hidden-xs"><i class="fas fa-users"></i></span><span class="hidden-md hidden-lg">'.trans('general.users').'</span></th>',
|
||||
'visible' => true,
|
||||
|
||||
], [
|
||||
'field' => 'assets_count',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'title' => '<span class="hidden-xs"><i class="fa fa-barcode" aria-hidden="true"></i></span><span class="hidden-md hidden-lg">'.trans('general.assets').'</span>',
|
||||
'title' => '<span class="hidden-xs"><i class="fas fa-barcode" aria-hidden="true"></i></span><span class="hidden-md hidden-lg">'.trans('general.assets').'</span>',
|
||||
'visible' => true,
|
||||
|
||||
], [
|
||||
|
@ -56,25 +56,25 @@ class CompanyPresenter extends Presenter
|
|||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'visible' => true,
|
||||
'title' => ' <span class="hidden-xs"><i class="fa fa-floppy-o"></i></span><span class="hidden-md hidden-lg">'.trans('general.licenses').'</span>',
|
||||
'title' => ' <span class="hidden-xs"><i class="far fa-save"></i></span><span class="hidden-md hidden-lg">'.trans('general.licenses').'</span>',
|
||||
], [
|
||||
'field' => 'accessories_count',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'visible' => true,
|
||||
'title' => ' <span class="hidden-xs"><i class="fa fa-keyboard-o"></i></span><span class="hidden-md hidden-lg">'.trans('general.accessories').'</span>',
|
||||
'title' => ' <span class="hidden-xs"><i class="far fa-keyboard"></i></span><span class="hidden-md hidden-lg">'.trans('general.accessories').'</span>',
|
||||
], [
|
||||
'field' => 'consumables_count',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'visible' => true,
|
||||
'title' => ' <span class="hidden-xs"><i class="fa fa-tint"></i></span><span class="hidden-md hidden-lg">'.trans('general.consumables').'</span>',
|
||||
'title' => ' <span class="hidden-xs"><i class="fas fa-tint"></i></span><span class="hidden-md hidden-lg">'.trans('general.consumables').'</span>',
|
||||
], [
|
||||
'field' => 'components_count',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'visible' => true,
|
||||
'title' => ' <span class="hidden-xs"><i class="fa fa-hdd-o"></i></span><span class="hidden-md hidden-lg">'.trans('general.components').'</span>',
|
||||
'title' => ' <span class="hidden-xs"><i class="far fa-hdd"></i></span><span class="hidden-md hidden-lg">'.trans('general.components').'</span>',
|
||||
], [
|
||||
'field' => 'updated_at',
|
||||
'searchable' => false,
|
||||
|
|
401
app/Presenters/DepreciationReportPresenter.php
Normal file
401
app/Presenters/DepreciationReportPresenter.php
Normal file
|
@ -0,0 +1,401 @@
|
|||
<?php
|
||||
namespace App\Presenters;
|
||||
|
||||
use DateTime;
|
||||
|
||||
/**
|
||||
* Class DepreciationReportPresenter
|
||||
* @package App\Presenters
|
||||
*/
|
||||
class DepreciationReportPresenter extends Presenter
|
||||
{
|
||||
|
||||
/**
|
||||
* Json Column Layout for bootstrap table
|
||||
* @return string
|
||||
*/
|
||||
public static function dataTableLayout()
|
||||
{
|
||||
$layout = [
|
||||
[
|
||||
"field" => "company",
|
||||
"searchable" => true,
|
||||
"sortable" => true,
|
||||
"switchable" => true,
|
||||
"title" => trans('general.company'),
|
||||
"visible" => false,
|
||||
], [
|
||||
"field" => "category",
|
||||
"searchable" => true,
|
||||
"sortable" => true,
|
||||
"title" => trans('general.category'),
|
||||
"visible" => true,
|
||||
], [
|
||||
"field" => "name",
|
||||
"searchable" => true,
|
||||
"sortable" => true,
|
||||
"title" => trans('admin/hardware/form.name'),
|
||||
"visible" => false,
|
||||
], [
|
||||
"field" => "asset_tag",
|
||||
"searchable" => true,
|
||||
"sortable" => true,
|
||||
"title" => trans('general.asset_tag'),
|
||||
"visible" => true,
|
||||
],[
|
||||
"field" => "model",
|
||||
"searchable" => true,
|
||||
"sortable" => true,
|
||||
"title" => trans('general.asset_model'),
|
||||
"visible" => true,
|
||||
], [
|
||||
"field" => "model",
|
||||
"searchable" => true,
|
||||
"sortable" => true,
|
||||
"title" => trans('admin/hardware/form.model'),
|
||||
"visible" => true,
|
||||
], [
|
||||
"field" => "model_number",
|
||||
"searchable" => true,
|
||||
"sortable" => true,
|
||||
"title" => trans('admin/models/table.modelnumber'),
|
||||
"visible" => false
|
||||
], [
|
||||
"field" => "serial",
|
||||
"searchable" => true,
|
||||
"sortable" => true,
|
||||
"title" => trans('admin/hardware/form.serial'),
|
||||
"visible" => true,
|
||||
], [
|
||||
"field" => "depreciation",
|
||||
"searchable" => true,
|
||||
"sortable" => true,
|
||||
"title" => trans('general.depreciation'),
|
||||
"visible" => true,
|
||||
], [
|
||||
"field" => "number_of_months",
|
||||
"searchable" => true,
|
||||
"sortable" => true,
|
||||
"title" => trans('admin/depreciations/general.number_of_months'),
|
||||
"visible" => true,
|
||||
], [
|
||||
"field" => "status",
|
||||
"searchable" => true,
|
||||
"sortable" => true,
|
||||
"title" => trans('admin/hardware/table.status'),
|
||||
"visible" => true,
|
||||
], [
|
||||
"field" => "checked_out_to",
|
||||
"searchable" => true,
|
||||
"sortable" => true,
|
||||
"title" => trans('admin/hardware/table.checkoutto'),
|
||||
"visible" => false,
|
||||
], [
|
||||
"field" => "location",
|
||||
"searchable" => true,
|
||||
"sortable" => true,
|
||||
"title" => trans('admin/hardware/table.location'),
|
||||
"visible" => true,
|
||||
], [
|
||||
"field" => "manufacturer",
|
||||
"searchable" => true,
|
||||
"sortable" => true,
|
||||
"title" => trans('general.manufacturer'),
|
||||
"visible" => false,
|
||||
],[
|
||||
"field" => "supplier",
|
||||
"searchable" => true,
|
||||
"sortable" => true,
|
||||
"title" => trans('general.supplier'),
|
||||
"visible" => false,
|
||||
], [
|
||||
"field" => "purchase_date",
|
||||
"searchable" => true,
|
||||
"sortable" => true,
|
||||
"visible" => true,
|
||||
"title" => trans('general.purchase_date'),
|
||||
"formatter" => "dateDisplayFormatter"
|
||||
], [
|
||||
"field" => "currency",
|
||||
"searchable" => false,
|
||||
"sortable" => false,
|
||||
"visible" => false,
|
||||
"title" => 'Currency',
|
||||
], [
|
||||
"field" => "purchase_cost",
|
||||
"searchable" => true,
|
||||
"sortable" => true,
|
||||
"visible" => true,
|
||||
"title" => trans('general.purchase_cost'),
|
||||
"footerFormatter" => 'sumFormatter',
|
||||
], [
|
||||
"field" => "order_number",
|
||||
"searchable" => true,
|
||||
"sortable" => true,
|
||||
"visible" => false,
|
||||
"title" => trans('general.order_number'),
|
||||
], [
|
||||
"field" => "eol",
|
||||
"searchable" => false,
|
||||
"sortable" => false,
|
||||
"visible" => false,
|
||||
"title" => trans('general.eol'),
|
||||
"formatter" => "dateDisplayFormatter"
|
||||
], [
|
||||
"field" => "book_value",
|
||||
"searchable" => true,
|
||||
"sortable" => true,
|
||||
"visible" => true,
|
||||
"title" => trans('admin/hardware/table.book_value'),
|
||||
"footerFormatter" => 'sumFormatter',
|
||||
], [
|
||||
"field" => "monthly_depreciation",
|
||||
"searchable" => true,
|
||||
"sortable" => true,
|
||||
"visible" => true,
|
||||
"title" => trans('admin/hardware/table.monthly_depreciation')
|
||||
],[
|
||||
"field" => "diff",
|
||||
"searchable" => false,
|
||||
"sortable" => false,
|
||||
"visible" => true,
|
||||
"title" => trans('admin/hardware/table.diff'),
|
||||
"footerFormatter" => 'sumFormatter',
|
||||
],[
|
||||
"field" => "warranty_expires",
|
||||
"searchable" => false,
|
||||
"sortable" => false,
|
||||
"visible" => false,
|
||||
"title" => trans('admin/hardware/form.warranty_expires'),
|
||||
"formatter" => "dateDisplayFormatter"
|
||||
],
|
||||
];
|
||||
|
||||
return json_encode($layout);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generate html link to this items name.
|
||||
* @return string
|
||||
*/
|
||||
public function nameUrl()
|
||||
{
|
||||
return (string) link_to_route('hardware.show', e($this->name), $this->id);
|
||||
}
|
||||
|
||||
public function modelUrl()
|
||||
{
|
||||
if ($this->model->model) {
|
||||
return $this->model->model->present()->nameUrl();
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate img tag to this items image.
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function imageUrl()
|
||||
{
|
||||
$imagePath = '';
|
||||
if ($this->image && !empty($this->image)) {
|
||||
$imagePath = $this->image;
|
||||
$imageAlt = $this->name;
|
||||
} elseif ($this->model && !empty($this->model->image)) {
|
||||
$imagePath = $this->model->image;
|
||||
$imageAlt = $this->model->name;
|
||||
}
|
||||
$url = config('app.url');
|
||||
if (!empty($imagePath)) {
|
||||
$imagePath = '<img src="'.$url.'/uploads/assets/'.$imagePath.' height="50" width="50" alt="'.$imageAlt.'">';
|
||||
}
|
||||
return $imagePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate img tag to this items image.
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function imageSrc()
|
||||
{
|
||||
$imagePath = '';
|
||||
if ($this->image && !empty($this->image)) {
|
||||
$imagePath = $this->image;
|
||||
} elseif ($this->model && !empty($this->model->image)) {
|
||||
$imagePath = $this->model->image;
|
||||
}
|
||||
if (!empty($imagePath)) {
|
||||
return config('app.url').'/uploads/assets/'.$imagePath;
|
||||
}
|
||||
return $imagePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Displayable Name
|
||||
* @return string
|
||||
*
|
||||
* @todo this should be factored out - it should be subsumed by fullName (below)
|
||||
*
|
||||
**/
|
||||
public function name()
|
||||
{
|
||||
return $this->fullName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for notification polymorphism.
|
||||
* @return mixed
|
||||
*/
|
||||
public function fullName()
|
||||
{
|
||||
$str = '';
|
||||
|
||||
// Asset name
|
||||
if ($this->model->name) {
|
||||
$str .= $this->model->name;
|
||||
}
|
||||
|
||||
// Asset tag
|
||||
if ($this->asset_tag) {
|
||||
$str .= ' ('.$this->model->asset_tag.')';
|
||||
}
|
||||
|
||||
// Asset Model name
|
||||
if ($this->model->model) {
|
||||
$str .= ' - '.$this->model->model->name;
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
/**
|
||||
* Returns the date this item hits EOL.
|
||||
* @return false|string
|
||||
*/
|
||||
public function eol_date()
|
||||
{
|
||||
|
||||
if (( $this->purchase_date ) && ( $this->model->model ) && ($this->model->model->eol) ) {
|
||||
$date = date_create($this->purchase_date);
|
||||
date_add($date, date_interval_create_from_date_string($this->model->model->eol . ' months'));
|
||||
return date_format($date, 'Y-m-d');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* How many months until this asset hits EOL.
|
||||
* @return null
|
||||
*/
|
||||
public function months_until_eol()
|
||||
{
|
||||
|
||||
$today = date("Y-m-d");
|
||||
$d1 = new DateTime($today);
|
||||
$d2 = new DateTime($this->eol_date());
|
||||
|
||||
if ($this->eol_date() > $today) {
|
||||
$interval = $d2->diff($d1);
|
||||
} else {
|
||||
$interval = null;
|
||||
}
|
||||
|
||||
return $interval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* This handles the status label "meta" status of "deployed" if
|
||||
* it's assigned. Should maybe deprecate.
|
||||
*/
|
||||
public function statusMeta()
|
||||
{
|
||||
if ($this->model->assigned) {
|
||||
return 'deployed';
|
||||
}
|
||||
return $this->model->assetstatus->getStatuslabelType();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* This handles the status label "meta" status of "deployed" if
|
||||
* it's assigned. Should maybe deprecate.
|
||||
*/
|
||||
public function statusText()
|
||||
{
|
||||
if ($this->model->assigned) {
|
||||
return trans('general.deployed');
|
||||
}
|
||||
return $this->model->assetstatus->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* This handles the status label "meta" status of "deployed" if
|
||||
* it's assigned. Results look like:
|
||||
*
|
||||
* (if assigned and the status label is "Ready to Deploy"):
|
||||
* (Deployed)
|
||||
*
|
||||
* (f assigned and status label is not "Ready to Deploy":)
|
||||
* Deployed (Another Status Label)
|
||||
*
|
||||
* (if not deployed:)
|
||||
* Another Status Label
|
||||
*/
|
||||
public function fullStatusText() {
|
||||
// Make sure the status is valid
|
||||
if ($this->assetstatus) {
|
||||
|
||||
// If the status is assigned to someone or something...
|
||||
if ($this->model->assigned) {
|
||||
|
||||
// If it's assigned and not set to the default "ready to deploy" status
|
||||
if ($this->assetstatus->name != trans('general.ready_to_deploy')) {
|
||||
return trans('general.deployed'). ' (' . $this->model->assetstatus->name.')';
|
||||
}
|
||||
|
||||
// If it's assigned to the default "ready to deploy" status, just
|
||||
// say it's deployed - otherwise it's confusing to have a status that is
|
||||
// both "ready to deploy" and deployed at the same time.
|
||||
return trans('general.deployed');
|
||||
}
|
||||
|
||||
// Return just the status name
|
||||
return $this->model->assetstatus->name;
|
||||
}
|
||||
|
||||
// This status doesn't seem valid - either data has been manually edited or
|
||||
// the status label was deleted.
|
||||
return 'Invalid status';
|
||||
}
|
||||
|
||||
/**
|
||||
* Date the warantee expires.
|
||||
* @return false|string
|
||||
*/
|
||||
public function warrantee_expires()
|
||||
{
|
||||
if (($this->purchase_date) && ($this->warranty_months)) {
|
||||
$date = date_create($this->purchase_date);
|
||||
date_add($date, date_interval_create_from_date_string($this->warranty_months . ' months'));
|
||||
return date_format($date, 'Y-m-d');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Url to view this item.
|
||||
* @return string
|
||||
*/
|
||||
public function viewUrl()
|
||||
{
|
||||
return route('hardware.show', $this->id);
|
||||
}
|
||||
|
||||
public function glyph()
|
||||
{
|
||||
return '<i class="fas fa-barcode" aria-hidden="true"></i>';
|
||||
}
|
||||
}
|
|
@ -193,7 +193,7 @@ class LocationPresenter extends Presenter
|
|||
|
||||
public function glyph()
|
||||
{
|
||||
return '<i class="fa fa-map-marker" aria-hidden="true"></i>';
|
||||
return '<i class="fas fa-map-marker-alt" aria-hidden="true"></i>';
|
||||
}
|
||||
|
||||
public function fullName()
|
||||
|
|
|
@ -85,7 +85,7 @@ class ManufacturerPresenter extends Presenter
|
|||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => ' <span class="hidden-md hidden-lg">Assets</span>'
|
||||
.'<span class="hidden-xs"><i class="fa fa-barcode fa-lg"></i></span>',
|
||||
.'<span class="hidden-xs"><i class="fas fa-barcode fa-lg"></i></span>',
|
||||
'visible' => true,
|
||||
],
|
||||
[
|
||||
|
@ -94,7 +94,7 @@ class ManufacturerPresenter extends Presenter
|
|||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => ' <span class="hidden-md hidden-lg">Licenses</span>'
|
||||
.'<span class="hidden-xs"><i class="fa fa-floppy-o fa-lg"></i></span>',
|
||||
.'<span class="hidden-xs"><i class="far fa-save fa-lg"></i></span>',
|
||||
'visible' => true,
|
||||
],
|
||||
[
|
||||
|
@ -103,7 +103,7 @@ class ManufacturerPresenter extends Presenter
|
|||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => ' <span class="hidden-md hidden-lg">Consumables</span>'
|
||||
.'<span class="hidden-xs"><i class="fa fa-tint fa-lg"></i></span>',
|
||||
.'<span class="hidden-xs"><i class="fas fa-tint fa-lg"></i></span>',
|
||||
'visible' => true,
|
||||
],
|
||||
[
|
||||
|
@ -112,7 +112,7 @@ class ManufacturerPresenter extends Presenter
|
|||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => ' <span class="hidden-md hidden-lg">Accessories</span>'
|
||||
.'<span class="hidden-xs"><i class="fa fa-keyboard-o fa-lg"></i></span>',
|
||||
.'<span class="hidden-xs"><i class="far fa-keyboard fa-lg"></i></span>',
|
||||
'visible' => true,
|
||||
],
|
||||
[
|
||||
|
|
|
@ -312,7 +312,7 @@ class UserPresenter extends Presenter
|
|||
{
|
||||
if ($this->email) {
|
||||
return '<a href="mailto:'.$this->email.'">'.$this->email.'</a>'
|
||||
.'<a href="mailto:'.$this->email.'" class="hidden-xs hidden-sm"><i class="fa fa-envelope"></i></a>';
|
||||
.'<a href="mailto:'.$this->email.'" class="hidden-xs hidden-sm"><i class="far fa-envelope"></i></a>';
|
||||
}
|
||||
|
||||
return '';
|
||||
|
@ -386,6 +386,6 @@ class UserPresenter extends Presenter
|
|||
|
||||
public function glyph()
|
||||
{
|
||||
return '<i class="fa fa-user" aria-hidden="true"></i>';
|
||||
return '<i class="fas fa-user" aria-hidden="true"></i>';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,20 @@ class ValidationServiceProvider extends ServiceProvider
|
|||
}
|
||||
});
|
||||
|
||||
// Unique if undeleted for two columns
|
||||
// Same as unique_undeleted but taking the combination of two columns as unique constrain.
|
||||
Validator::extend('two_column_unique_undeleted', function ($attribute, $value, $parameters, $validator) {
|
||||
if (count($parameters)) {
|
||||
$count = DB::table($parameters[0])
|
||||
->select('id')->where($attribute, '=', $value)
|
||||
->whereNull('deleted_at')
|
||||
->where('id', '!=', $parameters[1])
|
||||
->where($parameters[2], $parameters[3])->count();
|
||||
|
||||
return $count < 1;
|
||||
}
|
||||
});
|
||||
|
||||
// Prevent circular references
|
||||
//
|
||||
// Example usage in Location model where parent_id references another Location:
|
||||
|
|
|
@ -157,7 +157,7 @@ class LdapAdConfiguration
|
|||
private function setLdapConnectionConfiguration(): array
|
||||
{
|
||||
// Create the configuration array.
|
||||
return [
|
||||
$ldap_settings = [
|
||||
// Mandatory Configuration Options
|
||||
'hosts' => $this->getServerUrlBase(),
|
||||
'base_dn' => $this->ldapSettings['ldap_basedn'],
|
||||
|
@ -181,6 +181,14 @@ class LdapAdConfiguration
|
|||
// LDAP_OPT_X_TLS_REQUIRE_CERT => LDAP_OPT_X_TLS_HARD,
|
||||
],
|
||||
];
|
||||
|
||||
if($this->ldapSettings['ldap_client_tls_cert'] || $this->ldapSettings['ldap_client_tls_key']) {
|
||||
$ldap_settings['custom_options'] = [
|
||||
LDAP_OPT_X_TLS_CERTFILE => Setting::get_client_side_cert_path(),
|
||||
LDAP_OPT_X_TLS_KEYFILE => Setting::get_client_side_key_path()
|
||||
];
|
||||
}
|
||||
return $ldap_settings;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
1036
composer.lock
generated
1036
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -250,6 +250,9 @@ return [
|
|||
|
||||
'enable_csp' => env('ENABLE_CSP', false),
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Demo Mode Lockdown
|
||||
|
@ -273,6 +276,7 @@ return [
|
|||
|
||||
'min_php' => '7.2.5',
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Autoloaded Service Providers
|
||||
|
@ -397,6 +401,8 @@ return [
|
|||
'Google2FA' => PragmaRX\Google2FALaravel\Facade::class,
|
||||
'Image' => Intervention\Image\ImageServiceProvider::class,
|
||||
'Carbon' => Carbon\Carbon::class,
|
||||
'Helper' => App\Helpers\Helper::class, // makes it much easier to use 'Helper::blah' in blades (which is where we usually use this)
|
||||
|
||||
|
||||
],
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ class UserFactory extends Factory
|
|||
'first_name' => 'Admin',
|
||||
'last_name' => 'User',
|
||||
'username' => 'admin',
|
||||
'avatar' => '1.jpg',
|
||||
'permissions' => '{"superuser":"1"}',
|
||||
];
|
||||
});
|
||||
|
@ -66,6 +67,7 @@ class UserFactory extends Factory
|
|||
'first_name' => 'Snipe E.',
|
||||
'last_name' => 'Head',
|
||||
'username' => 'snipe',
|
||||
'avatar' => '2.jpg',
|
||||
'email' => 'snipe@snipe.net',
|
||||
'permissions' => '{"superuser":"1"}',
|
||||
];
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateLicensesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('licenses', function ($table) {
|
||||
$table->increments('id');
|
||||
$table->string('name');
|
||||
$table->integer('model_id');
|
||||
$table->text('serial');
|
||||
$table->string('license_email');
|
||||
$table->string('license_name');
|
||||
$table->date('purchase_date')->nullable();
|
||||
$table->decimal('purchase_cost', 8, 2)->nullable();
|
||||
$table->string('order_number');
|
||||
$table->integer('assigned_to');
|
||||
$table->text('notes');
|
||||
$table->integer('user_id')->nullable();
|
||||
$table->timestamps();
|
||||
$table->engine = 'InnoDB';
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('licenses');
|
||||
}
|
||||
}
|
46
database/migrations/2013_11_15_190357_create_temp_licenses_table.php
Executable file
46
database/migrations/2013_11_15_190357_create_temp_licenses_table.php
Executable file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateTempLicensesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
|
||||
if (!Schema::hasTable('licenses')) {
|
||||
Schema::create('licenses', function ($table) {
|
||||
$table->increments('id');
|
||||
$table->string('name');
|
||||
$table->integer('model_id');
|
||||
$table->text('serial');
|
||||
$table->string('license_email');
|
||||
$table->string('license_name');
|
||||
$table->date('purchase_date')->nullable();
|
||||
$table->decimal('purchase_cost', 8, 2)->nullable();
|
||||
$table->string('order_number');
|
||||
$table->integer('assigned_to');
|
||||
$table->text('notes');
|
||||
$table->integer('user_id')->nullable();
|
||||
$table->timestamps();
|
||||
$table->engine = 'InnoDB';
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('licenses');
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@ class DropLicensesTable extends Migration
|
|||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::drop('licenses');
|
||||
Schema::dropIfExists('licenses');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -13,7 +13,7 @@ class AddShowInNavToStatusLabels extends Migration
|
|||
public function up()
|
||||
{
|
||||
Schema::table('status_labels', function (Blueprint $table) {
|
||||
$table->boolean('show_in_nav')->default(0);
|
||||
$table->boolean('show_in_nav')->nullable()->default(0);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ class AddDefaultFlagOnStatuslabels extends Migration
|
|||
public function up()
|
||||
{
|
||||
Schema::table('status_labels', function (Blueprint $table) {
|
||||
$table->boolean('default_label')->default(0);
|
||||
$table->boolean('default_label')->nullable()->default(0);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -15,9 +15,16 @@ class MoveAccessoryCheckoutNoteToJoinTable extends Migration
|
|||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('accessories_users', function (Blueprint $table) {
|
||||
$table->string('note')->nullable(true)->default(null);
|
||||
});
|
||||
|
||||
if (!Schema::hasColumn('accessories_users', 'note'))
|
||||
{
|
||||
Schema::table('accessories_users', function (Blueprint $table) {
|
||||
$table->string('note')->nullable(true)->default(null);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Loop through the checked out accessories, find their related action_log entry, and copy over the note
|
||||
// to the newly created note field
|
||||
|
@ -44,7 +51,9 @@ class MoveAccessoryCheckoutNoteToJoinTable extends Migration
|
|||
->where('target_id', '=', $join_log->assigned_to)
|
||||
->where('item_id', '=', $accessory->id)
|
||||
->where('target_type', '=', \App\Models\User::class)
|
||||
->where('item_type', '=','App\\Models\\Accessory')
|
||||
->where('action_type', '=', 'checkout')
|
||||
->where('note', '!=', '')
|
||||
->orderBy('created_at', 'DESC')->get();
|
||||
|
||||
\Log::debug($action_log_entries->count().' matching entries in the action_logs table');
|
||||
|
@ -74,8 +83,15 @@ class MoveAccessoryCheckoutNoteToJoinTable extends Migration
|
|||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('accessories_users', function (Blueprint $table) {
|
||||
$table->dropColumn('note');
|
||||
});
|
||||
|
||||
if (Schema::hasColumn('accessories_users', 'note'))
|
||||
{
|
||||
Schema::table('accessories_users', function (Blueprint $table)
|
||||
{
|
||||
$table->dropColumn('note');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ class AddDigitSeparatorToSettings extends Migration
|
|||
public function up()
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
$table->char('digit_separator')->nullable()->default('1234.56');
|
||||
$table->char('digit_separator')->nullable()->default('1,234.56');
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddClientSideLDAPCertToSettings extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
$table->text('ldap_client_tls_cert')->nullable()->default(null);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
$table->dropColumn('ldap_client_tls_cert');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddClientSideLDAPKeyToSettings extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
$table->text("ldap_client_tls_key")->nullable()->default(null);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
$table->dropColumn("ldap_client_tls_key");
|
||||
});
|
||||
}
|
||||
}
|
|
@ -29,4 +29,4 @@ class AddDepreciationMinimumValue extends Migration
|
|||
$table->dropColumn('depreciation_min');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue