diff --git a/Admin/Install/Media/bill.pdf.php b/Admin/Install/Media/bill.pdf.php
index 5f571e9..f19a9ab 100755
--- a/Admin/Install/Media/bill.pdf.php
+++ b/Admin/Install/Media/bill.pdf.php
@@ -43,22 +43,22 @@ $pdf->setSubject($this->data['bill_subtitle'] ?? '');
$pdf->setKeywords(\implode(', ', $this->data['keywords'] ?? []));
$pdf->language = $bill->language;
-$pdf->attributes['legal_name'] = $this->data['legal_company_name'] ?? 'Jingga e.K.';
+$pdf->attributes['legal_name'] = $this->data['legal_company_name'] ?? 'Jingga e. K.';
$pdf->attributes['address'] = $this->data['bill_company_address'] ?? 'Gartenstr. 26';
-$pdf->attributes['city'] = $this->data['bill_company_city'] ?? '61206 Woellstadt';
+$pdf->attributes['city'] = $this->data['bill_company_city'] ?? '61206 Wöllstadt';
$pdf->attributes['ceo'] = $this->data['bill_company_ceo'] ?? 'Dennis Eichhorn';
-$pdf->attributes['tax_office'] = $this->data['bill_company_tax_office'] ?? 'HRB ???';
-$pdf->attributes['tax_number'] = $this->data['bill_company_tax_id'] ?? '123456789';
+$pdf->attributes['tax_office'] = $this->data['bill_company_tax_office'] ?? 'HRA 5058';
+$pdf->attributes['tax_number'] = $this->data['bill_company_tax_id'] ?? '16 814 6253 3';
$pdf->attributes['terms'] = $this->data['bill_company_terms'] ?? 'https://jingga.app/terms';
$pdf->attributes['bank_name'] = $this->data['bill_company_bank_name'] ?? 'Volksbank Mittelhessen';
-$pdf->attributes['swift'] = $this->data['bill_company_swift'] ?? '.....';
-$pdf->attributes['bank_account'] = $this->data['bill_company_bank_account'] ?? '.....';
+$pdf->attributes['swift'] = $this->data['bill_company_swift'] ?? 'VBMHDE5F';
+$pdf->attributes['bank_account'] = $this->data['bill_company_bank_account'] ?? 'DE62 5139 0000 0084 8044 10';
$pdf->attributes['website'] = $this->data['bill_company_website'] ?? 'www.jingga.app';
$pdf->attributes['email'] = $this->data['bill_company_email'] ?? 'info@jingga.app';
-$pdf->attributes['phone'] = $this->data['bill_company_phone'] ?? '+49 0152 ????';
+$pdf->attributes['phone'] = $this->data['bill_company_phone'] ?? '+49 152 04337728';
$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
@@ -290,6 +290,10 @@ $pdf->setFont('helvetica', 'B', 8);
$pdf->Write(0, $lang[$pdf->language]['Currency'] . ': ' . $bill->currency, '', 0, 'L', false, 0, false, false, 0);
$pdf->Ln();
+$pdf->setFont('helvetica', 'B', 8);
+$pdf->Write(0, $lang[$pdf->language]['TaxRemark'], '', 0, 'L', false, 0, false, false, 0);
+$pdf->Ln();
+
$pdf->setFont('helvetica', '', 8);
$pdf->Write(0, $bill->termsText, '', 0, 'L', false, 0, false, false, 0);
$pdf->Ln();
diff --git a/Admin/Install/Media/lang.php b/Admin/Install/Media/lang.php
index 6fbaa17..38f26e0 100755
--- a/Admin/Install/Media/lang.php
+++ b/Admin/Install/Media/lang.php
@@ -33,6 +33,7 @@ return [
'Taxes' => 'Taxes',
'Terms' => 'Terms',
'PaymentTerms' => 'Payment Terms',
+ 'TaxRemark' => 'No sales tax will be charged in accordance with §19 (1) UStG.',
],
'de' => [
'InvoiceNo' => 'Belegnummer',
@@ -52,5 +53,6 @@ return [
'Taxes' => 'USt',
'Terms' => 'AGB',
'PaymentTerms' => 'Zahlungsbedingungen',
+ 'TaxRemark' => 'Es wird gemäß §19 Abs. 1 UStG keine Umsatzsteuer berechnet.',
],
];
diff --git a/Admin/Install/Messages.install.json b/Admin/Install/Messages.install.json
index e076a08..7608fba 100755
--- a/Admin/Install/Messages.install.json
+++ b/Admin/Install/Messages.install.json
@@ -9,13 +9,13 @@
"l11n": {
"en": {
"subject": "Billing",
- "body": "
BillingBillingDear {user_name}, Thank you for for doing business with us. Attached kindly find your bill. Jingga e.K. - www.jingga.app - CEO Dennis Eichhorn |
|
",
- "bodyalt": "Dear {user_name},\n\nThank you for doing business with us.\n\nAttached kindly find your bill.\n\n\nJingga e.K. - www.jingga.app - CEO Dennis Eichhorn"
+ "body": "BillingBillingDear {user_name}, Thank you for for doing business with us. Attached kindly find your bill. Jingga e.K. - www.jingga.app - CEO Dennis Eichhorn - Amtsgericht Friedberg HRA 5058 |
|
",
+ "bodyalt": "Dear {user_name},\n\nThank you for doing business with us.\n\nAttached kindly find your bill.\n\n\nJingga e.K. - www.jingga.app - CEO Dennis Eichhorn - Amtsgericht Friedberg HRA 5058"
},
"de": {
"subject": "Rechnungsstellung",
- "body": "AbrechnungAbrechnungSehr geehrte/r {user_name}, Vielen Dank für Ihre Geschäftsbeziehung mit uns. Im Anhang finden Sie Ihre Rechnung. Jingga e.K. - www.jingga.app - CEO Dennis Eichhorn |
|
",
- "bodyalt": "Sehr geehrte/r {user_name},\n\nvielen Dank für Ihre Geschäftsbeziehung mit uns.\n\nIm Anhang finden Sie freundlicherweise Ihre Rechnung.\n\n\nJingga e.K. - www.jingga.app - CEO Dennis Eichhorn"
+ "body": "AbrechnungAbrechnungSehr geehrte/r {user_name}, Vielen Dank für Ihre Geschäftsbeziehung mit uns. Im Anhang finden Sie Ihre Rechnung. Jingga e.K. - www.jingga.app - CEO Dennis Eichhorn - Amtsgericht Friedberg HRA 5058 |
|
",
+ "bodyalt": "Sehr geehrte/r {user_name},\n\nvielen Dank für Ihre Geschäftsbeziehung mit uns.\n\nIm Anhang finden Sie freundlicherweise Ihre Rechnung.\n\n\nJingga e.K. - www.jingga.app - CEO Dennis Eichhorn - Amtsgericht Friedberg HRA 5058"
}
},
"send": false
diff --git a/Admin/Install/db.json b/Admin/Install/db.json
index 71460d9..7e9fa21 100755
--- a/Admin/Install/db.json
+++ b/Admin/Install/db.json
@@ -312,6 +312,12 @@
"type": "TINYINT(1)",
"null": false
},
+ "billing_type_transfer_sign": {
+ "description": "1 = from->to direction, -1 = to->from direction = credit note",
+ "name": "billing_type_transfer_sign",
+ "type": "TINYINT(1)",
+ "null": false
+ },
"billing_type_account_format": {
"name": "billing_type_account_format",
"type": "VARCHAR(255)",
diff --git a/Controller/ApiAttributeController.php b/Controller/ApiAttributeController.php
index c2f8536..21f4c8e 100755
--- a/Controller/ApiAttributeController.php
+++ b/Controller/ApiAttributeController.php
@@ -327,7 +327,7 @@ final class ApiAttributeController extends Controller
return;
}
- /** @var \Modules\Billing\Models\BillAttributeTypeL11n $billAttributeTypeL11n */
+ /** @var BaseStringL11n $billAttributeTypeL11n */
$billAttributeTypeL11n = BillAttributeTypeL11nMapper::get()->where('id', (int) $request->getData('id'))->execute();
$this->deleteModel($request->header->account, $billAttributeTypeL11n, BillAttributeTypeL11nMapper::class, 'bill_attribute_type_l11n', $request->getOrigin());
$this->createStandardDeleteResponse($request, $response, $billAttributeTypeL11n);
@@ -387,7 +387,7 @@ final class ApiAttributeController extends Controller
return;
}
- /** @var \Modules\Billing\Models\BillAttributeType $billAttributeType */
+ /** @var AttributeType $billAttributeType */
$billAttributeType = BillAttributeTypeMapper::get()->where('id', (int) $request->getData('id'))->execute();
$this->deleteModel($request->header->account, $billAttributeType, BillAttributeTypeMapper::class, 'bill_attribute_type', $request->getOrigin());
$this->createStandardDeleteResponse($request, $response, $billAttributeType);
@@ -418,7 +418,7 @@ final class ApiAttributeController extends Controller
/** @var AttributeValue $old */
$old = BillAttributeValueMapper::get()->where('id', (int) $request->getData('id'))->execute();
- /** @var \Modules\Attribute\Models\Attribute $type */
+ /** @var \Modules\Attribute\Models\Attribute $attr */
$attr = BillAttributeMapper::get()
->with('type')
->where('id', $request->getDataInt('attribute') ?? 0)
@@ -514,7 +514,7 @@ final class ApiAttributeController extends Controller
return;
}
- /** @var \Modules\Billing\Models\BillAttributeValueL11n $billAttributeValueL11n */
+ /** @var BaseStringL11n $billAttributeValueL11n */
$billAttributeValueL11n = BillAttributeValueL11nMapper::get()->where('id', (int) $request->getData('id'))->execute();
$this->deleteModel($request->header->account, $billAttributeValueL11n, BillAttributeValueL11nMapper::class, 'bill_attribute_value_l11n', $request->getOrigin());
$this->createStandardDeleteResponse($request, $response, $billAttributeValueL11n);
diff --git a/Controller/ApiBillController.php b/Controller/ApiBillController.php
index dde98b7..3d3dab5 100755
--- a/Controller/ApiBillController.php
+++ b/Controller/ApiBillController.php
@@ -38,6 +38,7 @@ use Modules\Messages\Models\EmailMapper;
use Modules\SupplierManagement\Models\NullSupplier;
use Modules\SupplierManagement\Models\Supplier;
use Modules\SupplierManagement\Models\SupplierMapper;
+use phpOMS\Application\ApplicationAbstract;
use phpOMS\Autoloader;
use phpOMS\Localization\ISO4217CharEnum;
use phpOMS\Localization\ISO639x1Enum;
@@ -60,6 +61,22 @@ use phpOMS\Views\View;
*/
final class ApiBillController extends Controller
{
+ /**
+ * Constructor.
+ *
+ * @param null|ApplicationAbstract $app Application instance
+ *
+ * @since 1.0.0
+ */
+ public function __construct(ApplicationAbstract $app = null)
+ {
+ parent::__construct($app);
+
+ if ($this->app->moduleManager->isActive('WarehouseManagement')) {
+ $this->app->eventManager->importFromFile(__DIR__ . '/../../WarehouseManagement/Admin/Hooks/Manual.php');
+ }
+ }
+
/**
* Api method to update a bill
*
diff --git a/Controller/ApiBillTypeController.php b/Controller/ApiBillTypeController.php
index 9592a7a..1ff5d25 100755
--- a/Controller/ApiBillTypeController.php
+++ b/Controller/ApiBillTypeController.php
@@ -397,7 +397,7 @@ final class ApiBillTypeController extends Controller
return;
}
- /** @var \Modules\Billing\Models\BillTypeL11n $billTypeL11n */
+ /** @var BaseStringL11n $billTypeL11n */
$billTypeL11n = BillTypeL11nMapper::get()->where('id', (int) $request->getData('id'))->execute();
$this->deleteModel($request->header->account, $billTypeL11n, BillTypeL11nMapper::class, 'bill_type_l11n', $request->getOrigin());
$this->createStandardDeleteResponse($request, $response, $billTypeL11n);
diff --git a/Controller/ApiPriceController.php b/Controller/ApiPriceController.php
index c0d4331..a6fec08 100755
--- a/Controller/ApiPriceController.php
+++ b/Controller/ApiPriceController.php
@@ -355,7 +355,10 @@ final class ApiPriceController extends Controller
*/
public function updatePriceFromRequest(RequestAbstract $request, Price $new) : Price
{
- $new->name = $new->name !== 'base' && $request->hasData('name') ? $request->getDataString('name') : $new->name;
+ $new->name = $new->name !== 'base'
+ ? ($request->getDataString('name') ?? $new->name)
+ : $new->name;
+
$new->promocode = $request->getDataString('promocode') ?? $new->promocode;
$new->item = $request->hasData('item') ? new NullItem((int) $request->getData('item')) : $new->item;
diff --git a/Controller/ApiTaxController.php b/Controller/ApiTaxController.php
index 40120fc..d657891 100755
--- a/Controller/ApiTaxController.php
+++ b/Controller/ApiTaxController.php
@@ -280,14 +280,16 @@ final class ApiTaxController extends Controller
return;
}
+ /** @var array $combinations */
$combinations = \json_decode(\file_get_contents($path), true);
foreach ($combinations as $combination) {
+ /** @var TaxCombination[] $old */
$old = TaxCombinationMapper::getAll()
->with('clientCode')
->with('itemCode')
- ->where('clientCode/valueStr', $combination['account_code'])
- ->where('itemCode/valueStr', $combination['item_code'])
+ ->where('clientCode/valueStr', $combination['account_code'] ?? '')
+ ->where('itemCode/valueStr', $combination['item_code'] ?? '')
->execute();
if (\count($old) !== 1) {
@@ -297,7 +299,7 @@ final class ApiTaxController extends Controller
$old = \reset($old);
$new = clone $old;
- $new->taxCode = $combination['tax_code'];
+ $new->taxCode = $combination['tax_code'] ?? '';
$this->updateModel($request->header->account, $old, $new, TaxCombinationMapper::class, 'tax_combination', $request->getOrigin());
}
@@ -390,7 +392,7 @@ final class ApiTaxController extends Controller
return;
}
- /** @var \Modules\Billing\Models\TaxCombination $taxCombination */
+ /** @var \Modules\Billing\Models\Tax\TaxCombination $taxCombination */
$taxCombination = TaxCombinationMapper::get()->where('id', (int) $request->getData('id'))->execute();
$this->deleteModel($request->header->account, $taxCombination, TaxCombinationMapper::class, 'tax_combination', $request->getOrigin());
$this->createStandardDeleteResponse($request, $response, $taxCombination);
diff --git a/Controller/CliController.php b/Controller/CliController.php
index be94812..66bbbe9 100755
--- a/Controller/CliController.php
+++ b/Controller/CliController.php
@@ -404,10 +404,12 @@ final class CliController extends Controller
private function parseDate(string $date, Supplier $supplier, array $formats) : ?\DateTime
{
if ((!empty($supplier->getAttribute('bill_date_format')->value->valueStr))) {
- return \DateTime::createFromFormat(
+ $dt = \DateTime::createFromFormat(
$supplier->getAttribute('bill_date_format')->value->valueStr ?? '',
$date
- ) ?? new \DateTime('1970-01-01');
+ );
+
+ return $dt === false ? new \DateTime('1970-01-01') : $dt;
}
foreach ($formats as $format) {
diff --git a/Models/Bill.php b/Models/Bill.php
index 513a7a4..867a4b6 100755
--- a/Models/Bill.php
+++ b/Models/Bill.php
@@ -424,7 +424,7 @@ class Bill implements \JsonSerializable
* @var BillElement[]
* @since 1.0.0
*/
- private array $elements = [];
+ public array $elements = [];
/**
* Reference to other Bill (delivery note/credit note etc).
diff --git a/Models/BillType.php b/Models/BillType.php
index 3927936..ecf20f6 100755
--- a/Models/BillType.php
+++ b/Models/BillType.php
@@ -50,6 +50,8 @@ class BillType implements \JsonSerializable
public bool $transferStock = true;
+ public int $sign = 1;
+
/**
* Localization
*
diff --git a/Models/BillTypeMapper.php b/Models/BillTypeMapper.php
index a42dcc6..433bbc6 100755
--- a/Models/BillTypeMapper.php
+++ b/Models/BillTypeMapper.php
@@ -44,6 +44,7 @@ final class BillTypeMapper extends DataMapperFactory
'billing_type_transfer_type' => ['name' => 'billing_type_transfer_type', 'type' => 'int', 'internal' => 'transferType'],
'billing_type_default_template' => ['name' => 'billing_type_default_template', 'type' => 'int', 'internal' => 'defaultTemplate'],
'billing_type_transfer_stock' => ['name' => 'billing_type_transfer_stock', 'type' => 'bool', 'internal' => 'transferStock'],
+ 'billing_type_sign' => ['name' => 'billing_type_sign', 'type' => 'bool', 'internal' => 'sign'],
'billing_type_is_template' => ['name' => 'billing_type_is_template', 'type' => 'bool', 'internal' => 'isTemplate'],
];
diff --git a/Models/itemcategoryidentifier.json b/Models/itemcategoryidentifier.json
new file mode 100644
index 0000000..d2b3eaf
--- /dev/null
+++ b/Models/itemcategoryidentifier.json
@@ -0,0 +1,107 @@
+{
+ "office_supplies": {
+ "en": [
+ "office supplies", "pencil", "pen", "notepad", "note", "highlighter",
+ "eraser", "paperclip", "binder clip", "staples", "stapler", "tape dispenser",
+ "scotch tape", "rubber bands", "marker", "whiteboard marker",
+ "whiteboard eraser", "desk organizer", "calendar", "desk calendar",
+ "file folder", "folder", "hanging file folder", "envelope", "stamp",
+ "scissor", "calculator", "ruler", "trash can", "recycling bin",
+ "cabinet labels", "paper towels", "cleaning supplies", "sticky tack",
+ "adhesive putty", "wall calendar"
+ ],
+ "de": []
+ },
+ "it_supplies": {
+ "en": [
+ "keyboard", "mouse", "mice", "USB drive", "network cable", "toner",
+ "printer paper", "ink", "cartridge"
+ ],
+ "de": []
+ },
+ "it_equipment": {
+ "en": [
+ "PC", "computer", "laptop", "monitor", "switch", "psu", "server", "printer",
+ "router", "webcam", "headset", "hard drive", "microphone", "macbook", "phone",
+ "cellphone", "mobile phone"
+ ],
+ "de": []
+ },
+ "internet_phone": {
+ "en": [
+ "domain", "website", "web server", "phone", "internet", "cellphone"
+ ],
+ "de": []
+ },
+ "furniture": {
+ "en": [
+ "sofa", "armchair", "table", "chair", "bed", "nightstand", "dresser", "wardrobe",
+ "bookshelf", "desk", "cabinet", "couch", "recliner", "tv stand", "kitchen island",
+ "barstool", "bathroom vanity", "dining room hutch", "chest of drawers",
+ "bench", "credenza", "sideboard", "ottoman", "headboard", "footboard",
+ "chaise lounge", "patio furniture", "outdoor dining set", "hammock",
+ "bean bag", "stool", "cubby storage", "shoe rack", "coat rack", "futon",
+ "crib", "playpen"
+ ],
+ "de": []
+ },
+ "appliances": {
+ "en": [
+ "refrigerator", "oven", "stove", "microwave", "dishwasher", "washing machine",
+ "clothes dryer", "freezer", "coffee maker", "toaster", "blender",
+ "food processor", "kettle", "rice cooker", "slow cooker",
+ "toaster oven", "air conditioner", "heater", "ceiling fan", "vacuum cleaner",
+ "iron", "hair dryer", "curling iron", "shaver",
+ "air purifier", "dehumidifier", "humidifier", "garbage disposal",
+ "trash compactor", "range hood", "juicer", "mixer", "grill",
+ "bread maker", "ice maker", "water dispenser", "ductless mini-split system",
+ "wall oven", "induction cooktop", "espresso machine", "can opener",
+ "portable air conditioner", "hot water dispenser", "skillet",
+ "popcorn maker", "margarita machine", "deep fryer", "griddle", "scale"
+ ],
+ "de": []
+ },
+ "cleaning": {
+ "en": [
+ "broom", "mop", "dustpan", "bucket", "sponge", "scrub brush", "cloth",
+ "paper towels", "trash bags", "trash can", "vacuum cleaner",
+ "carpet cleaner", "glass cleaner", "cleaner", "disinfectant wipes",
+ "toilet brush", "toilet bowl cleaner", "bathroom cleaner", "tile cleaner",
+ "oven cleaner", "dishwashing liquid", "detergent", "fabric softener",
+ "stain remover", "trash can liners", "baking soda", "vinegar",
+ "dust mask", "cleaning caddy", "window squeegee", "feather duster",
+ "lint roller", "air freshener", "gloves", "degreaser", "floor wax",
+ "furniture polish", "shoe polish", "stainless steel cleaner", "rust remover",
+ "grill brush", "lime scale remover", "rug cleaner", "furniture stain remover"
+ ],
+ "de": []
+ },
+ "marketing": {
+ "en": [
+ "flyer", "brochure", "article", "trade fair", "exhibition", "trade show",
+ "advertising", "social media", "market research", "marketing", "catalogue",
+ "catalog", "price list"
+ ],
+ "de": []
+ },
+ "food": {
+ "en": [
+ "wine", "beer", "schnaps", "water", "cola", "fanta", "juice", "sprite", "coffe",
+ "cake", "ice cream", "pudding", "donut",
+ "nudle", "steak", "fish", "salat", "burger", "fries", "potato", "soup"
+ ],
+ "de": []
+ },
+ "hotel": {
+ "en": [
+ "hotel", "motel", "hostel"
+ ],
+ "de": []
+ },
+ "travel": {
+ "en": [
+ "flight", "taxi", "train", "uber", "parking"
+ ],
+ "de": []
+ }
+}
\ No newline at end of file