Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: Django CI

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
test:
runs-on: ubuntu-latest

services:
mysql:
image: mysql:8.0
env:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: imaps_test
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping -h localhost -ppassword"
--health-interval=10s
--health-timeout=5s
--health-retries=3

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python 3.12
uses: actions/setup-python@v4
with:
python-version: 3.12

- name: Install system deps for MySQL client
run: |
sudo apt-get update
sudo apt-get install -y default-libmysqlclient-dev build-essential

- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt

- name: Run migrations
env:
DB_HOST: 127.0.0.1
DB_PORT: 3306
DB_NAME: imaps
DB_USER: root
DB_PASS: password
run: |
python manage.py migrate --noinput

- name: Run tests
env:
DB_HOST: 127.0.0.1
DB_PORT: 3306
DB_NAME: imaps_test
DB_USER: root
DB_PASS: password
run: |
python manage.py test --verbosity=2
6 changes: 6 additions & 0 deletions IMAPS/IMAPS/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Ignore OS-generated files
.DS_Store
Thumbs.db
.env
# Ignore dependencies
venv/
2 changes: 2 additions & 0 deletions IMAPS/IMAPS/IMAPS/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import pymysql
pymysql.install_as_MySQLdb()
Binary file removed IMAPS/IMAPS/IMAPS/__pycache__/__init__.cpython-311.pyc
Binary file not shown.
Binary file modified IMAPS/IMAPS/IMAPS/__pycache__/__init__.cpython-312.pyc
Binary file not shown.
Binary file removed IMAPS/IMAPS/IMAPS/__pycache__/__init__.cpython-39.pyc
Binary file not shown.
Binary file not shown.
Binary file modified IMAPS/IMAPS/IMAPS/__pycache__/settings.cpython-312.pyc
Binary file not shown.
Binary file not shown.
Binary file removed IMAPS/IMAPS/IMAPS/__pycache__/urls.cpython-311.pyc
Binary file not shown.
Binary file modified IMAPS/IMAPS/IMAPS/__pycache__/urls.cpython-312.pyc
Binary file not shown.
Binary file removed IMAPS/IMAPS/IMAPS/__pycache__/urls.cpython-39.pyc
Binary file not shown.
Binary file removed IMAPS/IMAPS/IMAPS/__pycache__/wsgi.cpython-311.pyc
Binary file not shown.
Binary file modified IMAPS/IMAPS/IMAPS/__pycache__/wsgi.cpython-312.pyc
Binary file not shown.
Binary file removed IMAPS/IMAPS/IMAPS/__pycache__/wsgi.cpython-39.pyc
Binary file not shown.
22 changes: 11 additions & 11 deletions IMAPS/IMAPS/IMAPS/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"""

from pathlib import Path

import os
from dotenv import load_dotenv
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent

Expand Down Expand Up @@ -75,20 +76,19 @@
# https://docs.djangoproject.com/en/5.1/ref/settings/#databases

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'imaps', # Your DB name
'USER': 'root', # Your MySQL username
'PASSWORD': '1234', # Your MySQL password
'HOST': '127.0.0.1', # Use '127.0.0.1' instead of 'localhost'
'PORT': '3306', # Use 3306 if running a standard MySQL server
'OPTIONS': {
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"
}
"default": {
"ENGINE": os.getenv("DB_ENGINE", "django.db.backends.sqlite3"),
"NAME": os.getenv("DB_NAME", BASE_DIR / "db.sqlite3"),
"USER": os.getenv("DB_USER", ""),
"PASSWORD": os.getenv("DB_PASS", ""),
"HOST": os.getenv("DB_HOST", ""),
"PORT": os.getenv("DB_PORT", ""),
"OPTIONS": {"init_command": "SET sql_mode='STRICT_TRANS_TABLES'"},
}
}



# Password validation
# https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators

Expand Down
Binary file modified IMAPS/IMAPS/IMAPS_app/__pycache__/forms.cpython-312.pyc
Binary file not shown.
Binary file modified IMAPS/IMAPS/IMAPS_app/__pycache__/models.cpython-312.pyc
Binary file not shown.
Binary file modified IMAPS/IMAPS/IMAPS_app/__pycache__/views.cpython-312.pyc
Binary file not shown.
2 changes: 1 addition & 1 deletion IMAPS/IMAPS/IMAPS_app/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class SupplierForm(RequiredFieldsAsteriskMixin, forms.ModelForm):

class Meta:
model = Supplier
fields = '__all__'
exclude = ['change_status']

class IngredientsRawMaterialsForm(RequiredFieldsAsteriskMixin, forms.ModelForm):
UseCategory = forms.ChoiceField(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Generated by Django 5.1.6 on 2025-05-08 11:57

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('IMAPS_app', '0002_alter_ingredientsrawmaterials_cost_and_more'),
]

operations = [
migrations.AddField(
model_name='ingredientsrawmaterials',
name='change_status',
field=models.CharField(choices=[('active', 'Active'), ('old_modified', 'Old Modified'), ('new_modified', 'New Modified'), ('deleted', 'Deleted')], default='active', max_length=15),
),
migrations.AddField(
model_name='packagingrawmaterials',
name='change_status',
field=models.CharField(choices=[('active', 'Active'), ('old_modified', 'Old Modified'), ('new_modified', 'New Modified'), ('deleted', 'Deleted')], default='active', max_length=15),
),
migrations.AddField(
model_name='supplier',
name='change_status',
field=models.CharField(choices=[('active', 'Active'), ('old_modified', 'Old Modified'), ('new_modified', 'New Modified'), ('deleted', 'Deleted')], default='active', max_length=15),
),
migrations.AddField(
model_name='usedingredient',
name='change_status',
field=models.CharField(choices=[('active', 'Active'), ('old_modified', 'Old Modified'), ('new_modified', 'New Modified'), ('deleted', 'Deleted')], default='active', max_length=15),
),
migrations.AddField(
model_name='usedpackaging',
name='change_status',
field=models.CharField(choices=[('active', 'Active'), ('old_modified', 'Old Modified'), ('new_modified', 'New Modified'), ('deleted', 'Deleted')], default='active', max_length=15),
),
migrations.AlterField(
model_name='supplier',
name='SupplierCode',
field=models.CharField(max_length=50, primary_key=True, serialize=False),
),
]
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
69 changes: 22 additions & 47 deletions IMAPS/IMAPS/IMAPS_app/models.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
# Updated models.py with change_status logic
import random
import string
from datetime import date, timedelta
from django.db import models

CHANGE_STATUS_CHOICES = [
("active", "Active"),
("old_modified", "Old Modified"),
("new_modified", "New Modified"),
("deleted", "Deleted"),
]

# -------------------- Supplier --------------------
class Supplier(models.Model):
SupplierCode = models.CharField(
max_length=50,
primary_key=True,
help_text="Unique identifier for the supplier (manually given)."
)
SupplierCode = models.CharField(max_length=50, primary_key=True)
SupplierName = models.CharField(max_length=255)
CATEGORY_CHOICES = [
('Ingredient', 'Ingredient'),
Expand All @@ -21,6 +25,7 @@ class Supplier(models.Model):
EmailAddress = models.CharField(max_length=320, blank=True, null=True)
ContactNumber = models.CharField(max_length=18, blank=True, null=True)
PointPerson = models.CharField(max_length=255, blank=True, null=True)
change_status = models.CharField(max_length=15, choices=CHANGE_STATUS_CHOICES, default="active")

def __str__(self):
return f"{self.SupplierName} ({self.SupplierCode})"
Expand All @@ -30,27 +35,19 @@ def __str__(self):
class IngredientsRawMaterials(models.Model):
id = models.AutoField(primary_key=True)
RawMaterialBatchCode = models.CharField(max_length=50, unique=True, blank=True)
SupplierCode = models.ForeignKey(
Supplier,
on_delete=models.CASCADE,
db_column='SupplierCode'
)
SupplierCode = models.ForeignKey(Supplier, on_delete=models.CASCADE, db_column='SupplierCode')
RawMaterialName = models.CharField(max_length=255)
DateDelivered = models.DateField()
QuantityBought = models.FloatField(default=0)
QuantityLeft = models.FloatField(default=0)
USECATEGORY_CHOICES = [
('WBC', 'WBC'),
('GGB', 'GGB'),
('Both', 'Both'),
]
USECATEGORY_CHOICES = [('WBC', 'WBC'), ('GGB', 'GGB'), ('Both', 'Both')]
UseCategory = models.CharField(max_length=10, choices=USECATEGORY_CHOICES, default="GGB")
ExpirationDate = models.DateField()
Status = models.CharField(max_length=15, blank=True)
Cost = models.FloatField(default=0, blank=True, null=True)
change_status = models.CharField(max_length=15, choices=CHANGE_STATUS_CHOICES, default="active")

def save(self, *args, **kwargs):
# Determine if we need to regenerate batch code
regenerate = False
if not self.pk:
regenerate = True
Expand All @@ -68,7 +65,6 @@ def save(self, *args, **kwargs):
if self.QuantityLeft == 0:
self.QuantityLeft = self.QuantityBought

# Auto-compute Status
today = date.today()
if self.ExpirationDate and self.ExpirationDate <= today + timedelta(days=30):
self.Status = "Expiring"
Expand All @@ -87,24 +83,17 @@ def __str__(self):
class PackagingRawMaterials(models.Model):
id = models.AutoField(primary_key=True)
PackagingBatchCode = models.CharField(max_length=50, unique=True, blank=True)
SupplierCode = models.ForeignKey(
Supplier,
on_delete=models.CASCADE,
db_column='SupplierCode'
)
SupplierCode = models.ForeignKey(Supplier, on_delete=models.CASCADE, db_column='SupplierCode')
RawMaterialName = models.CharField(max_length=255)
QuantityBought = models.IntegerField(default=0)
QuantityLeft = models.IntegerField(default=0)
USECATEGORY_CHOICES = [
('WBC', 'WBC'),
('GGB', 'GGB'),
('Both', 'Both'),
]
USECATEGORY_CHOICES = [('WBC', 'WBC'), ('GGB', 'GGB'), ('Both', 'Both')]
UseCategory = models.CharField(max_length=10, choices=USECATEGORY_CHOICES)
Status = models.CharField(max_length=15, blank=True)
Cost = models.FloatField(default=0, blank=True, null=True)
ContainerSize = models.CharField(max_length=50, blank=True, null=True)
DateDelivered = models.DateField()
change_status = models.CharField(max_length=15, choices=CHANGE_STATUS_CHOICES, default="active")

def save(self, *args, **kwargs):
regenerate = False
Expand Down Expand Up @@ -139,20 +128,13 @@ def __str__(self):
# -------------------- UsedIngredient --------------------
class UsedIngredient(models.Model):
UsedIngredientBatchCode = models.CharField(max_length=50, primary_key=True, blank=True)
IngredientRawMaterialBatchCode = models.ForeignKey(
IngredientsRawMaterials,
on_delete=models.CASCADE,
db_column='RawMaterialBatchCode'
)
IngredientRawMaterialBatchCode = models.ForeignKey(IngredientsRawMaterials, on_delete=models.CASCADE, db_column='RawMaterialBatchCode')
RawMaterialName = models.CharField(max_length=255)
QuantityUsed = models.IntegerField()
USECATEGORY_CHOICES = [
('WBC', 'WBC'),
('GGB', 'GGB'),
('Both', 'Both'),
]
USECATEGORY_CHOICES = [('WBC', 'WBC'), ('GGB', 'GGB'), ('Both', 'Both')]
UseCategory = models.CharField(max_length=10, choices=USECATEGORY_CHOICES)
DateUsed = models.DateField()
change_status = models.CharField(max_length=15, choices=CHANGE_STATUS_CHOICES, default="active")

def save(self, *args, **kwargs):
if not self.UsedIngredientBatchCode:
Expand All @@ -170,20 +152,13 @@ def __str__(self):
# -------------------- UsedPackaging --------------------
class UsedPackaging(models.Model):
USEDPackagingBatchCode = models.CharField(max_length=50, primary_key=True, blank=True)
PackagingRawMaterialBatchCode = models.ForeignKey(
PackagingRawMaterials,
on_delete=models.CASCADE,
db_column='PackagingBatchCode'
)
PackagingRawMaterialBatchCode = models.ForeignKey(PackagingRawMaterials, on_delete=models.CASCADE, db_column='PackagingBatchCode')
RawMaterialName = models.CharField(max_length=255)
QuantityUsed = models.IntegerField()
USECATEGORY_CHOICES = [
('WBC', 'WBC'),
('GGB', 'GGB'),
('Both', 'Both'),
]
USECATEGORY_CHOICES = [('WBC', 'WBC'), ('GGB', 'GGB'), ('Both', 'Both')]
UseCategory = models.CharField(max_length=10, choices=USECATEGORY_CHOICES)
DateUsed = models.DateField()
change_status = models.CharField(max_length=15, choices=CHANGE_STATUS_CHOICES, default="active")

def save(self, *args, **kwargs):
if not self.USEDPackagingBatchCode:
Expand Down
Loading