#include "record.h"
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include "stringtokenizer.h"
#include <dirent.h>
#include <stddef.h>
#include "datahandler.h"
#include <math.h>
#include "period.h"
#include "attributes.h"
const CStrings * const Record::m_strEmptyString = new CStrings;
Record::Record(DataHandler *pDataHandler)
{
m_pDataHandler = pDataHandler;
m_nChanged = 0;
m_nDeleted = 0;
}
Record::~Record()
{
}
const Id &Record::getId() const
{
return m_id;
}
int Record::remove()
{
m_nDeleted = 1;
detachParent();
}
const char *Record::getTypeString() const
{
return TYPE_NAMES[getType()];
}
// int Record::changed() const
// {
// return (m_nChanged || m_nDeleted);
// }
int Record::setChanged(int nChanged)
{
m_nChanged = nChanged;
return nChanged;
}
int Record::setDeleted(int nDeleted)
{
m_nDeleted = nDeleted;
return nDeleted;
}
// recursivelyDelete is used in order to delete the data directory of a record
// since data directories might not always be under Subversion control in Windows,
// wen need to do a simple delete under windows
int Record::recursivelyDelete(const char *strPath) const
{
#ifdef __CYGWIN__
CStrings path = strPath;
system("rm -rf '"+path+"'");
return 1;
#else
return m_pDataHandler->unlink(strPath);
#endif
}
CStrings Record::decode(const char *strData) const
{
CStrings data(strData);
return data.decodeBase64();
}
CStrings Record::encode(const char *strData) const
{
CStrings data(strData);
return data.encodeBase64();
}
void Record::createID()
{
/*uuid_t out;
uuid_generate(out);
char buffer[36];
uuid_unparse_lower(out, buffer);
uuid_clear(out);
m_strId = buffer;*/
m_id.generate();
setChanged(1);
}
// int Record::deleted() const
// {
// return m_nDeleted;
// }
int Record::validId() const
{
/*uuid_t uu;
CStrings strId = getId();
if (!uuid_parse((char *)(const char *)strId, uu)) {
return 1;
}*/
if (m_id.isValid()) {
return 1;
}
return 0;
}
double Record::computePrice(int nNetPrice) const
{
return 0.;
}
double Record::computeDiscount(int nNetPrice) const
{
return 0.;
}
double Record::computeDiscountPercent() const
{
return 0.;
}
double Record::computeVat() const
{
return 0.;
}
Record *Record::createSuccessor() const
{
return NULL;
}
int Record::isHot() const
{
return 0;
}
bool Record::isActive() const
{
//return true;
if (value(FIELD_STATE) == "inactive") {
return false;
}
return true;
}
void Record::applyDefaultValues()
{
}
CStrings Record::sortString() const
{
CStrings strSort;
return strSort;
}
int Record::isDeleteable() const
{
return 1;
}
int Record::operator==(const Record &record) const
{
/*if (!strcmp(record.getId(), getId())) {
return 1;
}*/
if (record.getId() == getId()) {
return 1;
}
return 0;
}
bool Record::invalid() const
{
// check the type
if (getType() < 1 || getType() > TYPE_MAX) {
return true;
}
// check the encoding
for (int i = 0; i < numberKeys(); i++) {
int nKey = key(i);
CStrings strValue = valueByIndex(i);
if (strValue.length() > 0) {
if (strValue.check_utf8() > 0) {
return true;
}
}
}
// check the id
/*if (strlen(getId()) == 0 || !validId()) {
return true;
}*/
if (!getId().isValid()) {
return true;
}
return false;
}
void Record::setId(const CStrings &strId)
{
m_id = strId;
}
void Record::adjustDueDate()
{
// if this record has attributes duedate and date, and if duedate <= date, set duedate to date+1
CStrings strDate = value(FIELD_DATE);
if (strDate.length() > 0) {
CStrings strDueDate = value(FIELD_DUEDATE);
if (strDueDate.length() > 0) {
Period date(strDate);
Period duedate(strDueDate);
if (duedate <= date) {
date += 1;
set(FIELD_DUEDATE, (const CStrings &)date);
}
}
}
}
CStrings Record::internalEvaluate(const char *strAttribute) const
{
CStrings strResult;
int nField = getDataHandler()->getFieldId(strAttribute);
if (nField >= 0) {
strResult = value(nField);
}
return strResult;
}
/*
* evaluate() works much like value(), but it will resolve special attribute names like id and type and will
* also resolve document syntax (dokument::name and such)
*/
CStrings Record::evaluate(const char *strAttribute) const
{
CStrings strResult;
if (!strcmp(strAttribute, "id")) {
strResult = getId();
}
else if (!strcmp(strAttribute, "type")) {
strResult = getTypeString();
}
else {
strResult = internalEvaluate(strAttribute);
if (strResult.length() == 0) {
Record *pParent = getParent();
if (pParent != NULL) {
strResult = pParent->evaluate(strAttribute);
}
}
}
return strResult;
}
bool Record::isNumericAttribute(const char *strAttribute) const
{
CStrings attr = strAttribute;
CStrings dokument = ATTR_DOKUMENT;
if (attr == "rate"
|| attr == "price"
|| attr == "vat"
|| attr == "amount"
|| attr == "percent"
|| attr == "amountleft"
|| attr == "renewalamount"
|| attr == "renewalprice"
|| attr == dokument+ATTR_BRUTTOTOTAL
|| attr == dokument+ATTR_MWST
|| attr == dokument+ATTR_RUNDUNG
|| attr == dokument+ATTR_NETTOTOTAL
|| attr == dokument+ATTR_TOTAL) {
return true;
}
return false;
}
bool Record::isDateAttribute(const char *strAttribute) const
{
CStrings attr = strAttribute;
if (attr == "date"
|| attr == "duedate"
|| attr == "dundate"
|| attr == "lastdate"
|| attr == "nextdate"
|| attr == "startdate"
|| attr == "enddate") {
return true;
}
return false;
}
int Record::compare(const char *strKey, const char *strValue) const
{
CStrings strData = evaluate(strKey);
//printf("Comparing %s <-> %s\n", (const char *)strData, strValue);
if (strData.length() == 0) {
if (strlen(strValue) == 0) {
return 0;
}
else {
return -1;
}
}
if (isNumericAttribute(strKey)) {
double d1 = atof(strData);
double d2 = atof(strValue);
double dDiff = d1-d2;
if (dDiff < -0.00001) {
return -1;
}
else if (dDiff > 0.00001) {
return 1;
}
else {
return 0;
}
}
else if (isDateAttribute(strKey)) {
//printf("Comparing date: %s <-> %s\n", (const char *)strData, strValue);
Period p1(strData);
Period p2(strValue);
if (p1 < p2) {
return -1;
}
else if (p1 > p2) {
return 1;
}
else {
return 0;
}
}
else {
return strcmp(strData, strValue);
}
}
void Record::attachParent()
{
}
void Record::detachParent()
{
}
double Record::doubleValue(unsigned int nField) const
{
CStrings strValue = value(nField);
if (strValue.length() == 0) {
return 0.;
}
return atof(strValue);
}
bool Record::matchesFilter(const CStrings &strFilter) const
{
if (strFilter == "all") {
return true;
}
return false;
}
bool Record::isUnbooked() const
{
return false;
}
Period Record::lastAction() const
{
Period today;
return today;
}
void Record::setIndex(unsigned int nIndex)
{
m_id.setIndex(getDataHandler(), (int)nIndex);
}
bool Record::matching(const CStrings &strMatch) const
{
return false;
}
int Record::getState() const
{
return STATE_NORMAL;
}