mirror of
https://github.com/Karaka-Management/oms-Billing.git
synced 2026-01-29 15:58:41 +00:00
update composer and some item/client impl.
This commit is contained in:
parent
773bb2a574
commit
12e69aedeb
6
.directory
Normal file
6
.directory
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
[Dolphin]
|
||||
Timestamp=2021,2,7,12,37,21
|
||||
Version=4
|
||||
|
||||
[Settings]
|
||||
HiddenFilesShown=true
|
||||
35
.github/dev_bug_report.md
vendored
Executable file
35
.github/dev_bug_report.md
vendored
Executable file
|
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
name: Dev Bug Report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: stat_backlog, type_bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
# Bug Description
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
# How to Reproduce
|
||||
|
||||
Steps to reproduce the behavior:
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
## Minimal Code Example
|
||||
|
||||
```
|
||||
// your code ...
|
||||
```
|
||||
|
||||
# Expected Behavior
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
# Screenshots
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
# Additional Information
|
||||
Add any other context about the problem here.
|
||||
18
.github/dev_feature_request.md
vendored
Executable file
18
.github/dev_feature_request.md
vendored
Executable file
|
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
name: Dev Feature Request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: stat_backlog, type_feature
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
# What is the feature you request
|
||||
* A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
* A clear and concise description of what you want to happen.
|
||||
|
||||
# Alternatives
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
# Additional Information
|
||||
Add any other context or screenshots about the feature request here.
|
||||
34
.github/user_bug_report.md
vendored
Executable file
34
.github/user_bug_report.md
vendored
Executable file
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
name: User Bug Report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: stat_backlog, type_bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
# Bug Description
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
# How 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.
|
||||
|
||||
# System Information
|
||||
- System: [e.g. PC or iPhone11, ...]
|
||||
- OS: [e.g. iOS]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Orange Management Version [e.g. 22]
|
||||
|
||||
# Additional Information
|
||||
Add any other context about the problem here.
|
||||
18
.github/user_feature_request.md
vendored
Executable file
18
.github/user_feature_request.md
vendored
Executable file
|
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
name: User Feature Request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: stat_backlog, type_feature
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
# What is the feature you request
|
||||
* A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
* A clear and concise description of what you want to happen.
|
||||
|
||||
# Alternatives
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
# Additional Information
|
||||
Add any other context or screenshots about the feature request here.
|
||||
13
.github/workflows/greetings.yml
vendored
Executable file
13
.github/workflows/greetings.yml
vendored
Executable file
|
|
@ -0,0 +1,13 @@
|
|||
name: Greetings
|
||||
|
||||
on: [pull_request, issues]
|
||||
|
||||
jobs:
|
||||
greeting:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/first-interaction@v1
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-message: 'Thank you for createing this issue. We will check it as soon as possible.'
|
||||
pr-message: 'Thank you for your pull request. We will check it as soon as possible.'
|
||||
24
.github/workflows/image.yml
vendored
Executable file
24
.github/workflows/image.yml
vendored
Executable file
|
|
@ -0,0 +1,24 @@
|
|||
name: Compress images
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- '**.jpg'
|
||||
- '**.png'
|
||||
- '**.webp'
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.jpg'
|
||||
- '**.png'
|
||||
- '**.webp'
|
||||
jobs:
|
||||
build:
|
||||
name: calibreapp/image-actions
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@master
|
||||
|
||||
- name: Compress Images
|
||||
uses: calibreapp/image-actions@master
|
||||
with:
|
||||
githubToken: ${{ secrets.GITHUB_TOKEN }}
|
||||
118
.github/workflows/main.yml
vendored
Executable file
118
.github/workflows/main.yml
vendored
Executable file
|
|
@ -0,0 +1,118 @@
|
|||
name: CI/CD
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
autoformat:
|
||||
runs-on: ubuntu-latest
|
||||
if: "!contains(github.event.head_commit.message, 'NO_CI')"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 3
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@master
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Get Composer Cache Directory
|
||||
id: composer-cache
|
||||
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ${{ steps.composer-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: ${{ runner.os }}-composer-
|
||||
- name: Setup Composer
|
||||
run: composer install
|
||||
- name: Autoformat
|
||||
run: 'vendor/bin/php-cs-fixer fix ./ --rules=''{"array_syntax": {"syntax": "short"}, "blank_line_after_namespace": true, "binary_operator_spaces": {"operators": {"=": "align", ".=": "align", "+=": "align", "-=": "align", "*=": "align", "/=": "align", "|=": "align", "&=": "align", "=>": "align", "??=": "align"}}, "cast_spaces": {"space": "single"}, "class_attributes_separation": { "elements": ["const", "method", "property"] }, "combine_consecutive_issets": true, "compact_nullable_typehint": true, "declare_strict_types": true, "declare_equal_normalize": {"space": "none"}, "elseif": true, "encoding": true, "explicit_indirect_variable": true, "explicit_string_variable": true, "function_to_constant": true, "implode_call": true, "increment_style": {"style": "pre"}, "is_null": {"use_yoda_style": false}, "line_ending": true, "logical_operators": true, "lowercase_cast": true, "lowercase_constants": true, "lowercase_keywords": true, "modernize_types_casting": true, "native_constant_invocation": true, "native_function_casing": true, "native_function_invocation": true, "new_with_braces": true, "no_extra_blank_lines": ["break", "case", "continue", "curly_brace_block", "extra", "return", "switch", "throw", "use"], "no_spaces_after_function_name": true, "no_alias_functions": true, "no_closing_tag": true, "no_empty_comment": true, "no_empty_phpdoc": true, "no_empty_statement": true, "no_homoglyph_names": true, "no_mixed_echo_print": {"use": "echo"}, "no_php4_constructor": true, "no_singleline_whitespace_before_semicolons": true, "no_spaces_inside_parenthesis": true, "no_trailing_whitespace": true, "no_unneeded_final_method": true, "no_unused_imports": true, "no_useless_return": true, "no_whitespace_before_comma_in_array": true, "no_whitespace_in_blank_line": true, "non_printable_character": true, "normalize_index_brace": true, "ordered_imports": {"sort_algorithm": "alpha"}, "ordered_interfaces": {"order": "alpha"}, "php_unit_construct": true, "php_unit_internal_class": true, "php_unit_ordered_covers": true, "php_unit_set_up_tear_down_visibility": true, "phpdoc_indent": true, "phpdoc_align": {"align": "vertical"}, "phpdoc_annotation_without_dot": true, "phpdoc_scalar": true, "phpdoc_return_self_reference": {"this": "self"}, "phpdoc_trim": true, "phpdoc_trim_consecutive_blank_line_separation": true, "random_api_migration": true, "self_accessor": true, "return_type_declaration": {"space_before": "one"}, "semicolon_after_instruction": true, "set_type_to_cast": true, "short_scalar_cast": true, "single_blank_line_at_eof": true, "single_line_after_imports": true, "standardize_increment": true, "trailing_comma_in_multiline_array": true, "trim_array_spaces": true, "visibility_required": true, "void_return": true}'' --allow-risky=yes'
|
||||
- name: Check for modified files
|
||||
id: git-check
|
||||
run: echo ::set-output name=modified::$(if git diff-index --quiet HEAD --; then echo "false"; else echo "true"; fi)
|
||||
- name: Push changes
|
||||
if: steps.git-check.outputs.modified == 'true'
|
||||
run: |
|
||||
git config --global user.name 'Formatter Bot'
|
||||
git config --global user.email 'formatter.bot@orange-management.email'
|
||||
git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
|
||||
git commit -am "Automated formatting changes"
|
||||
git push
|
||||
code-tests:
|
||||
runs-on: ubuntu-latest
|
||||
if: "!contains(github.event.head_commit.message, 'NO_CI')"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 3
|
||||
matrix:
|
||||
php-versions: ['8.0']
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@master
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Checkout Build Repository
|
||||
uses: actions/checkout@master
|
||||
with:
|
||||
fetch-depth: 1
|
||||
ref: develop
|
||||
repository: Orange-Management/Build
|
||||
path: Build
|
||||
- name: Setup PHP, with composer and extensions
|
||||
uses: shivammathur/setup-php@master
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
extensions: mbstring, gd, zip, dom, mysql, pgsql, sqlite, imap, bcmath, redis, memcached
|
||||
ini-values: opcache.jit_buffer_size=256M, opcache.jit=1235, pcre.jit=1
|
||||
- name: Get Composer Cache Directory
|
||||
id: composer-cache
|
||||
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ${{ steps.composer-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: ${{ runner.os }}-composer-
|
||||
- name: Setup Composer
|
||||
run: composer install
|
||||
- name: phpcs
|
||||
run: vendor/bin/phpcs ./ --standard="Build/Config/phpcs.xml" -s --report=full
|
||||
custom:
|
||||
runs-on: ubuntu-latest
|
||||
if: "!contains(github.event.head_commit.message, 'NO_CI')"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 3
|
||||
matrix:
|
||||
php-versions: ['8.0']
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@master
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Checkout Build Repository
|
||||
uses: actions/checkout@master
|
||||
with:
|
||||
fetch-depth: 1
|
||||
ref: develop
|
||||
repository: Orange-Management/Build
|
||||
path: Build
|
||||
- name: Setup PHP, with composer and extensions
|
||||
uses: shivammathur/setup-php@master
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
extensions: mbstring, gd, zip, dom, mysql, pgsql, sqlite, imap, bcmath, redis, memcached
|
||||
ini-values: opcache.jit_buffer_size=256M, opcache.jit=1235, pcre.jit=1
|
||||
- name: PHP linting
|
||||
run: find ./ -type f -name '*.php' -print0 | xargs -0 -n1 -P4 php -l -n | (! grep -v "No syntax errors detected" )
|
||||
- name: Php strict
|
||||
run: if [[ $(grep -r -L "declare(strict_types=1);" --include=*.php --exclude={*.tpl.php,*Hooks.php,*Routes.php,*SearchCommands.php} ./) -ne "" ]]; then exit 1; fi
|
||||
- name: Html inspection
|
||||
run: |
|
||||
if [[ $(find ./ -name "*tpl.php" | xargs grep -E '=\"[\#\$\%\^\&\*\(\)\\/\ ]*\"') -ne "" ]]; then exit 1; fi
|
||||
if [[ $(find ./ -name "*tpl.php" | xargs grep -P '(\<img)((?!.*?alt=).)*(>)') -ne "" ]]; then exit 1; fi
|
||||
- name: Js strict
|
||||
run: if [[ $(grep -r -L "\"use strict\";" --include=*.js ./) -ne "" ]]; then exit 1; fi
|
||||
- name: Js inspection
|
||||
run: |
|
||||
if [[ $(grep -rlni "onafterprint=\|onbeforeprint=\|onbeforeunload=\|onerror=\|onhaschange=\|onload=\|onmessage=\|onoffline=\|ononline=\|onpagehide=\|onpageshow=\|onpopstate=\|onredo=\|onresize=\|onstorage=\|onund=o\|onunload=\|onblur=\|onchage=\|oncontextmenu=\|onfocus=\|onformchange=\|onforminput=\|oninput=\|oninvalid=\|onreset=\|onselect=\|onsubmit=\|onkeydown=\|onkeypress=\|onkeyup=\|onclick=\|ondblclic=k\|ondrag=\|ondragend=\|ondragenter=\|ondragleave=\|ondragover=\|ondragstart=\|ondrop=\|onmousedown=\|onmousemove=\|onmouseout=\|onmouseover=\|onmouseup=\|onmousewheel=\|onscroll=\|onabor=t\|oncanplay=\|oncanplaythrough=\|ondurationchange=\|onemptied=\|onended=\|onerror=\|onloadeddata=\|onloadedmetadata=\|onloadstart=\|onpause=\|onplay=\|onplaying=\|onprogress=\|onratechange=\|onreadystatechange=\|onseeked=\|onseeking=\|onstalled=\|onsuspend=\|ontimeupdate=\|onvolumechange=" --include=*.js ./) -ne "" ]]; then exit 1; fi
|
||||
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
vendor
|
||||
|
|
@ -88,7 +88,8 @@ final class ApiController extends Controller
|
|||
$bill = new Bill();
|
||||
$bill->setCreatedBy(new NullAccount($request->header->account));
|
||||
$bill->number = '{y}-{id}'; // @todo: use admin defined format
|
||||
$bill->billTo = $request->getData('billto') ?? $client->profile->account->name1; // @todo: use defaultInvoiceAddress or mainAddress
|
||||
$bill->billTo = $request->getData('billto')
|
||||
?? ($client->profile->account->name1 . (!empty($client->profile->account->name2) ? ', ' . $client->profile->account->name2 : '')); // @todo: use defaultInvoiceAddress or mainAddress. also consider to use billto1, billto2, billto3 (for multiple lines e.g. name2, fao etc.)
|
||||
$bill->billCountry = $request->getData('billtocountry') ?? $client->mainAddress->getCountry();
|
||||
$bill->type = new NullBillType((int) $request->getData('type'));
|
||||
$bill->client = new NullClient((int) $request->getData('client'));
|
||||
|
|
@ -171,22 +172,30 @@ final class ApiController extends Controller
|
|||
$element->bill = (int) $request->getData('bill');
|
||||
$element->item = $request->getData('item', 'int');
|
||||
|
||||
if ($element->item !== null) {
|
||||
$item = ItemMapper::withConditional('language', $response->getLanguage())::get($element->item);
|
||||
// @todo: which item name should be stored in the database? server language (problem for international company with subsidiaries)? customer default language/customer invoice language?
|
||||
$element->itemNumber = $item->number;
|
||||
$element->itemName = $item->getL11n('name1')->description;
|
||||
$element->quantity = $request->getData('quantity', 'int');
|
||||
|
||||
$element->singleSalesPriceNet = new Money($request->getData('singlesalespricenet', 'int') ?? $item->salesPrice->getInt());
|
||||
$element->totalSalesPriceNet = clone $element->singleSalesPriceNet;
|
||||
$element->totalSalesPriceNet->mult($element->quantity);
|
||||
|
||||
$element->singlePurchasePriceNet = new Money($item->purchasePrice->getInt());
|
||||
$element->totalPurchasePriceNet = clone $element->singlePurchasePriceNet;
|
||||
$element->totalPurchasePriceNet->mult($element->quantity);
|
||||
if ($element->item === null) {
|
||||
return $element;
|
||||
}
|
||||
|
||||
$item = ItemMapper::withConditional('language', $response->getLanguage())::get($element->item);
|
||||
// @todo: which item name should be stored in the database? server language (problem for international company with subsidiaries)? customer default language/customer invoice language?
|
||||
$element->itemNumber = $item->number;
|
||||
$element->itemName = $item->getL11n('name1')->description;
|
||||
$element->quantity = $request->getData('quantity', 'int');
|
||||
|
||||
$element->singleSalesPriceNet = new Money($request->getData('singlesalespricenet', 'int') ?? $item->salesPrice->getInt());
|
||||
$element->totalSalesPriceNet = clone $element->singleSalesPriceNet;
|
||||
$element->totalSalesPriceNet->mult($element->quantity);
|
||||
|
||||
// discounts
|
||||
if ($request->getData('discount_percentage') !== null) {
|
||||
$element->singleSalesPriceNet->sub((int) ($element->singleSalesPriceNet->getInt() / 100 * $request->getData('discount_percentage', 'int')));
|
||||
$element->totalSalesPriceNet->sub((int) ($element->totalSalesPriceNet->getInt() / 100 * $request->getData('discount_percentage', 'int')));
|
||||
}
|
||||
|
||||
$element->singlePurchasePriceNet = new Money($item->purchasePrice->getInt());
|
||||
$element->totalPurchasePriceNet = clone $element->singlePurchasePriceNet;
|
||||
$element->totalPurchasePriceNet->mult($element->quantity);
|
||||
|
||||
return $element;
|
||||
}
|
||||
|
||||
|
|
@ -205,6 +214,7 @@ final class ApiController extends Controller
|
|||
{
|
||||
if ($type === 1) {
|
||||
$bill->net->add($element->singleSalesPriceNet);
|
||||
$bill->costs->add($element->singlePurchasePriceNet);
|
||||
}
|
||||
|
||||
return $bill;
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ final class BillMapper extends DataMapperAbstract
|
|||
$result = $query->select('SUM(billing_out_element_total_salesprice_net)')
|
||||
->from(self::$table)
|
||||
->leftJoin(BillElementMapper::getTable())
|
||||
->on(self::$table . '.billing_out_id', '=', BillElementMapper::getTable() . '.billing_out_element_bill')
|
||||
->on(self::$table . '.billing_out_id', '=', BillElementMapper::getTable() . '.billing_out_element_bill')
|
||||
->where(BillElementMapper::getTable() . '.billing_out_element_item', '=', $id)
|
||||
->andWhere(self::$table . '.billing_out_performance_date', '>=', $start)
|
||||
->andWhere(self::$table . '.billing_out_performance_date', '<=', $end)
|
||||
|
|
@ -157,13 +157,27 @@ final class BillMapper extends DataMapperAbstract
|
|||
return new Money((int) $result[0]);
|
||||
}
|
||||
|
||||
public static function getSalesByClientId(int $id, \DateTime $start, \DateTime $end) : Money
|
||||
{
|
||||
$query = new Builder(self::$db);
|
||||
$result = $query->select('SUM(billing_out_net)')
|
||||
->from(self::$table)
|
||||
->where(self::$table . '.billing_out_client', '=', $id)
|
||||
->andWhere(self::$table . '.billing_out_performance_date', '>=', $start)
|
||||
->andWhere(self::$table . '.billing_out_performance_date', '<=', $end)
|
||||
->execute()
|
||||
->fetch();
|
||||
|
||||
return new Money((int) $result[0]);
|
||||
}
|
||||
|
||||
public static function getAvgSalesPriceByItemId(int $id, \DateTime $start, \DateTime $end) : Money
|
||||
{
|
||||
$query = new Builder(self::$db);
|
||||
$result = $query->select('SUM(billing_out_element_single_salesprice_net)', 'COUNT(billing_out_element_total_salesprice_net)')
|
||||
->from(self::$table)
|
||||
->leftJoin(BillElementMapper::getTable())
|
||||
->on(self::$table . '.billing_out_id', '=', BillElementMapper::getTable() . '.billing_out_element_bill')
|
||||
->on(self::$table . '.billing_out_id', '=', BillElementMapper::getTable() . '.billing_out_element_bill')
|
||||
->where(BillElementMapper::getTable() . '.billing_out_element_item', '=', $id)
|
||||
->andWhere(self::$table . '.billing_out_performance_date', '>=', $start)
|
||||
->andWhere(self::$table . '.billing_out_performance_date', '<=', $end)
|
||||
|
|
@ -180,7 +194,7 @@ final class BillMapper extends DataMapperAbstract
|
|||
$result = $query->select('billing_out_performance_date')
|
||||
->from(self::$table)
|
||||
->leftJoin(BillElementMapper::getTable())
|
||||
->on(self::$table . '.billing_out_id', '=', BillElementMapper::getTable() . '.billing_out_element_bill')
|
||||
->on(self::$table . '.billing_out_id', '=', BillElementMapper::getTable() . '.billing_out_element_bill')
|
||||
->where(BillElementMapper::getTable() . '.billing_out_element_item', '=', $id)
|
||||
->orderBy('billing_out_id', 'DESC')
|
||||
->limit(1)
|
||||
|
|
@ -190,6 +204,21 @@ final class BillMapper extends DataMapperAbstract
|
|||
return new \DateTimeImmutable($result[0]);
|
||||
}
|
||||
|
||||
public static function getLastOrderDateByClientId(int $id) : \DateTimeImmutable
|
||||
{
|
||||
// @todo: only delivers/invoice/production (no offers ...)
|
||||
$query = new Builder(self::$db);
|
||||
$result = $query->select('billing_out_performance_date')
|
||||
->from(self::$table)
|
||||
->where(self::$table . '.billing_out_client', '=', $id)
|
||||
->orderBy('billing_out_id', 'DESC')
|
||||
->limit(1)
|
||||
->execute()
|
||||
->fetch();
|
||||
|
||||
return new \DateTimeImmutable($result[0]);
|
||||
}
|
||||
|
||||
public static function getItemRetentionRate(int $id, \DateTime $start, \DateTime $end) : float
|
||||
{
|
||||
|
||||
|
|
@ -208,7 +237,7 @@ final class BillMapper extends DataMapperAbstract
|
|||
|
||||
$query ??= self::getQuery(null, [], RelationType::ALL, $depth);
|
||||
$query->leftJoin(BillElementMapper::getTable(), BillElementMapper::getTable() . '_' . $depth)
|
||||
->on(self::$table . '_' . $depth . '.billing_out_id', '=', BillElementMapper::getTable() . '_' . $depth . '.billing_out_element_bill')
|
||||
->on(self::$table . '_' . $depth . '.billing_out_id', '=', BillElementMapper::getTable() . '_' . $depth . '.billing_out_element_bill')
|
||||
->where(BillElementMapper::getTable() . '_' . $depth . '.billing_out_element_item', '=', $id)
|
||||
->limit($limit);
|
||||
|
||||
|
|
@ -221,6 +250,25 @@ final class BillMapper extends DataMapperAbstract
|
|||
return self::getAllByQuery($query, RelationType::ALL, $depth);
|
||||
}
|
||||
|
||||
public static function getNewestClientInvoices(int $id, int $limit = 10) : array
|
||||
{
|
||||
$depth = 3;
|
||||
|
||||
// @todo: limit is not working correctly... only returns / 2 or something like that?. Maybe because bills arent unique?
|
||||
|
||||
$query ??= self::getQuery(null, [], RelationType::ALL, $depth);
|
||||
$query->where(self::$table . '_' . $depth . '.billing_out_client', '=', $id)
|
||||
->limit($limit);
|
||||
|
||||
if (!empty(self::$createdAt)) {
|
||||
$query->orderBy(self::$table . '_' . $depth . '.' . self::$columns[self::$createdAt]['name'], 'DESC');
|
||||
} else {
|
||||
$query->orderBy(self::$table . '_' . $depth . '.' . self::$columns[self::$primaryField]['name'], 'DESC');
|
||||
}
|
||||
|
||||
return self::getAllByQuery($query, RelationType::ALL, $depth);
|
||||
}
|
||||
|
||||
public static function getItemTopCustomers(int $id, \DateTime $start, \DateTime $end, int $limit = 10) : array
|
||||
{
|
||||
$depth = 3;
|
||||
|
|
@ -306,4 +354,23 @@ final class BillMapper extends DataMapperAbstract
|
|||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function getClientMonthlySalesCosts(int $id, \DateTime $start, \DateTime $end) : array
|
||||
{
|
||||
$query = new Builder(self::$db);
|
||||
$result = $query->selectAs('SUM(billing_out_net)', 'net_sales')
|
||||
->selectAs('SUM(billing_out_costs)', 'net_costs')
|
||||
->selectAs('YEAR(billing_out_performance_date)', 'year')
|
||||
->selectAs('MONTH(billing_out_performance_date)', 'month')
|
||||
->from(self::$table)
|
||||
->where(self::$table . '.billing_out_client', '=', $id)
|
||||
->andWhere(self::$table . '.billing_out_performance_date', '>=', $start)
|
||||
->andWhere(self::$table . '.billing_out_performance_date', '<=', $end)
|
||||
->groupBy('year', 'month')
|
||||
->orderBy(['year', 'month'], ['ASC', 'ASC'])
|
||||
->execute()
|
||||
->fetchAll();
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
20
composer.json
Normal file
20
composer.json
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"name": "orange-management/module",
|
||||
"description": "Module for Orange Management.",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Dennis Eichhorn",
|
||||
"email": "spl1nes.com@googlemail.com"
|
||||
}
|
||||
],
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": ">=9.4",
|
||||
"friendsofphp/php-cs-fixer": ">=2.18",
|
||||
"squizlabs/php_codesniffer": ">=3.5",
|
||||
"phpmd/phpmd": ">=2.9",
|
||||
"phpstan/phpstan": ">=0.12.58",
|
||||
"phan/phan": ">=3.2.6"
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true
|
||||
}
|
||||
4777
composer.lock
generated
Normal file
4777
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user